diff --git a/functions/package-lock.json b/functions/package-lock.json index 617b6eb9..2c82029d 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -13,12 +13,12 @@ "cors": "^2.8.5", "deepl-node": "^1.15.0", "express": "^4.21.2", - "firebase-admin": "^13.0.1", - "firebase-functions": "^6.1.1", + "firebase-admin": "^13.0.2", + "firebase-functions": "^6.2.0", "sharp": "^0.33.5", "stripe": "^17.4.0", - "uuid": "^11.0.3", - "zod": "^3.23.8" + "uuid": "^11.0.5", + "zod": "^3.24.1" }, "devDependencies": { "@types/express": "^4.17.21", @@ -3071,9 +3071,9 @@ } }, "node_modules/firebase-admin": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.0.1.tgz", - "integrity": "sha512-sKQ/Yw8o/WdC9qTKvuLMBjTbdcBISIXW4+M9PXk0bNjxEbZf1Er7EVq47eRb5+bnKof10xlns6zAIbj4tmSexg==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.0.2.tgz", + "integrity": "sha512-YWVpoN+tZVSRXF0qC0gojoF5bSqvBRbnBk8+xUtFiguM2L4vB7f0moAwV1VVWDDHvTnvQ68OyTMpdp6wKo/clw==", "license": "Apache-2.0", "dependencies": { "@fastify/busboy": "^3.0.0", @@ -3091,14 +3091,14 @@ "node": ">=18" }, "optionalDependencies": { - "@google-cloud/firestore": "^7.10.0", + "@google-cloud/firestore": "^7.11.0", "@google-cloud/storage": "^7.14.0" } }, "node_modules/firebase-functions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.1.1.tgz", - "integrity": "sha512-q+4zsQhX04YJUz6hqaiH/j5kixljPj0PMxkm8KN3juYp3I4NC6CZ4qfy5JRfwvV8VfXM2KkJrZuyJtLyZr97aw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.2.0.tgz", + "integrity": "sha512-vfyyVHS8elxplzEQ9To+NaINRPFUsDasQrasTa2eFJBYSPzdhkw6rwLmvwyYw622+ze+g4sDIb14VZym+afqXQ==", "license": "MIT", "dependencies": { "@types/cors": "^2.8.5", @@ -6082,9 +6082,9 @@ } }, "node_modules/uuid": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", - "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -6309,9 +6309,9 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/functions/package.json b/functions/package.json index f07f90fa..798a4a48 100644 --- a/functions/package.json +++ b/functions/package.json @@ -24,12 +24,12 @@ "cors": "^2.8.5", "deepl-node": "^1.15.0", "express": "^4.21.2", - "firebase-admin": "^13.0.1", - "firebase-functions": "^6.1.1", + "firebase-admin": "^13.0.2", + "firebase-functions": "^6.2.0", "sharp": "^0.33.5", "stripe": "^17.4.0", - "uuid": "^11.0.3", - "zod": "^3.23.8" + "uuid": "^11.0.5", + "zod": "^3.24.1" }, "devDependencies": { "openapi3-ts": "^4.4.0", diff --git a/functions/src/contents.ts b/functions/src/contents.ts index bacc4bcd..f6faf486 100644 --- a/functions/src/contents.ts +++ b/functions/src/contents.ts @@ -317,6 +317,19 @@ const onContentWrite = onDocumentWritten('spaces/{spaceId}/contents/{contentId}' } await findContentsHistory(spaceId, contentId).add(addHistory); + const countSnapshot = await findContentsHistory(spaceId, contentId).count().get(); + const { count } = countSnapshot.data(); + if (count > 30) { + const historySnapshot = await findContentsHistory(spaceId, contentId) + .orderBy('createdAt', 'asc') + .limit(count - 30) + .get(); + if (historySnapshot.size > 0) { + const batch = firestoreService.batch(); + historySnapshot.docs.forEach(doc => batch.delete(doc.ref)); + await batch.commit(); + } + } return; }); diff --git a/functions/src/models/content.zod.ts b/functions/src/models/content.zod.ts index 7769cacc..97246a5a 100644 --- a/functions/src/models/content.zod.ts +++ b/functions/src/models/content.zod.ts @@ -18,7 +18,7 @@ export const contentBaseSchema = z.object({ export const contentDocumentSchema = contentBaseSchema.extend({ kind: z.literal(ContentKind.DOCUMENT), schema: z.string(), - data: contentDataSchema.optional(), + data: z.string().optional().or(contentDataSchema.optional()), }); export const contentFolderSchema = contentBaseSchema.extend({ diff --git a/functions/src/services/open-api.service.ts b/functions/src/services/open-api.service.ts index 401edb42..958a5807 100644 --- a/functions/src/services/open-api.service.ts +++ b/functions/src/services/open-api.service.ts @@ -692,6 +692,16 @@ export function generateOpenApi(schemasById: Map): OpenAPIObject example: false, }, }, + { + name: 'thumbnail', + in: 'query', + description: 'In case you have animated image like WebP/Gif, and you wish to generate non animated thumbnail.', + required: false, + schema: { + type: 'boolean', + example: false, + }, + }, ], responses: { '200': { diff --git a/functions/src/translations.ts b/functions/src/translations.ts index 5220e027..1ecce578 100644 --- a/functions/src/translations.ts +++ b/functions/src/translations.ts @@ -3,7 +3,7 @@ import { HttpsError, onCall } from 'firebase-functions/v2/https'; import { onDocumentCreated, onDocumentWritten } from 'firebase-functions/v2/firestore'; import { FieldValue, WithFieldValue } from 'firebase-admin/firestore'; import { canPerform } from './utils/security-utils'; -import { bucket } from './config'; +import { bucket, firestoreService } from './config'; import { PublishTranslationsData, Space, Translation, TranslationHistory, TranslationHistoryType, UserPermission } from './models'; import { findSpaceById, findTranslations, findTranslationsHistory } from './services'; import { translateCloud } from './services/translate.service'; @@ -147,6 +147,19 @@ const onWriteToHistory = onDocumentWritten('spaces/{spaceId}/translations/{trans addHistory.name = afterData.updatedBy.name; } await findTranslationsHistory(spaceId).add(addHistory); + const countSnapshot = await findTranslationsHistory(spaceId).count().get(); + const { count } = countSnapshot.data(); + if (count > 30) { + const historySnapshot = await findTranslationsHistory(spaceId) + .orderBy('createdAt', 'asc') + .limit(count - 30) + .get(); + if (historySnapshot.size > 0) { + const batch = firestoreService.batch(); + historySnapshot.docs.forEach(doc => batch.delete(doc.ref)); + await batch.commit(); + } + } return; }); diff --git a/functions/src/v1.ts b/functions/src/v1.ts index b2a9f629..3f6e040e 100644 --- a/functions/src/v1.ts +++ b/functions/src/v1.ts @@ -347,7 +347,7 @@ expressApp.get('/api/v1/spaces/:spaceId/assets/:assetId', async (req, res) => { logger.info('v1 spaces asset params: ' + JSON.stringify(req.params)); logger.info('v1 spaces asset query: ' + JSON.stringify(req.query)); const { spaceId, assetId } = req.params; - const { w: width, download } = req.query; + const { w: width, download, thumbnail } = req.query; const assetFile = bucket.file(`spaces/${spaceId}/assets/${assetId}/original`); const [exists] = await assetFile.exists(); @@ -362,15 +362,25 @@ expressApp.get('/api/v1/spaces/:spaceId/assets/:assetId', async (req, res) => { if (asset.type === 'image/webp' || asset.type === 'image/gif') { // possible animated or single frame webp/gif const [file] = await assetFile.download(); - const sharpFile = sharp(file); + let sharpFile = sharp(file); const sharpFileMetadata = await sharpFile.metadata(); - if (sharpFileMetadata.pages) { - // animated webp/gif - await assetFile.download({ destination: tempFilePath }); - } else { + const isAnimated = sharpFileMetadata.pages !== undefined; + if (thumbnail && isAnimated) { + // Thumbnail with Animation: Remove animations, to reduce load + filename = `${asset.name}-w${width}-thumbnail${asset.extension}`; + sharpFile = sharp(file, { page: 0, pages: 1 }); + await sharpFile.resize(parseInt(width.toString(), 10)).toFile(tempFilePath); + } else if (thumbnail && !isAnimated) { + // thumbnail without Animation + filename = `${asset.name}-w${width}-thumbnail${asset.extension}`; // single frame webp/gif - filename = `${asset.name}-w${width}${asset.extension}`; await sharpFile.resize(parseInt(width.toString(), 10)).toFile(tempFilePath); + } else { + // Animated + filename = `${asset.name}-w${width}${asset.extension}`; + // animated webp/gif + // TODO no way now to resize animated files + await assetFile.download({ destination: tempFilePath }); } } else if (asset.type === 'image/svg+xml') { // svg, cannot resize diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 25f22f90..c84cd320 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -97,7 +97,8 @@ import { provideRemoteConfig, getRemoteConfig } from '@angular/fire/remote-confi useValue: (config: ImageLoaderConfig) => { // optimize image for API assets if (config.src.startsWith('/api/') && config.width) { - return `${config.src}?w=${config.width}`; + const thumbnailParam = config.loaderParams && config.loaderParams['thumbnail'] ? '&thumbnail=true' : ''; + return `${config.src}?w=${config.width}${thumbnailParam}`; } else { return config.src; } diff --git a/src/app/features/admin/settings/ui/ui.component.html b/src/app/features/admin/settings/ui/ui.component.html index 29f859aa..4780f812 100644 --- a/src/app/features/admin/settings/ui/ui.component.html +++ b/src/app/features/admin/settings/ui/ui.component.html @@ -2,10 +2,12 @@ User Interface - +
+ +
diff --git a/src/app/features/admin/spaces/spaces.component.html b/src/app/features/admin/spaces/spaces.component.html index 8f7f4d35..e36b917f 100644 --- a/src/app/features/admin/spaces/spaces.component.html +++ b/src/app/features/admin/spaces/spaces.component.html @@ -2,10 +2,12 @@ Spaces - +
+ +
@if (isLoading) { @@ -58,5 +60,5 @@ - + diff --git a/src/app/features/admin/users/users.component.html b/src/app/features/admin/users/users.component.html index 41d8c922..285e36fe 100644 --- a/src/app/features/admin/users/users.component.html +++ b/src/app/features/admin/users/users.component.html @@ -2,15 +2,17 @@ Users - +
+ - + +
@if (isLoading()) { @@ -102,5 +104,5 @@ - + diff --git a/src/app/features/features.component.ts b/src/app/features/features.component.ts index b2e93bdf..b972867c 100644 --- a/src/app/features/features.component.ts +++ b/src/app/features/features.component.ts @@ -12,7 +12,6 @@ import { signal, Signal, } from '@angular/core'; -import { Observable } from 'rxjs'; import { LocalStorageService } from '@core/core.module'; import { Auth, signOut } from '@angular/fire/auth'; @@ -91,9 +90,6 @@ export class FeaturesComponent implements OnInit { { link: 'https://github.com/Lessify/localess/issues', label: 'Feedback', icon: 'forum' }, ]; - stickyHeader$: Observable | undefined; - language$: Observable | undefined; - private destroyRef = inject(DestroyRef); spaceStore = inject(SpaceStore); userStore = inject(UserStore); diff --git a/src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.component.html b/src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.component.html index d4abff54..73048229 100644 --- a/src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.component.html +++ b/src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.component.html @@ -4,8 +4,8 @@

Create new Folder

Name - - {{ form.controls['name'].value?.length || 0 }}/50 + + {{ form.controls['name'].value?.length || 0 }}/100 @if (form.controls['name'].errors; as errors) { {{ fe.errors(errors) }} } diff --git a/src/app/features/spaces/assets/assets.component.html b/src/app/features/spaces/assets/assets.component.html index b8819d24..3b4ddb0c 100644 --- a/src/app/features/spaces/assets/assets.component.html +++ b/src/app/features/spaces/assets/assets.component.html @@ -5,39 +5,55 @@ help - @if ('ASSET_CREATE' | canUserPerform | async) { - - - - - } - - @if (['ASSET_IMPORT', 'ASSET_EXPORT'] | canUserPerform | async) { - - } +
+ @if (fileUploadQueue().length > 0) { + + } + + + view_list + + + grid_view + + + @if ('ASSET_CREATE' | canUserPerform | async) { + + - - @if ('ASSET_IMPORT' | canUserPerform | async) { - } - @if ('ASSET_EXPORT' | canUserPerform | async) { - } - + + + @if ('ASSET_IMPORT' | canUserPerform | async) { + + } + @if ('ASSET_EXPORT' | canUserPerform | async) { + + } + +
@if (isLoading()) { @@ -51,162 +67,262 @@ } +
+ @if (settingsStore.assetLayout() === 'list') { + + + + + + + + + + + + + + Icon + + @switch (element.kind) { + @case ('FILE') { + {{ fileIcon(element.type) }} + } + @case ('FOLDER') { + folder + } + } + + + + Preview + + @if (element.kind === 'FILE' && filePreview(element.type)) { + @if (element.inProgress) { + + } @else { + thumbnail + } + } + + + + Name + +
+
{{ element.name }}{{ element.extension }}
+ @if (element.metadata; as metadata) { + @if (metadata.width && metadata.height) { + W{{ metadata.width }} x H{{ metadata.height }} + } + @if (metadata.animated) { +

animated_images

+ } + } +
+
+
+ + File Size + + @if (element.size) { + {{ element.size | formatFileSize }} + } @else { + remove + } + + + + Type + + @if (element.kind === 'FILE') { + @if (element.type) { + {{ element.type }} + } @else { + unknown + } + } @else { + Folder + } + + + + Created At + + {{ element.createdAt?.toDate() | date: 'mediumDate' }} + + + + Updated At + + {{ element.updatedAt?.toDate() | date: 'mediumDate' }} + + + + Actions + + + @if ('ASSET_UPDATE' | canUserPerform | async) { + + } + @if ('ASSET_UPDATE' | canUserPerform | async) { + + } + @if ('ASSET_DELETE' | canUserPerform | async) { + + } + + - - - - - - - - - - - - - - Icon - - @switch (element.kind) { - @case ('FILE') { - {{ fileIcon(element.type) }} - } - @case ('FOLDER') { - folder - } - } - - - - Preview - - @if (element.kind === 'FILE' && filePreview(element.type)) { - @if (element.inProgress) { - - } @else { - thumbnail - } + + + + + + + + + + + + + + + + + + + + + + + @if (!isLoading()) { + +
+
+
+ Drag and Drop a file here or use the "Upload Asset" button +
+
+
+
+
} -
-
- - Name - -
-
{{ element.name }}{{ element.extension }}
- @if (element.metadata; as metadata) { - - @if (metadata.width && metadata.height) { - W{{ metadata.width }} x H{{ metadata.height }} + + } @else { +
+ @for (item of dataSource.connect() | async; track item.id) { + + @if (item.inProgress) { +
+ +
+ } @else if (item.kind === 'FILE' && filePreview(item.type)) { + thumbnail + } @else if (item.kind === 'FILE') { + File + } @else { + Folder + } + + {{ item.name }}{{ item.extension }} + + + @if (item.kind === 'FILE') { + @if (item.size; as size) { +

{{ size | formatFileSize }}

+ } + @if (item.metadata; as metadata) { + @if (metadata.width && metadata.height) { + W{{ metadata.width }} x H{{ metadata.height }} + } + } } -
- } -
- - - - Size - {{ element.size | digitalStore }} - - - Type - {{ element.type }} - - - Created At - - {{ element.createdAt?.toDate() | date: 'mediumDate' }} - - - - Updated At - - {{ element.updatedAt?.toDate() | date: 'mediumDate' }} - - - - Actions - - - @if ('ASSET_UPDATE' | canUserPerform | async) { - - } - @if ('ASSET_UPDATE' | canUserPerform | async) { - - } - @if ('ASSET_DELETE' | canUserPerform | async) { - +

+ {{ item.updatedAt?.toDate() | date: 'mediumDate' }} +

+ + + + + @if ('ASSET_UPDATE' | canUserPerform | async) { + + } + @if ('ASSET_UPDATE' | canUserPerform | async) { + + } + @if ('ASSET_DELETE' | canUserPerform | async) { + + } + + + } @empty { +
+
+
+ Drag and Drop a file here or use the "Upload Asset" button +
+
+
+
} -
-
- - - - - - - - - - - - - - - - - - - - - - - - @if (!isLoading()) { - -
-
-
- Drag and Drop a file here or use the "Upload Asset" button -
-
-
-
+
} -
- - @if (fileUploadQueue.length > 0) { +
+ + @if (false || fileUploadQueue().length > 0) {
@@ -215,7 +331,7 @@ - @for (file of fileUploadQueue; track file.name; let idx = $index) { + @for (file of fileUploadQueue(); track file.name; let idx = $index) { {{ file.name.length < 30 ? file.name : file.name.slice(0, 27).concat('...') }} @if (idx === 0) { @@ -224,7 +340,7 @@ } - {{ file.size | digitalStore }} + {{ file.size | formatFileSize }} } diff --git a/src/app/features/spaces/assets/assets.component.scss b/src/app/features/spaces/assets/assets.component.scss index 81ceaac4..f0e9cc82 100644 --- a/src/app/features/spaces/assets/assets.component.scss +++ b/src/app/features/spaces/assets/assets.component.scss @@ -1,9 +1,8 @@ -@use '@angular/material' as mat; - table { width: 100%; } + //mat-header-cell { // &.mat-column-actions { // text-align: center; @@ -15,11 +14,11 @@ table { // } //} -mat-row { - &.row-folder { - cursor: pointer; - } -} +//mat-row { +// &.row-folder { +// cursor: pointer; +// } +//} mat-cell { &.mat-column-preview { diff --git a/src/app/features/spaces/assets/assets.component.ts b/src/app/features/spaces/assets/assets.component.ts index 751aac8f..31186180 100644 --- a/src/app/features/spaces/assets/assets.component.ts +++ b/src/app/features/spaces/assets/assets.component.ts @@ -11,7 +11,15 @@ import { ConfirmationDialogModel } from '@shared/components/confirmation-dialog/ import { ObjectUtils } from '@core/utils/object-utils.service'; import { SelectionModel } from '@angular/cdk/collections'; import { AssetService } from '@shared/services/asset.service'; -import { Asset, AssetFile, AssetFileUpdate, AssetFolderCreate, AssetFolderUpdate, AssetKind } from '@shared/models/asset.model'; +import { + Asset, + AssetFile, + AssetFileUpdate, + AssetFolder, + AssetFolderCreate, + AssetFolderUpdate, + AssetKind, +} from '@shared/models/asset.model'; import { AddFolderDialogModel } from './add-folder-dialog/add-folder-dialog.model'; import { AddFolderDialogComponent } from './add-folder-dialog/add-folder-dialog.component'; import { EditFolderDialogComponent } from './edit-folder-dialog/edit-folder-dialog.component'; @@ -26,6 +34,9 @@ import { EditFileDialogModel } from './edit-file-dialog/edit-file-dialog.model'; import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; import { PathItem, SpaceStore } from '@shared/stores/space.store'; import { MoveDialogComponent, MoveDialogModel, MoveDialogReturn } from './move-dialog'; +import { LocalSettingsStore } from '@shared/stores/local-settings.store'; +import { ImagePreviewDialogComponent } from './image-preview-dialog/image-preview-dialog.component'; +import { ImagePreviewDialogModel } from './image-preview-dialog/image-preview-dialog.model'; @Component({ selector: 'll-assets', @@ -34,7 +45,7 @@ import { MoveDialogComponent, MoveDialogModel, MoveDialogReturn } from './move-d changeDetection: ChangeDetectionStrategy.OnPush, }) export class AssetsComponent implements OnInit { - sort = viewChild.required(MatSort); + sort = viewChild(MatSort); paginator = viewChild.required(MatPaginator); // Input @@ -45,9 +56,9 @@ export class AssetsComponent implements OnInit { private destroyRef = inject(DestroyRef); dataSource: MatTableDataSource = new MatTableDataSource([]); displayedColumns: string[] = [/*'select',*/ 'icon', 'preview', 'name', 'size', 'type', /*'createdAt',*/ 'updatedAt', 'actions']; - selection = new SelectionModel(true, []); + selection = new SelectionModel(true, [], undefined, (o1, o2) => o1.id === o2.id); assets: Asset[] = []; - fileUploadQueue: File[] = []; + fileUploadQueue = signal([]); now = Date.now(); get parentPath(): string { @@ -63,6 +74,8 @@ export class AssetsComponent implements OnInit { // Loading isLoading = signal(true); + // Local Settings + settingsStore = inject(LocalSettingsStore); constructor( private readonly assetService: AssetService, @@ -79,9 +92,10 @@ export class AssetsComponent implements OnInit { ) .subscribe({ next: assets => { + console.log(assets); this.assets = assets; this.dataSource = new MatTableDataSource(assets); - this.dataSource.sort = this.sort(); + this.dataSource.sort = this.sort() || null; this.dataSource.paginator = this.paginator(); this.isLoading.set(false); this.selection.clear(); @@ -99,7 +113,10 @@ export class AssetsComponent implements OnInit { ) .subscribe({ next: () => { - this.fileUploadQueue.shift(); + this.fileUploadQueue.update(files => { + files.shift(); + return files; + }); }, error: () => { this.notificationService.error(`Asset can not be uploaded.`); @@ -113,7 +130,10 @@ export class AssetsComponent implements OnInit { if (target.files && target.files.length > 0) { for (let idx = 0; idx < target.files.length; idx++) { const file = target.files[idx]; - this.fileUploadQueue.push(file); + this.fileUploadQueue.update(files => { + files.push(file); + return files; + }); this.fileUploadQueue$.next(file); } } @@ -160,7 +180,7 @@ export class AssetsComponent implements OnInit { panelClass: 'sm', data: { reservedNames: this.assets.map(it => it.name), - asset: ObjectUtils.clone(element), + asset: ObjectUtils.clone(element) as AssetFolder, }, }) .afterClosed() @@ -189,7 +209,7 @@ export class AssetsComponent implements OnInit { panelClass: 'sm', data: { reservedNames: this.assets.map(it => it.name), - asset: ObjectUtils.clone(element), + asset: ObjectUtils.clone(element) as AssetFile, }, }) .afterClosed() @@ -294,19 +314,24 @@ export class AssetsComponent implements OnInit { this.selection.select(...this.dataSource.data); } - onRowSelect(element: Asset): void { - // if (element.kind === AssetKind.FILE) { - // element.publishedAt - // if (this.schemasMap.has(element.schema)) { - // this.router.navigate(['features', 'contents', element.id]); - // } else { - // this.notificationService.warn(`Content Schema can not be found.`); - // } - // return; - // } - - this.isLoading.set(true); - if (element.kind === AssetKind.FOLDER) { + onAssetSelect(element: Asset): void { + if (element.kind === AssetKind.FILE && element.type.startsWith('image/')) { + this.dialog + .open(ImagePreviewDialogComponent, { + panelClass: 'image-preview', + data: { + spaceId: this.spaceId(), + asset: element, + }, + }) + .afterClosed() + .subscribe({ + next: () => { + console.log('close'); + }, + }); + } else if (element.kind === AssetKind.FOLDER) { + this.isLoading.set(true); this.selection.clear(); const assetPath = ObjectUtils.clone(this.spaceStore.assetPath() || []); assetPath.push({ @@ -394,16 +419,20 @@ export class AssetsComponent implements OnInit { }); } - onDownload(event: Event, element: AssetFile): void { + onDownload(event: Event, element: Asset): void { // Prevent Default event.preventDefault(); event.stopImmediatePropagation(); + if (element.kind !== AssetKind.FILE) return; window.open(`/api/v1/spaces/${this.spaceId()}/assets/${element.id}?download`); } filesDragAndDrop(event: File[]) { event.forEach(file => { - this.fileUploadQueue.push(file); + this.fileUploadQueue.update(files => { + files.push(file); + return files; + }); this.fileUploadQueue$.next(file); }); } diff --git a/src/app/features/spaces/assets/assets.module.ts b/src/app/features/spaces/assets/assets.module.ts index a09979c1..cf78234f 100644 --- a/src/app/features/spaces/assets/assets.module.ts +++ b/src/app/features/spaces/assets/assets.module.ts @@ -12,6 +12,7 @@ import { ImportDialogComponent } from './import-dialog/import-dialog.component'; import { TaskService } from '@shared/services/task.service'; import { EditFileDialogComponent } from './edit-file-dialog/edit-file-dialog.component'; import { MoveDialogComponent } from './move-dialog'; +import { ImagePreviewDialogComponent } from './image-preview-dialog/image-preview-dialog.component'; @NgModule({ declarations: [ @@ -22,6 +23,7 @@ import { MoveDialogComponent } from './move-dialog'; ExportDialogComponent, ImportDialogComponent, MoveDialogComponent, + ImagePreviewDialogComponent, ], imports: [SharedModule, AssetsRoutingModule], providers: [SpaceService, AssetService, TaskService], diff --git a/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.component.html b/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.component.html index 064b0dd5..22751d52 100644 --- a/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.component.html +++ b/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.component.html @@ -4,8 +4,9 @@

Edit File

Name - - {{ form.controls['name'].value?.length || 0 }}/50 + + {{ data.asset.extension }} + {{ form.controls['name'].value?.length || 0 }}/100 @if (form.controls['name'].errors; as errors) { {{ fe.errors(errors) }} } diff --git a/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.model.ts b/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.model.ts index 51de90bc..cf1e6fa9 100644 --- a/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.model.ts +++ b/src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.model.ts @@ -1,6 +1,6 @@ -import { Asset } from '@shared/models/asset.model'; +import { AssetFile } from '@shared/models/asset.model'; export interface EditFileDialogModel { - asset: Asset; + asset: AssetFile; reservedNames: string[]; } diff --git a/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.component.html b/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.component.html index b1cdb460..4367f8a2 100644 --- a/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.component.html +++ b/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.component.html @@ -4,8 +4,8 @@

Edit Folder

Name - - {{ form.controls['name'].value?.length || 0 }}/50 + + {{ form.controls['name'].value?.length || 0 }}/100 @if (form.controls['name'].errors; as errors) { {{ fe.errors(errors) }} } diff --git a/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.model.ts b/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.model.ts index eae0e88c..e04c351d 100644 --- a/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.model.ts +++ b/src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.model.ts @@ -1,6 +1,6 @@ -import { Asset } from '@shared/models/asset.model'; +import { AssetFolder } from '@shared/models/asset.model'; export interface EditFolderDialogModel { - asset: Asset; + asset: AssetFolder; reservedNames: string[]; } diff --git a/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.html b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.html new file mode 100644 index 00000000..b56296d9 --- /dev/null +++ b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.html @@ -0,0 +1,13 @@ + + thumbnail + + + + diff --git a/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.scss b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.ts b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.ts new file mode 100644 index 00000000..8de257d5 --- /dev/null +++ b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.component.ts @@ -0,0 +1,13 @@ +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ImagePreviewDialogModel } from './image-preview-dialog.model'; + +@Component({ + selector: 'll-asset-image-preview-dialog', + templateUrl: './image-preview-dialog.component.html', + styleUrls: ['./image-preview-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ImagePreviewDialogComponent { + constructor(@Inject(MAT_DIALOG_DATA) public data: ImagePreviewDialogModel) {} +} diff --git a/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.model.ts b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.model.ts new file mode 100644 index 00000000..7e58c746 --- /dev/null +++ b/src/app/features/spaces/assets/image-preview-dialog/image-preview-dialog.model.ts @@ -0,0 +1,6 @@ +import { AssetFile } from '@shared/models/asset.model'; + +export interface ImagePreviewDialogModel { + spaceId: string; + asset: AssetFile; +} diff --git a/src/app/features/spaces/contents/contents.component.html b/src/app/features/spaces/contents/contents.component.html index 551815e2..4a170d72 100644 --- a/src/app/features/spaces/contents/contents.component.html +++ b/src/app/features/spaces/contents/contents.component.html @@ -5,48 +5,49 @@ help - - @if ('CONTENT_CREATE' | canUserPerform | async) { - - - - - - } - - + + + + + } - - - - @if ('CONTENT_IMPORT' | canUserPerform | async) { - - } - @if ('CONTENT_EXPORT' | canUserPerform | async) { - - } - + + + @if ('CONTENT_IMPORT' | canUserPerform | async) { + + } + @if ('CONTENT_EXPORT' | canUserPerform | async) { + + } + +
@if (isLoading()) { @@ -201,5 +202,5 @@ - + diff --git a/src/app/features/spaces/contents/contents.component.ts b/src/app/features/spaces/contents/contents.component.ts index f9f49675..6e7f55a2 100644 --- a/src/app/features/spaces/contents/contents.component.ts +++ b/src/app/features/spaces/contents/contents.component.ts @@ -52,7 +52,7 @@ export class ContentsComponent { isLoading = signal(true); dataSource: MatTableDataSource = new MatTableDataSource([]); displayedColumns: string[] = [/*'select',*/ 'status', 'name', 'slug', 'schema', /*'publishedAt', 'createdAt',*/ 'updatedAt', 'actions']; - selection = new SelectionModel(true, []); + selection = new SelectionModel(true, [], undefined, (o1, o2) => o1.id === o2.id); schemas: Schema[] = []; schemasMapById: Map = new Map(); diff --git a/src/app/features/spaces/contents/edit-document/edit-document.component.html b/src/app/features/spaces/contents/edit-document/edit-document.component.html index f5bf6bc3..95e0b322 100644 --- a/src/app/features/spaces/contents/edit-document/edit-document.component.html +++ b/src/app/features/spaces/contents/edit-document/edit-document.component.html @@ -7,103 +7,106 @@   #{{ document?.slug }} - - - design_services - - - edit_note - - +
+ + + design_services + + + edit_note + + - - - - @for (locale of availableLocales; track locale.id) { - - } - - - @if (contentErrors.length > 0) { - - } - -
- @for (error of contentErrors; track error.contentId) { -
- warning - In {{ error.schema }} the {{ error.fieldDisplayName || error.fieldName }} {{ fe.errors(error.errors) }} for Locale - {{ availableLocalesMap.get(error.locale) }} -
+ + @for (locale of availableLocales; track locale.id) { + } -
-
- @if ('CONTENT_UPDATE' | canUserPerform | async) { - - } - @if ('CONTENT_PUBLISH' | canUserPerform | async) { - - } - @if (document?.publishedAt === undefined) { - - } @else if (document?.publishedAt?.seconds > document?.updatedAt?.seconds) { - - } @else if (document?.publishedAt && document?.publishedAt?.seconds < document?.updatedAt?.seconds) { - - } + - - - + @if (contentErrors.length > 0) { + + } - - @for (locale of selectedSpace?.locales; track locale.id) { - } - - @for (locale of selectedSpace?.locales; track locale.id) { - } - + @if (document?.publishedAt === undefined) { + + } @else if (document?.publishedAt?.seconds > document?.updatedAt?.seconds) { + + } @else if (document?.publishedAt && document?.publishedAt?.seconds < document?.updatedAt?.seconds) { + + } + + + + + + + @for (locale of selectedSpace?.locales; track locale.id) { + + } + + @for (locale of selectedSpace?.locales; track locale.id) { + + } + +
@@ -211,117 +214,119 @@ -
-
    - @for (item of history$ | async; track item.id; let isLast = $last) { -
  • -
    -
    - @switch (item.type) { - @case ('PUBLISHED') { -
    - - publish - -
    -
    + @if (showHistory) { +
    +
      + @for (item of history$ | async; track item.id; let isLast = $last) { +
    • +
      +
      + @switch (item.type) { + @case ('PUBLISHED') {
      -

      - Published by - - {{ item.name || 'Unknown' }} - -

      + + publish +
      -
      - +
      +
      +

      + Published by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @case ('CREATE') { -
      - - add - -
      -
      + } + @case ('CREATE') {
      -

      - Created with name {{ item.cName }} and slug - {{ item.cSlug }} by - - {{ item.name || 'Unknown' }} - -

      + + add +
      -
      - +
      +
      +

      + Created with name {{ item.cName }} and slug + {{ item.cSlug }} by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @case ('UPDATE') { -
      - - edit - -
      -
      + } + @case ('UPDATE') {
      -

      - Updated with - @if (item.cName) { - name {{ item.cName }} - } - @if (item.cSlug) { + + edit + +

      +
      +
      +

      + Updated with @if (item.cName) { - and + name {{ item.cName }} } - slug {{ item.cSlug }} - } - @if (item.cParentSlug) { - parent slug {{ item.cParentSlug }} - } @else if (item.cData) { - content - } @else { - nothing - } - by - - {{ item.name || 'Unknown' }} - -

      -
      -
      - + @if (item.cSlug) { + @if (item.cName) { + and + } + slug {{ item.cSlug }} + } + @if (item.cParentSlug) { + parent slug {{ item.cParentSlug }} + } @else if (item.cData) { + content + } @else { + nothing + } + by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @default { -
      - - question_mark - -
      -
      + } + @default {
      -

      Unknown

      by - - {{ item.name || 'Unknown' }} + + question_mark
      -
      - +
      +
      +

      Unknown

      by + + {{ item.name || 'Unknown' }} + +
      +
      + +
      -
      + } } - } +
      -
      -
    • - } @empty { - No Records found - } -
    -
    +
  • + } @empty { + No Records found + } +
+
+ }
diff --git a/src/app/features/spaces/contents/edit-document/edit-document.component.ts b/src/app/features/spaces/contents/edit-document/edit-document.component.ts index 0c1e6879..a2dee531 100644 --- a/src/app/features/spaces/contents/edit-document/edit-document.component.ts +++ b/src/app/features/spaces/contents/edit-document/edit-document.component.ts @@ -164,7 +164,7 @@ export class EditDocumentComponent implements OnInit, DirtyFormGuardComponent { } get isFormDirty(): boolean { - return !ObjectUtils.isEqual(this.document?.data, JSON.stringify(this.contentHelperService.clone(this.documentData))); + return JSON.stringify(this.document?.data) !== JSON.stringify(this.contentHelperService.clone(this.documentData)); } publish(): void { diff --git a/src/app/features/spaces/contents/shared/asset-select/asset-select.component.html b/src/app/features/spaces/contents/shared/asset-select/asset-select.component.html index eff1b6a4..1445ec74 100644 --- a/src/app/features/spaces/contents/shared/asset-select/asset-select.component.html +++ b/src/app/features/spaces/contents/shared/asset-select/asset-select.component.html @@ -30,13 +30,14 @@ height="200" alt="thumbnail" loading="lazy" + [loaderParams]="{ thumbnail: true }" ngSrc="/api/v1/spaces/{{ space().id }}/assets/{{ asset.id }}" /> } @else { file_present }
{{ asset.name }}{{ asset.extension }}
- {{ asset.size | digitalStore }} + {{ asset.size | formatFileSize }} @if (asset.metadata; as metadata) { | W{{ metadata.width }} x H{{ metadata.height }} } diff --git a/src/app/features/spaces/contents/shared/asset-select/asset-select.component.ts b/src/app/features/spaces/contents/shared/asset-select/asset-select.component.ts index 0b3bb6eb..9d56242c 100644 --- a/src/app/features/spaces/contents/shared/asset-select/asset-select.component.ts +++ b/src/app/features/spaces/contents/shared/asset-select/asset-select.component.ts @@ -55,7 +55,7 @@ export class AssetSelectComponent implements OnInit { openAssetSelectDialog(): void { this.dialog .open(AssetsSelectDialogComponent, { - panelClass: 'xl', + panelClass: 'full-screen', data: { spaceId: this.space().id, multiple: false, diff --git a/src/app/features/spaces/contents/shared/assets-select/assets-select.component.html b/src/app/features/spaces/contents/shared/assets-select/assets-select.component.html index 11c4311a..c5d2a0fa 100644 --- a/src/app/features/spaces/contents/shared/assets-select/assets-select.component.html +++ b/src/app/features/spaces/contents/shared/assets-select/assets-select.component.html @@ -29,13 +29,14 @@ height="200" alt="thumbnail" loading="lazy" + [loaderParams]="{ thumbnail: true }" ngSrc="/api/v1/spaces/{{ space().id }}/assets/{{ asset.id }}" /> } @else { file_present }
{{ asset.name }}{{ asset.extension }}
- {{ asset.size | digitalStore }} + {{ asset.size | formatFileSize }} @if (asset.metadata; as metadata) { | W{{ metadata.width }} x H{{ metadata.height }} } diff --git a/src/app/features/spaces/contents/shared/assets-select/assets-select.component.ts b/src/app/features/spaces/contents/shared/assets-select/assets-select.component.ts index 9ca9f029..be2b5731 100644 --- a/src/app/features/spaces/contents/shared/assets-select/assets-select.component.ts +++ b/src/app/features/spaces/contents/shared/assets-select/assets-select.component.ts @@ -64,7 +64,7 @@ export class AssetsSelectComponent implements OnInit { openAssetSelectDialog(): void { this.dialog .open(AssetsSelectDialogComponent, { - panelClass: 'xl', + panelClass: 'full-screen', data: { spaceId: this.space().id, multiple: true, diff --git a/src/app/features/spaces/dashboard/dashboard.component.html b/src/app/features/spaces/dashboard/dashboard.component.html index 1970cb4d..58e01cd7 100644 --- a/src/app/features/spaces/dashboard/dashboard.component.html +++ b/src/app/features/spaces/dashboard/dashboard.component.html @@ -2,11 +2,13 @@ Dashboard - @if ('SPACE_MANAGEMENT' | canUserPerform | async) { - - } +
+ @if ('SPACE_MANAGEMENT' | canUserPerform | async) { + + } +
@@ -53,25 +55,25 @@

Storage

Total
- {{ space.overview?.translationSize + space?.overview?.assetsSize + space?.overview?.contentSize | digitalStore }} + {{ space.overview?.translationSize + space?.overview?.assetsSize + space?.overview?.contentSize | formatFileSize }}
Translations
- {{ space.overview?.translationSize || 0 | digitalStore }} + {{ space.overview?.translationSize || 0 | formatFileSize }}
Asset Files
- {{ space.overview?.assetsSize || 0 | digitalStore }} + {{ space.overview?.assetsSize || 0 | formatFileSize }}
Content Documents
- {{ space.overview?.contentSize || 0 | digitalStore }} + {{ space.overview?.contentSize || 0 | formatFileSize }}
diff --git a/src/app/features/spaces/schemas/schemas.component.html b/src/app/features/spaces/schemas/schemas.component.html index 56f72dc2..75b8edd4 100644 --- a/src/app/features/spaces/schemas/schemas.component.html +++ b/src/app/features/spaces/schemas/schemas.component.html @@ -5,31 +5,33 @@ help - @if ('SCHEMA_CREATE' | canUserPerform | async) { - - } - @if (['SCHEMA_IMPORT', 'SCHEMA_EXPORT'] | canUserPerform | async) { - - - @if ('SCHEMA_IMPORT' | canUserPerform | async) { - - } - @if ('SCHEMA_EXPORT' | canUserPerform | async) { - - } - - } +
+ @if ('SCHEMA_CREATE' | canUserPerform | async) { + + } + @if (['SCHEMA_IMPORT', 'SCHEMA_EXPORT'] | canUserPerform | async) { + + + @if ('SCHEMA_IMPORT' | canUserPerform | async) { + + } + @if ('SCHEMA_EXPORT' | canUserPerform | async) { + + } + + } +
@if (isLoading) { @@ -106,5 +108,5 @@ - +
diff --git a/src/app/features/spaces/settings/general/general.component.html b/src/app/features/spaces/settings/general/general.component.html index 9ecd0601..115b56b1 100644 --- a/src/app/features/spaces/settings/general/general.component.html +++ b/src/app/features/spaces/settings/general/general.component.html @@ -2,10 +2,12 @@ General - +
+ +
@if (isLoading()) { diff --git a/src/app/features/spaces/settings/locales/locales.component.html b/src/app/features/spaces/settings/locales/locales.component.html index a9d181fd..19f35400 100644 --- a/src/app/features/spaces/settings/locales/locales.component.html +++ b/src/app/features/spaces/settings/locales/locales.component.html @@ -2,10 +2,12 @@ Locales - +
+ +
@if (isLoading()) { @@ -56,5 +58,5 @@ - + diff --git a/src/app/features/spaces/settings/tokens/tokens.component.html b/src/app/features/spaces/settings/tokens/tokens.component.html index 59bacb1c..ebdb29b1 100644 --- a/src/app/features/spaces/settings/tokens/tokens.component.html +++ b/src/app/features/spaces/settings/tokens/tokens.component.html @@ -2,10 +2,12 @@ Tokens - +
+ +
@if (isLoading()) { @@ -45,5 +47,5 @@ - + diff --git a/src/app/features/spaces/settings/visual-editor/visual-editor.component.html b/src/app/features/spaces/settings/visual-editor/visual-editor.component.html index 7085ec10..4a5599d4 100644 --- a/src/app/features/spaces/settings/visual-editor/visual-editor.component.html +++ b/src/app/features/spaces/settings/visual-editor/visual-editor.component.html @@ -2,10 +2,12 @@ Visual Editor - +
+ +
@@ -18,10 +20,12 @@ Preview URL's - +
+ +
diff --git a/src/app/features/spaces/tasks/tasks.component.html b/src/app/features/spaces/tasks/tasks.component.html index 34f7446d..3d1a64e5 100644 --- a/src/app/features/spaces/tasks/tasks.component.html +++ b/src/app/features/spaces/tasks/tasks.component.html @@ -70,7 +70,7 @@ @if (element.file; as file) {
{{ file.name }}
-
Size : {{ file.size | digitalStore }}
+
Size : {{ file.size | formatFileSize }}
} @@ -133,5 +133,5 @@ - + diff --git a/src/app/features/spaces/translations/translations.component.html b/src/app/features/spaces/translations/translations.component.html index 47f07f6f..af8037c3 100644 --- a/src/app/features/spaces/translations/translations.component.html +++ b/src/app/features/spaces/translations/translations.component.html @@ -6,52 +6,54 @@ help - @if ('TRANSLATION_CREATE' | canUserPerform | async) { - - } - @if ('TRANSLATION_PUBLISH' | canUserPerform | async) { - - } - - - - @for (locale of space.locales; track locale.id) { - } - @if (['TRANSLATION_IMPORT', 'TRANSLATION_EXPORT'] | canUserPerform | async) { - - @if ('TRANSLATION_IMPORT' | canUserPerform | async) { - + } + + + + @for (locale of space.locales; track locale.id) { + } - @if ('TRANSLATION_EXPORT' | canUserPerform | async) { - + @if (['TRANSLATION_IMPORT', 'TRANSLATION_EXPORT'] | canUserPerform | async) { + + @if ('TRANSLATION_IMPORT' | canUserPerform | async) { + + } + @if ('TRANSLATION_EXPORT' | canUserPerform | async) { + + } } - } - + + @if (isLoading()) { @@ -351,117 +353,119 @@ -
-
    - @for (item of history$ | async; track item.id; let isLast = $last) { -
  • -
    -
    - @switch (item.type) { - @case ('PUBLISHED') { -
    - - publish - -
    -
    + @if (showHistory) { +
    +
      + @for (item of history$ | async; track item.id; let isLast = $last) { +
    • +
      +
      + @switch (item.type) { + @case ('PUBLISHED') {
      -

      - Published by - - {{ item.name || 'Unknown' }} - -

      + + publish +
      -
      - +
      +
      +

      + Published by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @case ('CREATE') { -
      - - add - -
      -
      + } + @case ('CREATE') {
      -

      - Add {{ item.key }} by - - {{ item.name || 'Unknown' }} - -

      + + add +
      -
      - +
      +
      +

      + Add {{ item.key }} by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @case ('UPDATE') { -
      - - edit - -
      -
      + } + @case ('UPDATE') {
      -

      - Edit {{ item.key }} by - - {{ item.name || 'Unknown' }} - -

      + + edit +
      -
      - +
      +
      +

      + Edit {{ item.key }} by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @case ('DELETE') { -
      - - delete - -
      -
      + } + @case ('DELETE') {
      -

      - Delete {{ item.key }} by - - {{ item.name || 'Unknown' }} - -

      + + delete +
      -
      - +
      +
      +

      + Delete {{ item.key }} by + + {{ item.name || 'Unknown' }} + +

      +
      +
      + +
      -
      - } - @default { -
      - - question_mark - -
      -
      + } + @default {
      -

      Unknown

      + + question_mark +
      -
      - +
      +
      +

      Unknown

      +
      +
      + +
      -
      + } } - } +
      -
      -
    • - } @empty { - No Records found - } -
    -
    +
  • + } @empty { + No Records found + } +
+
+ }
} diff --git a/src/app/shared/components/assets-select-dialog/assets-select-dialog.component.html b/src/app/shared/components/assets-select-dialog/assets-select-dialog.component.html index 1919e9b3..eb0e5173 100644 --- a/src/app/shared/components/assets-select-dialog/assets-select-dialog.component.html +++ b/src/app/shared/components/assets-select-dialog/assets-select-dialog.component.html @@ -1,4 +1,32 @@ -

Assets

+

+ Assets +
+ @if (fileUploadQueue().length > 0) { + + } + + + view_list + + + grid_view + + + @if ('ASSET_CREATE' | canUserPerform | async) { + + + } +
+

+@if (isLoading()) { + +}   @for (pathItem of assetPath; track pathItem.fullSlug; let isFirst = $first) { @@ -8,83 +36,154 @@

Assets

}
- - - - # - - @if (row.kind === 'FILE') { - - - } - - - - Icon - - @switch (element.kind) { - @case ('FILE') { - {{ fileIcon(element.type) }} + @if (settingsStore.assetDialogLayout() === 'list') { + + + + # + + @if (row.kind === 'FILE') { + + } - @case ('FOLDER') { - folder + + + + Icon + + @switch (element.kind) { + @case ('FILE') { + {{ fileIcon(element.type) }} + } + @case ('FOLDER') { + folder + } } - } - - - - Preview - - @if (element.kind === 'FILE' && filePreview(element.type)) { - thumbnail - } - - - - Name - -
-
{{ element.name }}{{ element.extension }}
- @if (element.metadata; as metadata) { - - @if (metadata.width && metadata.height) { - W{{ metadata.width }} x H{{ metadata.height }} - } - + + + + Preview + + @if (element.kind === 'FILE' && filePreview(element.type)) { + thumbnail + } + + + + Name + +
+
{{ element.name }}{{ element.extension }}
+ @if (element.metadata; as metadata) { + + @if (metadata.width && metadata.height) { + W{{ metadata.width }} x H{{ metadata.height }} + } + + } +
+
+
+ + File Size + + @if (element.size) { + {{ element.size | formatFileSize }} + } @else { + remove + } + + + + Type + + @if (element.kind === 'FILE') { + @if (element.type) { + {{ element.type }} + } @else { + unknown + } + } @else { + Folder } -
-
-
- - Size - {{ element.size | digitalStore }} - - - Type - {{ element.type }} - - - Updated At - - {{ element.updatedAt?.toDate() | date: 'mediumDate' }} - - +
+
+ + Updated At + + {{ element.updatedAt?.toDate() | date: 'mediumDate' }} + + - - -
+ + + + } @else { +
+ @for (item of dataSource.connect() | async; track item.id) { + + @if (item.inProgress) { +
+ +
+ } @else if (item.kind === 'FILE' && filePreview(item.type)) { + thumbnail + } @else if (item.kind === 'FILE') { + File + } @else { + Folder + } + + {{ item.name }}{{ item.extension }} + + + @if (item.kind === 'FILE') { + @if (item.size; as size) { +

{{ size | formatFileSize }}

+ } + @if (item.metadata; as metadata) { + @if (metadata.width && metadata.height) { + W{{ metadata.width }} x H{{ metadata.height }} + } + } + } +

+ {{ item.updatedAt?.toDate() | date: 'mediumDate' }} +

+
+ + + + + +
+ } +
+ }
+