User Insert ve Update için Avatar
This commit is contained in:
parent
0f46de0381
commit
0c202ece24
8 changed files with 65 additions and 17 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Sozsoft.Platform.Extensions;
|
using Sozsoft.Platform.Extensions;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
@ -10,17 +12,26 @@ using Volo.Abp.Domain.Entities;
|
||||||
using Volo.Abp.Identity;
|
using Volo.Abp.Identity;
|
||||||
using Volo.Abp.TenantManagement;
|
using Volo.Abp.TenantManagement;
|
||||||
using IdentityUser = Volo.Abp.Identity.IdentityUser;
|
using IdentityUser = Volo.Abp.Identity.IdentityUser;
|
||||||
|
using Sozsoft.Platform.BlobStoring;
|
||||||
|
using Sozsoft.Platform.Identity;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Sozsoft.Platform.ListForms.DynamicApi;
|
namespace Sozsoft.Platform.ListForms.DynamicApi;
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamicApiAppService
|
public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamicApiAppService
|
||||||
{
|
{
|
||||||
|
private static readonly Regex DataUrlRegex = new(
|
||||||
|
@"^data:(?<contentType>image\/[a-zA-Z0-9.+-]+);base64,(?<data>.+)$",
|
||||||
|
RegexOptions.Compiled);
|
||||||
|
|
||||||
private readonly ITenantRepository tenantRepository;
|
private readonly ITenantRepository tenantRepository;
|
||||||
private readonly ITenantManager tenantManager;
|
private readonly ITenantManager tenantManager;
|
||||||
private readonly IIdentityUserAppService identityUserAppService;
|
private readonly IIdentityUserAppService identityUserAppService;
|
||||||
private readonly IIdentityRoleAppService identityRoleAppService;
|
private readonly IIdentityRoleAppService identityRoleAppService;
|
||||||
private readonly IdentityUserManager userManager;
|
private readonly IdentityUserManager userManager;
|
||||||
|
private readonly BlobManager blobCdnManager;
|
||||||
|
private readonly IConfiguration configuration;
|
||||||
private readonly IOptions<IdentityOptions> identityOptions;
|
private readonly IOptions<IdentityOptions> identityOptions;
|
||||||
|
|
||||||
public ListFormDynamicApiAppService(
|
public ListFormDynamicApiAppService(
|
||||||
|
|
@ -29,6 +40,8 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
IIdentityUserAppService identityUserAppService,
|
IIdentityUserAppService identityUserAppService,
|
||||||
IIdentityRoleAppService identityRoleAppService,
|
IIdentityRoleAppService identityRoleAppService,
|
||||||
IdentityUserManager userManager,
|
IdentityUserManager userManager,
|
||||||
|
BlobManager blobCdnManager,
|
||||||
|
IConfiguration configuration,
|
||||||
IOptions<IdentityOptions> identityOptions)
|
IOptions<IdentityOptions> identityOptions)
|
||||||
{
|
{
|
||||||
this.tenantRepository = tenantRepository;
|
this.tenantRepository = tenantRepository;
|
||||||
|
|
@ -36,6 +49,8 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
this.identityUserAppService = identityUserAppService;
|
this.identityUserAppService = identityUserAppService;
|
||||||
this.identityRoleAppService = identityRoleAppService;
|
this.identityRoleAppService = identityRoleAppService;
|
||||||
this.userManager = userManager;
|
this.userManager = userManager;
|
||||||
|
this.blobCdnManager = blobCdnManager;
|
||||||
|
this.configuration = configuration;
|
||||||
this.identityOptions = identityOptions;
|
this.identityOptions = identityOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,6 +59,41 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
return Guid.TryParse(value, out var id) ? id : Guid.Empty;
|
return Guid.TryParse(value, out var id) ? id : Guid.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SaveAvatarAsync(IdentityUser user, string avatar)
|
||||||
|
{
|
||||||
|
if (avatar.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var base64 = avatar.Trim();
|
||||||
|
var match = DataUrlRegex.Match(base64);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
base64 = match.Groups["data"].Value;
|
||||||
|
}
|
||||||
|
else if (avatar.StartsWith("http", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
avatar.StartsWith("/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bytes = Convert.FromBase64String(base64);
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileName = $"{user.Id}.jpg";
|
||||||
|
await using var stream = new MemoryStream(bytes);
|
||||||
|
await blobCdnManager.SaveAsync(BlobContainerNames.Avatar, fileName, stream);
|
||||||
|
user.SetAvatar(AvatarProvider.GetAvatar(configuration, user.TenantId?.ToString(), user.Id.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
[Authorize(IdentityPermissions.Users.Create)]
|
[Authorize(IdentityPermissions.Users.Create)]
|
||||||
public async Task PostUserInsertAsync(DynamicApiBaseInput<CreateUpdateUserInput> input)
|
public async Task PostUserInsertAsync(DynamicApiBaseInput<CreateUpdateUserInput> input)
|
||||||
{
|
{
|
||||||
|
|
@ -68,7 +118,8 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
user.SetDepartmentId(ParseGuid(input.Data.DepartmentId));
|
user.SetDepartmentId(ParseGuid(input.Data.DepartmentId));
|
||||||
user.SetJobPositionId(ParseGuid(input.Data.JobPositionId));
|
user.SetJobPositionId(ParseGuid(input.Data.JobPositionId));
|
||||||
user.SetIsVerified(verify);
|
user.SetIsVerified(verify);
|
||||||
user.SetAvatar(input.Data.Avatar);
|
|
||||||
|
await SaveAvatarAsync(user, input.Data.Avatar);
|
||||||
|
|
||||||
(await userManager.CreateAsync(user, input.Data.Password)).CheckErrors();
|
(await userManager.CreateAsync(user, input.Data.Password)).CheckErrors();
|
||||||
await userManager.SetLockoutEnabledAsync(user, true);
|
await userManager.SetLockoutEnabledAsync(user, true);
|
||||||
|
|
@ -139,11 +190,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
user.SetJobPositionId(ParseGuid(input.Data.JobPositionId));
|
user.SetJobPositionId(ParseGuid(input.Data.JobPositionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.Data.Avatar != null)
|
await SaveAvatarAsync(user, input.Data.Avatar);
|
||||||
{
|
|
||||||
user.SetJobPositionId(ParseGuid(input.Data.Avatar));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
(await userManager.UpdateAsync(user)).CheckErrors();
|
(await userManager.UpdateAsync(user)).CheckErrors();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -809,7 +809,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 710, true, true, true, true, false),
|
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 710, true, true, true, true, false),
|
||||||
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>() {
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>() {
|
||||||
new () { Order=1,ColCount=1,ColSpan=1,ItemType="group",Items=[
|
new () { Order=1,ColCount=1,ColSpan=1,ItemType="group",Items=[
|
||||||
new EditingFormItemDto { Order=1, DataField="Avatar", ColSpan=1, EditorType2=EditorTypes.dxImageViewer },
|
new EditingFormItemDto { Order=1, DataField="Avatar", ColSpan=1, EditorType2=EditorTypes.dxImageViewer, EditorOptions=EditorOptionValues.ImageUploadOptions(false) },
|
||||||
new EditingFormItemDto { Order=2, DataField="Email", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order=2, DataField="Email", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=3, DataField="Name", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order=3, DataField="Name", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=4, DataField="Surname", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order=4, DataField="Surname", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
|
||||||
|
|
@ -2703,7 +2703,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.Announcement)),
|
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.Announcement)),
|
||||||
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
||||||
PagerOptionJson = DefaultPagerOptionJson,
|
PagerOptionJson = DefaultPagerOptionJson,
|
||||||
EditingOptionJson = DefaultEditingOptionJson(listFormName, 750, 600, true, true, true, true, false),
|
EditingOptionJson = DefaultEditingOptionJson(listFormName, 750, 700, true, true, true, true, false),
|
||||||
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
||||||
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>()
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>()
|
||||||
{
|
{
|
||||||
|
|
@ -2717,7 +2717,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
new EditingFormItemDto { Order = 6, DataField = "PublishDate", ColSpan=1, EditorType2 = EditorTypes.dxDateBox },
|
new EditingFormItemDto { Order = 6, DataField = "PublishDate", ColSpan=1, EditorType2 = EditorTypes.dxDateBox },
|
||||||
new EditingFormItemDto { Order = 7, DataField = "ExpiryDate", ColSpan=1, EditorType2 = EditorTypes.dxDateBox },
|
new EditingFormItemDto { Order = 7, DataField = "ExpiryDate", ColSpan=1, EditorType2 = EditorTypes.dxDateBox },
|
||||||
new EditingFormItemDto { Order = 8, DataField = "IsPinned", ColSpan=1, EditorType2 = EditorTypes.dxCheckBox },
|
new EditingFormItemDto { Order = 8, DataField = "IsPinned", ColSpan=1, EditorType2 = EditorTypes.dxCheckBox },
|
||||||
new EditingFormItemDto { Order = 9, DataField = "ImageUrl", ColSpan=1, EditorType2 = EditorTypes.dxImageUpload, EditorOptions = EditorOptionValues.ImageUploadOptions},
|
new EditingFormItemDto { Order = 9, DataField = "ImageUrl", ColSpan=1, EditorType2 = EditorTypes.dxImageUpload, EditorOptions = EditorOptionValues.ImageUploadOptions()},
|
||||||
]}
|
]}
|
||||||
}),
|
}),
|
||||||
FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
||||||
|
|
@ -4218,7 +4218,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
new EditingFormItemDto { Order = 7, DataField = "Status", ColSpan = 1, EditorType2 = EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
|
new EditingFormItemDto { Order = 7, DataField = "Status", ColSpan = 1, EditorType2 = EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
|
||||||
new EditingFormItemDto { Order = 8, DataField = "ParticipantsCount", ColSpan = 1, EditorType2 = EditorTypes.dxNumberBox },
|
new EditingFormItemDto { Order = 8, DataField = "ParticipantsCount", ColSpan = 1, EditorType2 = EditorTypes.dxNumberBox },
|
||||||
new EditingFormItemDto { Order = 9, DataField = "Description", ColSpan = 2, EditorType2 = EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order = 9, DataField = "Description", ColSpan = 2, EditorType2 = EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order = 10, DataField = "Photos", ColSpan = 1, EditorType2 = EditorTypes.dxImageUpload, EditorOptions = EditorOptionValues.ImageUploadOptions },
|
new EditingFormItemDto { Order = 10, DataField = "Photos", ColSpan = 1, EditorType2 = EditorTypes.dxImageUpload, EditorOptions = EditorOptionValues.ImageUploadOptions() },
|
||||||
]}
|
]}
|
||||||
}),
|
}),
|
||||||
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public static class PlatformConsts
|
||||||
public static string DateFormat = "{ \"format\": \"dd/MM/yyyy\", \"displayFormat\" : \"dd/MM/yyyy\" }";
|
public static string DateFormat = "{ \"format\": \"dd/MM/yyyy\", \"displayFormat\" : \"dd/MM/yyyy\" }";
|
||||||
public static string DateTimeFormat = "{ \"format\": \"dd/MM/yyyy HH:mm\", \"displayFormat\" : \"dd/MM/yyyy HH:mm\" }";
|
public static string DateTimeFormat = "{ \"format\": \"dd/MM/yyyy HH:mm\", \"displayFormat\" : \"dd/MM/yyyy HH:mm\" }";
|
||||||
public static string SliderOptions = "{\"tooltip\": { \"enabled\": true }}";
|
public static string SliderOptions = "{\"tooltip\": { \"enabled\": true }}";
|
||||||
public static string ImageUploadOptions = "{\"width\": 80, \"height\": 80, \"multiple\": true}";
|
public static string ImageUploadOptions(bool multiple = true) => $"{{\"width\": 80, \"height\": 80, \"multiple\": {multiple.ToString().ToLower()}}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EditorScriptValues
|
public static class EditorScriptValues
|
||||||
|
|
|
||||||
BIN
ui/public/img/others/no-image.png
Normal file
BIN
ui/public/img/others/no-image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
|
|
@ -137,6 +137,7 @@ export interface UserInfoViewModel extends ExtensibleObject {
|
||||||
phoneNumberConfirmed: boolean
|
phoneNumberConfirmed: boolean
|
||||||
accessFailedCount: number
|
accessFailedCount: number
|
||||||
shouldChangePasswordOnNextLogin: boolean
|
shouldChangePasswordOnNextLogin: boolean
|
||||||
|
avatar: string
|
||||||
rocketUsername?: string
|
rocketUsername?: string
|
||||||
creationTime: Date | string
|
creationTime: Date | string
|
||||||
lastModificationTime: Date | string
|
lastModificationTime: Date | string
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ const ImageViewerEditorComponent = ({
|
||||||
}}
|
}}
|
||||||
onError={({ currentTarget }) => {
|
onError={({ currentTarget }) => {
|
||||||
currentTarget.onerror = null
|
currentTarget.onerror = null
|
||||||
currentTarget.src = '/img/others/default-profile.png'
|
currentTarget.src = '/img/others/no-image.png'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ const ImageViewerEditorComponent = (templateData: any): ReactElement => {
|
||||||
}}
|
}}
|
||||||
onError={({ currentTarget }) => {
|
onError={({ currentTarget }) => {
|
||||||
currentTarget.onerror = null
|
currentTarget.onerror = null
|
||||||
currentTarget.src = '/img/others/default-profile.png'
|
currentTarget.src = '/img/others/no-image.png'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '@/proxy/form/models'
|
} from '@/proxy/form/models'
|
||||||
import { addCss } from './Utils'
|
import { addCss } from './Utils'
|
||||||
|
|
||||||
const DEFAULT_PROFILE_IMAGE = '/img/others/default-profile.png'
|
const NO_IMAGE = '/img/others/no-image.png'
|
||||||
|
|
||||||
const cellTemplateMultiValue = (
|
const cellTemplateMultiValue = (
|
||||||
cellElement: HTMLElement,
|
cellElement: HTMLElement,
|
||||||
|
|
@ -92,7 +92,7 @@ function getImgPreview(): HTMLDivElement {
|
||||||
].join(';')
|
].join(';')
|
||||||
const img = document.createElement('img')
|
const img = document.createElement('img')
|
||||||
img.onerror = null
|
img.onerror = null
|
||||||
img.src = DEFAULT_PROFILE_IMAGE
|
img.src = NO_IMAGE
|
||||||
img.style.cssText =
|
img.style.cssText =
|
||||||
'display:block;max-width:312px;max-height:312px;object-fit:contain;border-radius:4px;'
|
'display:block;max-width:312px;max-height:312px;object-fit:contain;border-radius:4px;'
|
||||||
el.appendChild(img)
|
el.appendChild(img)
|
||||||
|
|
@ -107,7 +107,7 @@ function showImgPreview(src: string, e: MouseEvent) {
|
||||||
const imgEl = el.querySelector('img') as HTMLImageElement
|
const imgEl = el.querySelector('img') as HTMLImageElement
|
||||||
imgEl.onerror = () => {
|
imgEl.onerror = () => {
|
||||||
imgEl.onerror = null
|
imgEl.onerror = null
|
||||||
imgEl.src = DEFAULT_PROFILE_IMAGE
|
imgEl.src = NO_IMAGE
|
||||||
}
|
}
|
||||||
if (imgEl.src !== src) imgEl.src = src
|
if (imgEl.src !== src) imgEl.src = src
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ const cellTemplateImage = (
|
||||||
const img = document.createElement('img')
|
const img = document.createElement('img')
|
||||||
img.onerror = () => {
|
img.onerror = () => {
|
||||||
img.onerror = null
|
img.onerror = null
|
||||||
img.src = DEFAULT_PROFILE_IMAGE
|
img.src = NO_IMAGE
|
||||||
}
|
}
|
||||||
img.src = url
|
img.src = url
|
||||||
img.alt = ''
|
img.alt = ''
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue