Browse Source

Edit Organization and New Organization creation pages

pull/41/head
Berkan Sasmaz 6 years ago
parent
commit
c6fc137ef9
  1. 22
      src/EventHub.Application.Contracts/Organizations/CreateOrganizationDto.cs
  2. 14
      src/EventHub.Application/Organizations/OrganizationAppService.cs
  3. 13
      src/EventHub.Domain.Shared/Organizations/OrganizationContst.cs
  4. 14
      src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml
  5. 4
      src/EventHub.Web.Theme/Themes/EventHub/Components/MainNavbar/Default.cshtml
  6. 83
      src/EventHub.Web/Pages/Organizations/Index.cshtml
  7. 107
      src/EventHub.Web/Pages/Organizations/New.cshtml
  8. 43
      src/EventHub.Web/Pages/Organizations/New.cshtml.cs
  9. 56
      src/EventHub.Web/Pages/Organizations/New.js

22
src/EventHub.Application.Contracts/Organizations/CreateOrganizationDto.cs

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using JetBrains.Annotations;
namespace EventHub.Organizations
{
@ -15,5 +16,26 @@ namespace EventHub.Organizations
[Required]
[StringLength(OrganizationConsts.MaxDescriptionNameLength, MinimumLength = OrganizationConsts.MinDescriptionNameLength)]
public string Description { get; set; }
[CanBeNull]
public byte[] ProfilePictureContent { get; set; }
[StringLength(OrganizationConsts.MaxWebsiteLength)]
public string Website { get; set; }
[StringLength(OrganizationConsts.MaxTwitterUsernameLength)]
public string TwitterUsername { get; set; }
[StringLength(OrganizationConsts.MaxGitHubUsernameLength)]
public string GitHubUsername { get; set; }
[StringLength(OrganizationConsts.MaxFacebookUsernameLength)]
public string FacebookUsername { get; set; }
[StringLength(OrganizationConsts.MaxInstagramUsernameLength)]
public string InstagramUsername { get; set; }
[StringLength(OrganizationConsts.MaxMediumUsernameLength)]
public string MediumUsername { get; set; }
}
}

14
src/EventHub.Application/Organizations/OrganizationAppService.cs

@ -37,7 +37,19 @@ namespace EventHub.Organizations
input.Description
);
await _organizationRepository.InsertAsync(organization);
organization.Website = input.Website;
organization.TwitterUsername = input.TwitterUsername;
organization.GitHubUsername = input.GitHubUsername;
organization.FacebookUsername = input.FacebookUsername;
organization.InstagramUsername = input.InstagramUsername;
organization.MediumUsername = input.MediumUsername;
await _organizationRepository.InsertAsync(organization, true);
if (input.ProfilePictureContent != null && input.ProfilePictureContent.Length > 0)
{
await SaveProfilePictureAsync(organization.Id, input.ProfilePictureContent);
}
}
public async Task<PagedResultDto<OrganizationInListDto>> GetListAsync(PagedResultRequestDto input)

13
src/EventHub.Domain.Shared/Organizations/OrganizationContst.cs

@ -12,5 +12,18 @@
public const int MaxDescriptionNameLength = 1000;
public const int MaxProfilePictureFileSize = 1024 * 1024; //1MB
public const int MaxWebsiteLength = 512;
public const int MaxTwitterUsernameLength = 24;
public const int MaxGitHubUsernameLength = 24;
public const int MaxFacebookUsernameLength = 24;
public const int MaxInstagramUsernameLength = 24;
public const int MaxMediumUsernameLength = 24;
}
}

14
src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml

@ -3,7 +3,7 @@
@using Volo.Abp.Users
@inject ICurrentUser CurrentUser
<footer>
<footer class="mt-2">
<div class="container">
<div class="row">
<div class="col-md">
@ -34,19 +34,19 @@
@* ToDo: Social platform links *@
<div class="footer-links">
<a href="#">
<img src="assets/facebook.svg">
<img src="/assets/facebook.svg">
</a>
<a href="#">
<img src="assets/twitter.svg">
<img src="/assets/twitter.svg">
</a>
<a href="#">
<img src="assets/in.svg">
<img src="/assets/in.svg">
</a>
<a href="#">
<img src="assets/you.svg">
<img src="/assets/you.svg">
</a>
<a href="#">
<img src="assets/google.svg">
<img src="/assets/google.svg">
</a>
</div>
</div>
@ -65,7 +65,7 @@
Terms of Service
</a>
<span>
<img src="assets/seperator2.svg" class="mx-3">
<img src="/assets/seperator2.svg" class="mx-3">
</span>
<a href="@Url.Page("/PrivacyPolicy")">
@* ToDo: The content of the page will be edited *@

4
src/EventHub.Web.Theme/Themes/EventHub/Components/MainNavbar/Default.cshtml

