mirror of https://github.com/abpframework/eventhub
committed by
GitHub
26 changed files with 5732 additions and 2561 deletions
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace EventHub.Organizations |
|||
{ |
|||
[BlobContainerName("organization-profile-pictures")] |
|||
public class OrganizationProfilePictureContainer |
|||
{ |
|||
|
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,73 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace EventHub.Migrations |
|||
{ |
|||
public partial class Added_Blob_Database : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: "AbpBlobContainers", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpBlobContainers", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "AbpBlobs", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
ContainerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
|||
Content = table.Column<byte[]>(type: "varbinary(max)", maxLength: 2147483647, nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpBlobs", x => x.Id); |
|||
table.ForeignKey( |
|||
name: "FK_AbpBlobs_AbpBlobContainers_ContainerId", |
|||
column: x => x.ContainerId, |
|||
principalTable: "AbpBlobContainers", |
|||
principalColumn: "Id", |
|||
onDelete: ReferentialAction.Cascade); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpBlobContainers_TenantId_Name", |
|||
table: "AbpBlobContainers", |
|||
columns: new[] { "TenantId", "Name" }); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpBlobs_ContainerId", |
|||
table: "AbpBlobs", |
|||
column: "ContainerId"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpBlobs_TenantId_ContainerId_Name", |
|||
table: "AbpBlobs", |
|||
columns: new[] { "TenantId", "ContainerId", "Name" }); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "AbpBlobs"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: "AbpBlobContainers"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,40 @@ |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Organizations; |
|||
using EventHub.Web.Pages.Organizations; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace EventHub.Web.Controllers |
|||
{ |
|||
[Route("api/organization")] |
|||
public class OrganizationController : AbpController |
|||
{ |
|||
private readonly IOrganizationAppService _organizationAppService; |
|||
|
|||
public OrganizationController(IOrganizationAppService organizationAppService) |
|||
{ |
|||
_organizationAppService = organizationAppService; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Authorize] |
|||
[Route("save-profile-picture")] |
|||
public async Task SaveProfilePicture([FromForm] OrganizationProfilePictureInput input) |
|||
{ |
|||
byte[] profilePictureContent = new byte[] {}; |
|||
|
|||
if (input.ProfilePictureFile != null && input.ProfilePictureFile.Length > 0) |
|||
{ |
|||
using (var memoryStream = new MemoryStream()) |
|||
{ |
|||
await input.ProfilePictureFile.CopyToAsync(memoryStream); |
|||
profilePictureContent = memoryStream.ToArray(); |
|||
} |
|||
} |
|||
|
|||
await _organizationAppService.SaveProfilePictureAsync(input.OrganizationId, profilePictureContent); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Http; |
|||
|
|||
namespace EventHub.Web.Helpers |
|||
{ |
|||
public class AllowedExtensionsAttribute : ValidationAttribute |
|||
{ |
|||
private readonly string[] _allowedExtensions; |
|||
|
|||
public AllowedExtensionsAttribute(string[] allowedExtensions) |
|||
{ |
|||
_allowedExtensions = allowedExtensions; |
|||
} |
|||
|
|||
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return ValidationResult.Success; |
|||
} |
|||
|
|||
var file = value as IFormFile; |
|||
var extension = Path.GetExtension(file.FileName); |
|||
|
|||
if (file.Length > 0 && file != null) |
|||
{ |
|||
if (!_allowedExtensions.Contains(extension.ToLower())) |
|||
{ |
|||
return new ValidationResult("This file extension is not allowed. Allowed extensions: " + string.Join(",", _allowedExtensions)); |
|||
} |
|||
} |
|||
|
|||
return ValidationResult.Success; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Microsoft.AspNetCore.Http; |
|||
|
|||
namespace EventHub.Web.Helpers |
|||
{ |
|||
public class MaxFileSizeAttribute : ValidationAttribute |
|||
{ |
|||
private readonly int _maxFileSize; |
|||
|
|||
public MaxFileSizeAttribute(int maxFileSize) |
|||
{ |
|||
_maxFileSize = maxFileSize; |
|||
} |
|||
|
|||
protected override ValidationResult IsValid( |
|||
object value, ValidationContext validationContext) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
return ValidationResult.Success; |
|||
} |
|||
|
|||
var file = value as IFormFile; |
|||
|
|||
if (file.Length > 0) |
|||
{ |
|||
if (file.Length > _maxFileSize) |
|||
{ |
|||
return new ValidationResult("Maximum file size: " + _maxFileSize); |
|||
} |
|||
} |
|||
|
|||
return ValidationResult.Success; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,118 @@ |
|||
$(function () { |
|||
var l = abp.localization.getResource('EventHub'); |
|||
|
|||
var fileInput = document.getElementById("organization-profile-picture"); |
|||
var file; |
|||
|
|||
fileInput.addEventListener('change', function () { |
|||
var showModal = true; |
|||
|
|||
file = fileInput.files[0]; |
|||
|
|||
if(file == undefined) { |
|||
$("#choose-cover-image").html(l("ChooseOrganizationProfilePicture")); |
|||
return; |
|||
} |
|||
else { |
|||
$("#choose-cover-image").html(file.name); |
|||
} |
|||
|
|||
var permittedExtensions = ["jpg", "jpeg", "png"] |
|||
var fileExtension = $(this).val().split('.').pop(); |
|||
|
|||
if (permittedExtensions.indexOf(fileExtension) === -1) { |
|||
showModal = false; |
|||
abp.message.error(l("OrganizationProfilePictureExtensionNotAllowed")) |
|||
.then(() => { |
|||
$("#choose-cover-image").html(l("ChooseOrganizationProfilePicture")); |
|||
file = null; |
|||
}); |
|||
} |
|||
//1mb
|
|||
else if(file.size > 1024 * 1024) { |
|||
showModal = false; |
|||
abp.message.error(l("OrganizationProfilePictureSizeExceedMessage")) |
|||
.then(() => { |
|||
$("#choose-cover-image").html(l("ChooseOrganizationProfilePicture")); |
|||
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(showModal && imageError) { |
|||
readURL(file); |
|||
$("#picturePreviewModal").modal('show'); |
|||
} |
|||
} |
|||
|
|||
var objectURL = URL.createObjectURL(file); |
|||
img.src = objectURL; |
|||
}); |
|||
|
|||
function readURL(input) { |
|||
if (input) { |
|||
var reader = new FileReader(); |
|||
|
|||
reader.onload = function (e) { |
|||
$('#img-upload').attr('src', e.target.result); |
|||
} |
|||
|
|||
reader.readAsDataURL(input); |
|||
} |
|||
} |
|||
|
|||
$("form#EditOrganizationProfileForm").submit(function (e) { |
|||
e.preventDefault(); |
|||
|
|||
var organizationId = document.getElementById("organization-id").value; |
|||
var organizationName = document.getElementById("organization-name").value; |
|||
|
|||
if(file === undefined) { |
|||
file = null; |
|||
} |
|||
|
|||
var formData = new FormData(); |
|||
formData.append("OrganizationId", organizationId); |
|||
formData.append("ProfilePictureFile", file); |
|||
|
|||
$.ajax({ |
|||
xhr: function() { |
|||
var xhr = new window.XMLHttpRequest(); |
|||
xhr.upload.addEventListener("progress", function(evt) { |
|||
if (evt.lengthComputable) { |
|||
var percentage = evt.loaded / evt.total; |
|||
percentage = parseInt(percentage * 100); |
|||
if(percentage !== 100){ |
|||
$('#btnSubmit').prop("disabled", true); |
|||
} |
|||
} |
|||
}, false); |
|||
|
|||
return xhr; |
|||
}, |
|||
url: `/api/organization/save-profile-picture`, |
|||
data: formData, |
|||
type: 'POST', |
|||
contentType: false, |
|||
processData: false, |
|||
success: function(data){ |
|||
abp.message |
|||
.success(l("OrganizationProfilePictureEditSuccessMessage")) |
|||
.then(data => window.location.href = "/Organizations/" + organizationName); |
|||
}, |
|||
error: function (data) { |
|||
abp.message.error(data.responseJSON.error.message); |
|||
} |
|||
}); |
|||
|
|||
}); |
|||
}); |
|||
Loading…
Reference in new issue