@ -39,8 +39,7 @@
@* ToDo: Emoji or Gravatar? *@
@if (!string.IsNullOrWhiteSpace(CurrentUser.Name) && !string.IsNullOrWhiteSpace(CurrentUser.SurName))
{
{@CurrentUser.Name}
{@CurrentUser.SurName}
@(CurrentUser.Name + " " + CurrentUser.SurName)
}
else
{
@ -59,6 +58,7 @@
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
@* ToDo: Write language specific code find solution here (if block) *@
@if (CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "en")
{
<span class="flag-icon flag-icon flag-icon-gb" data-toggle="tooltip" title="" data-original-title="@CultureInfo.CurrentUICulture.DisplayName"></span>

83
src/EventHub.Web/Pages/Organizations/Index.cshtml

@ -4,27 +4,62 @@
@using Microsoft.AspNetCore.Mvc.Localization
@model EventHub.Web.Pages.Organizations.IndexPageModel
<abp-row>
@foreach (var organization in Model.Organizations)
{
<abp-column size-lg="_4" size-md="_6">
<abp-card class="mb-3">
@if (organization.ProfilePictureContent == null)
{
<img abp-card-image="Top" style="max-height: 200px; min-height: 150px;" src="https://picsum.photos/seed/@organization.Name/400/160?blur=8" alt="@organization.DisplayName"/>
}
else
{
<img abp-card-image="Top" style="max-height: 200px; min-height: 150px;" src="@($"data:image/png;base64,{Convert.ToBase64String(organization.ProfilePictureContent)}")" alt="@organization.DisplayName"/>
}
<abp-card-body>
<abp-card-title>@organization.DisplayName</abp-card-title>
<abp-card-text>
@organization.Description.TruncateWithPostfix(100)
</abp-card-text>
<a abp-button="Primary" href="@Url.Page("/Organizations/Profile", new {name = organization.Name})"> @L["SeeOrganization"]</a>
</abp-card-body>
</abp-card>
</abp-column>
}
</abp-row>
<div class="container-fluid p-0">
<div class="inner-banner inner-banner-2">
<div class="container">
<div class="row align-items-center" style="min-height: 250px;">
<div class="col">
<h1>Organizations</h1>
<nav aria-label="breadcrumb" class="breadcrumb-container">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="@Url.Page("/Index")">Home</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Organizations</li>
</ol>
</nav>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
@foreach (var organization in Model.Organizations)
{
<div class="col-lg-4 col-md-6">
<div class="card">
@if (organization.ProfilePictureContent == null)
{
<img src="assets/card-img.png" class="card-img-top" alt="@organization.Name">
}
else
{
<img src="@($"data:image/png;base64,{Convert.ToBase64String(organization.ProfilePictureContent)}")" class="card-img-top" alt="@organization.Name">
}
<div class="card-body">
<div class="event-container">
<div class="event-info">
<h5>@organization.DisplayName</h5>
<p>
@organization.Description
</p>
</div>
<a href="@Url.Page("/Organizations/Profile", new {name = organization.Name})" class="btn btn-link p-0">Details <img src="assets/more-btn.svg"></a>
</div>
</div>
</div>
</div>
}
</div>
<div class="row">
<div class="col text-center">
<button class="btn btn-secondary btn-lg ">
Load More
</button>
</div>
</div>
</div>

107
src/EventHub.Web/Pages/Organizations/New.cshtml

@ -1,7 +1,110 @@
@page "/organizations/new"
@inject IHtmlLocalizer<EventHubResource> L
@using EventHub.Localization
@using EventHub.Organizations
@using Microsoft.AspNetCore.Mvc.Localization
@model EventHub.Web.Pages.Organizations.NewPageModel
<h1>@L["NewOrganization"]</h1>
<abp-dynamic-form abp-model="Organization" submit-button="true" />
@section scripts {
<abp-script-bundle>
<abp-script src="/Pages/Organizations/New.js"/>
</abp-script-bundle>
}
<div class="container pt-4">
<div class="row py-4">
<div class="col-md-9 mx-auto profile-content">
<div class="card">
<div class="card-body" style="min-height: 496px">
<h3 class="mb-4">Create New Organization</h3>
<form method="post" enctype="multipart/form-data">
<div class="form">
<div class="row">
<div class="col-md-12">
<h4 class="mb-4">Profile Image</h4>
<div class="row">
<div class="col-4">
<div class="image-area">
<img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block">
</div>
</div>
<div class="col-8">
<div>
<p class="mb-3">Photo size should be <span class="text-primary">max @(OrganizationConsts.MaxProfilePictureFileSize / (1024 * 1024)) MB.</span></p>
<input type="file" id="Organization_ProfilePictureFile" asp-for="Organization.ProfilePictureFile" class="form-control border-0" hidden>
<label id="upload-label" for="Organization_ProfilePictureFile" class="btn btn-primary btn-lg text-white">Upload</label>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputName" asp-for="Organization.Name" class="form-control" placeholder="Name *" required="">
<label for="inputName">Name*</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputDisplayname" asp-for="Organization.DisplayName" class="form-control" placeholder="Display Name*" required="">
<label for="inputDisplayname">Display Name*</label>
</div>
</div>
<div class="col-md-12">
<div class="form-label-group">
<input type="text" id="inputDescription" asp-for="Organization.Description" class="form-control" placeholder="Description*" required="">
<label for="inputDescription">Description*</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputWebsite" class="form-control" asp-for="Organization.Website" placeholder="Website">
<label for="inputWebsite">Website</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputTwitterusername" asp-for="Organization.TwitterUsername" class="form-control" placeholder="Twitter Username">
<label for="inputTwitterusername">Twitter Username</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputGitHubusername" asp-for="Organization.GitHubUsername" class="form-control" placeholder="GitHub Username">
<label for="inputGitHubusername">GitHub Username</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputFacebookusername" asp-for="Organization.FacebookUsername" class="form-control" placeholder="Facebook Username">
<label for="inputFacebookusername">Facebook Username</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputInstagramusername" asp-for="Organization.InstagramUsername" class="form-control" placeholder="Instagram Username">
<label for="inputInstagramusername">Instagram Username</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputMediumusername" asp-for="Organization.MediumUsername" class="form-control" placeholder="Medium Username">
<label for="inputMediumusername">Medium Username</label>
</div>
</div>
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary btn-lg">
Submit Organization
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

43
src/EventHub.Web/Pages/Organizations/New.cshtml.cs

@ -1,8 +1,12 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Threading.Tasks;
using EventHub.Organizations;
using EventHub.Web.Helpers;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
@ -11,8 +15,7 @@ namespace EventHub.Web.Pages.Organizations
[Authorize]
public class NewPageModel : EventHubPageModel
{
[BindProperty]
public CreateOrganizationViewModel Organization { get; set; }
[BindProperty] public CreateOrganizationViewModel Organization { get; set; }
private readonly IOrganizationAppService _organizationAppService;
@ -33,6 +36,16 @@ namespace EventHub.Web.Pages.Organizations
ValidateModel();
var input = ObjectMapper.Map<CreateOrganizationViewModel, CreateOrganizationDto>(Organization);
if (Organization.ProfilePictureFile != null && Organization.ProfilePictureFile.Length > 0)
{
using (var memoryStream = new MemoryStream())
{
await Organization.ProfilePictureFile.CopyToAsync(memoryStream);
input.ProfilePictureContent = memoryStream.ToArray();
}
}
await _organizationAppService.CreateAsync(input);
return RedirectToPage("./Profile", new {name = Organization.Name});
@ -58,6 +71,30 @@ namespace EventHub.Web.Pages.Organizations
[StringLength(OrganizationConsts.MaxDescriptionNameLength, MinimumLength = OrganizationConsts.MinDescriptionNameLength)]
[TextArea]
public string Description { get; set; }
[CanBeNull]
[DataType(DataType.Upload)]
[MaxFileSize(OrganizationConsts.MaxProfilePictureFileSize)]
[AllowedExtensions(new string[] {".jpg", ".png", ".jpeg"})]
public IFormFile ProfilePictureFile { get; set; }
[StringLength(OrganizationConsts.MaxWebsiteLength)]
public string Website { get; set; }
[StringLength(OrganizationConsts.MaxTwitterUsernameLength)]
public string TwitterUsername { get; set; }
[StringLength(OrganizationConsts.MaxGitHubUsernameLength)]
public string GitHubUsername { get; set; }
[StringLength(OrganizationConsts.MaxFacebookUsernameLength)]
public string FacebookUsername { get; set; }
[StringLength(OrganizationConsts.MaxInstagramUsernameLength)]
public string InstagramUsername { get; set; }
[StringLength(OrganizationConsts.MaxMediumUsernameLength)]
public string MediumUsername { get; set; }
}
}
}
}

56
src/EventHub.Web/Pages/Organizations/New.js

@ -0,0 +1,56 @@
$(function () {
var l = abp.localization.getResource('EventHub');
var fileInput = document.getElementById('Organization_ProfilePictureFile');
var file;
fileInput.addEventListener('change', function () {
file = fileInput.files[0];
var permittedExtensions = ["jpg", "jpeg", "png"]
var fileExtension = $(this).val().split('.').pop();
if (permittedExtensions.indexOf(fileExtension) === -1) {
abp.message.error(l('OrganizationCoverImageExtensionNotAllowed'))
.then(() => {
$('#Organization_ProfilePictureFile').val('');
file = null;
});
} else if (file.size > 1024 * 1024) {
abp.message.error(l('OrganizationCoverImageSizeExceedMessage'))
.then(() => {
$('#Organization_ProfilePictureFile').val('');
file = null;
});
}
var img = new Image();
img.onload = function () {
var imageError = true;
var sizes = {
width: this.width,
height: this.height
};
URL.revokeObjectURL(this.src);
if (imageError) {
readURL(file);
}
}
var objectURL = URL.createObjectURL(file);
img.src = objectURL;
});
function readURL(input) {
if (input) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imageResult').attr('src', e.target.result);
}
reader.readAsDataURL(input);
}
}
});
Loading…
Cancel
Save