From 6737d8f5d67eb337992646d5772863421c9df938 Mon Sep 17 00:00:00 2001 From: TomasHermanek Date: Thu, 26 Oct 2023 11:35:07 +0200 Subject: [PATCH] Feature/#74657/after gold 3 (#148) * feature #74657 after gold 3 features. * feature #74657 security fix * feature #74657 animation support * feature #74657 fixes prettyBps * feature #74657 vue search input warning fix. * feature #74657 vue search input warning fix. --------- Co-authored-by: Tomas Hermanek --- src/components/coreDam/FileUpload.vue | 5 ++ src/components/wrappers/MainWrapper.vue | 10 ++- src/locales/en.ts | 4 ++ src/locales/en/coreDam/asset.json | 4 +- src/locales/en/coreDam/audioFile.json | 8 +++ src/locales/en/coreDam/videoFile.json | 9 +++ src/locales/en/system.json | 4 +- src/locales/sk.ts | 4 ++ src/locales/sk/coreDam/asset.json | 4 +- src/locales/sk/coreDam/audioFile.json | 8 +++ src/locales/sk/coreDam/videoFile.json | 9 +++ src/locales/sk/system.json | 4 +- src/main.ts | 4 ++ src/model/coreDam/filter/AssetFilter.ts | 3 + src/styles/components/image-detail.scss | 19 +++++- src/types/coreDam/File.ts | 1 + src/utils/file.ts | 21 +++++++ .../asset/components/AssetMetadata.vue | 31 ++++++++-- .../AssetMetadataAudioAttributes.vue | 29 +++++++++ .../AssetMetadataImageAttributes.vue | 7 +++ .../AssetMetadataVideoAttributes.vue | 35 +++++++++++ .../footer/AssetFooterUploadOverlayFull.vue | 4 +- .../components/toolbar/AssetSearchInput.vue | 61 +++++++++++++++++++ .../toolbar/AssetToolbarOptions.vue | 52 +++++++++++++++- .../components/toolbar/AssetToolbarSearch.vue | 27 +------- .../ExternalProviderAssetToolbarSearch.vue | 16 +---- .../components/AssetDetailDialogSidebar.vue | 1 + .../distribution/DistributionNewDialog.vue | 6 +- .../coreDam/asset/list/AssetListView.vue | 4 +- .../components/AssetListSidebarFilter.vue | 9 +++ .../ExternalProviderAssetListView.vue | 4 +- .../components/KeywordTitleRemoteSelect.vue | 31 ++++++++++ 32 files changed, 380 insertions(+), 58 deletions(-) create mode 100644 src/locales/en/coreDam/audioFile.json create mode 100644 src/locales/en/coreDam/videoFile.json create mode 100644 src/locales/sk/coreDam/audioFile.json create mode 100644 src/locales/sk/coreDam/videoFile.json create mode 100644 src/utils/file.ts create mode 100644 src/views/coreDam/asset/components/AssetMetadataAudioAttributes.vue create mode 100644 src/views/coreDam/asset/components/AssetMetadataVideoAttributes.vue create mode 100644 src/views/coreDam/asset/components/toolbar/AssetSearchInput.vue create mode 100644 src/views/coreDam/keyword/components/KeywordTitleRemoteSelect.vue diff --git a/src/components/coreDam/FileUpload.vue b/src/components/coreDam/FileUpload.vue index f2d82214..e0221546 100644 --- a/src/components/coreDam/FileUpload.vue +++ b/src/components/coreDam/FileUpload.vue @@ -291,6 +291,11 @@ watch(selectedFiles, (newValue, oldValue) => { :height="height" @click.stop="clickDropzone" > + {{ buttonText }} diff --git a/src/components/wrappers/MainWrapper.vue b/src/components/wrappers/MainWrapper.vue index 1420b1a2..1026e46c 100644 --- a/src/components/wrappers/MainWrapper.vue +++ b/src/components/wrappers/MainWrapper.vue @@ -13,7 +13,6 @@ import AssetToolbarIntegrations from '@/views/coreDam/asset/components/toolbar/A import { ACL } from '@/types/Permission' import { AAdminSwitcher, ASystemBar } from '@anzusystems/common-admin' import { envConfig } from '@/services/EnvConfigService' -import AssetToolbarExtSystemLicence from '@/views/coreDam/asset/components/toolbar/AssetToolbarExtSystemLicence.vue' const { t } = useI18n() @@ -51,14 +50,18 @@ const { sidebarLeft, sidebarRight, customFooterHeight, customDialog } = useMainW > + + + +
- +
+
-
+
= ['en', 'sk'] +dayjs.extend(Duration) + const { currentUser } = useCurrentUser() loadCommonFonts() diff --git a/src/model/coreDam/filter/AssetFilter.ts b/src/model/coreDam/filter/AssetFilter.ts index 02d18367..8326ac3f 100644 --- a/src/model/coreDam/filter/AssetFilter.ts +++ b/src/model/coreDam/filter/AssetFilter.ts @@ -19,6 +19,9 @@ const filter = reactive({ status: { ...makeFilter({ name: 'status', default: [AssetStatus.WithFile] }), }, + keywordIds: { + ...makeFilter({ name: 'keywordIds', default: [], multiple: true }), + }, mostDominantColor: { ...makeFilter({ name: 'mostDominantColor', default: [] }), }, diff --git a/src/styles/components/image-detail.scss b/src/styles/components/image-detail.scss index b1ff5f7a..31b66b71 100644 --- a/src/styles/components/image-detail.scss +++ b/src/styles/components/image-detail.scss @@ -1,3 +1,5 @@ +@use 'vuetify/lib/styles/settings/_variables.scss' as vars; + $class-name-root: 'dam-image-detail'; $sidebar-width: 600px; $toolbar-height: 50px; @@ -28,7 +30,14 @@ $bg-sidebar-color-dark: #1a1a1a; position: absolute; top: 0; right: 0; - width: $sidebar-width; + + @media #{map-get(vars.$display-breakpoints, 'sm-and-down')} { + width: 100%; + } + + @media #{map-get(vars.$display-breakpoints, 'md-and-up')} { + width: $sidebar-width; + } } &__left { @@ -51,7 +60,13 @@ $bg-sidebar-color-dark: #1a1a1a; } .#{$class-name-root}__left { - padding-right: $sidebar-width; + @media #{map-get(vars.$display-breakpoints, 'sm-and-down')} { + width: 100%; + } + + @media #{map-get(vars.$display-breakpoints, 'md-and-up')} { + padding-right: $sidebar-width; + } } } } diff --git a/src/types/coreDam/File.ts b/src/types/coreDam/File.ts index f5bbbe17..1f390dba 100644 --- a/src/types/coreDam/File.ts +++ b/src/types/coreDam/File.ts @@ -18,6 +18,7 @@ interface ImageAttributes { height: number rotation: number mostDominantColor: string + animated: boolean } interface AudioAttributes { diff --git a/src/utils/file.ts b/src/utils/file.ts new file mode 100644 index 00000000..8b21c456 --- /dev/null +++ b/src/utils/file.ts @@ -0,0 +1,21 @@ +import dayjs from 'dayjs' + +export const prettyBps = (bytes: number, decimals = 2): string => { + const sizes = ['bps', 'kbps', 'Mbps', 'Gbps'] + + if (bytes === 0) { + return '0 ' + sizes[0] + } + + const k = 1024 + const dm = decimals < 0 ? 0 : decimals + const i = Math.floor(Math.log(bytes) / Math.log(k)) + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i] +} + +export const prettyDuration = (seconds: number): string => { + const duration = dayjs.duration(seconds * 1000) + + return duration.format('HH:mm:ss') +} diff --git a/src/views/coreDam/asset/components/AssetMetadata.vue b/src/views/coreDam/asset/components/AssetMetadata.vue index be4a8e81..aed6f2c2 100644 --- a/src/views/coreDam/asset/components/AssetMetadata.vue +++ b/src/views/coreDam/asset/components/AssetMetadata.vue @@ -14,6 +14,9 @@ import { useKeywordAssetTypeConfig } from '@/views/coreDam/keyword/composables/k import { useAuthorAssetTypeConfig } from '@/views/coreDam/author/composables/authorConfig' import { AssetMetadataValidationScopeSymbol } from '@/components/validationScopes' import AssetMetadataImageAttributes from '@/views/coreDam/asset/components/AssetMetadataImageAttributes.vue' +import { isVideoFile, isAudioFile } from '@/types/coreDam/File' +import AssetMetadataVideoAttributes from '@/views/coreDam/asset/components/AssetMetadataVideoAttributes.vue' +import AssetMetadataAudioAttributes from '@/views/coreDam/asset/components/AssetMetadataAudioAttributes.vue' const { t } = useI18n() @@ -29,6 +32,14 @@ const isTypeImage = computed(() => { return assetType.value === AssetType.Image }) +const isTypeAudio = computed(() => { + return assetType.value === AssetType.Audio +}) + +const isTypeVideo = computed(() => { + return assetType.value === AssetType.Video +}) + const assetMainFile = computed(() => { return asset.value && asset.value.mainFile ? asset.value.mainFile : null }) @@ -176,12 +187,22 @@ const onAnyMetadataChange = () => { {{ prettyBytes(assetMainFile.fileAttributes.size) }} + + + + + +
- - diff --git a/src/views/coreDam/asset/components/AssetMetadataAudioAttributes.vue b/src/views/coreDam/asset/components/AssetMetadataAudioAttributes.vue new file mode 100644 index 00000000..dd1b7442 --- /dev/null +++ b/src/views/coreDam/asset/components/AssetMetadataAudioAttributes.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/views/coreDam/asset/components/AssetMetadataImageAttributes.vue b/src/views/coreDam/asset/components/AssetMetadataImageAttributes.vue index 99b4a158..a9001466 100644 --- a/src/views/coreDam/asset/components/AssetMetadataImageAttributes.vue +++ b/src/views/coreDam/asset/components/AssetMetadataImageAttributes.vue @@ -2,6 +2,7 @@ import ColorBox from '@/components/coreDam/ColorBox.vue' import { useI18n } from 'vue-i18n' import type { ImageFile } from '@/types/coreDam/File' +import { ABooleanValue } from '@anzusystems/common-admin' withDefaults( defineProps<{ @@ -38,4 +39,10 @@ const { t } = useI18n() {{ file.imageAttributes.ratioWidth }} / {{ file.imageAttributes.ratioHeight }} + + {{ t('coreDam.asset.detail.info.field.animated') }} + + + + diff --git a/src/views/coreDam/asset/components/AssetMetadataVideoAttributes.vue b/src/views/coreDam/asset/components/AssetMetadataVideoAttributes.vue new file mode 100644 index 00000000..f4df991b --- /dev/null +++ b/src/views/coreDam/asset/components/AssetMetadataVideoAttributes.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/views/coreDam/asset/components/footer/AssetFooterUploadOverlayFull.vue b/src/views/coreDam/asset/components/footer/AssetFooterUploadOverlayFull.vue index 4a4ac947..7c3fd7f9 100644 --- a/src/views/coreDam/asset/components/footer/AssetFooterUploadOverlayFull.vue +++ b/src/views/coreDam/asset/components/footer/AssetFooterUploadOverlayFull.vue @@ -11,6 +11,7 @@ import AssetUpload from '@/views/coreDam/asset/components/AssetUpload.vue' import { useI18n } from 'vue-i18n' import useVuelidate from '@vuelidate/core' import { useAssetListActions } from '@/views/coreDam/asset/list/composables/assetListActions' +import { useDisplay } from 'vuetify' const { t } = useI18n() @@ -37,7 +38,8 @@ watch(queueTotalCount, (newValue, oldValue) => { } }) -const massOperations = ref(true) +const { mobile } = useDisplay() +const massOperations = ref(!mobile.value) const list = computed(() => { return uploadQueuesStore.getQueueItems(QUEUE_ID_UPLOAD_GLOBAL) diff --git a/src/views/coreDam/asset/components/toolbar/AssetSearchInput.vue b/src/views/coreDam/asset/components/toolbar/AssetSearchInput.vue new file mode 100644 index 00000000..c49446e1 --- /dev/null +++ b/src/views/coreDam/asset/components/toolbar/AssetSearchInput.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/views/coreDam/asset/components/toolbar/AssetToolbarOptions.vue b/src/views/coreDam/asset/components/toolbar/AssetToolbarOptions.vue index cdb5f8ce..50581f9f 100644 --- a/src/views/coreDam/asset/components/toolbar/AssetToolbarOptions.vue +++ b/src/views/coreDam/asset/components/toolbar/AssetToolbarOptions.vue @@ -3,6 +3,10 @@ import { ROUTE } from '@/router/routes' import { useI18n } from 'vue-i18n' import { ACL } from '@/types/Permission' import AssetCreateButton from '@/views/coreDam/asset/components/AssetCreateButton.vue' +import { computed, ref } from 'vue' +import { useCurrentAssetLicence, useCurrentExtSystem } from '@/composables/system/currentExtSystem' +import AssetToolbarExtSystemLicenceDialog + from '@/views/coreDam/asset/components/toolbar/AssetToolbarExtSystemLicenceDialog.vue' withDefaults( defineProps<{ @@ -14,6 +18,30 @@ withDefaults( ) const { t } = useI18n() + +const { currentExtSystem } = useCurrentExtSystem() +const { currentAssetLicence } = useCurrentAssetLicence() + +const displayTextExtSystem = computed(() => { + if (currentExtSystem.value) { + return currentExtSystem.value.name + } + return '' +}) + +const displayTextLicence = computed(() => { + if (currentAssetLicence.value) { + return currentAssetLicence.value.name + } + return '' +}) + +const dialog = ref(false) + +const openDialog = () => { + dialog.value = true +} + diff --git a/src/views/coreDam/asset/components/toolbar/AssetToolbarSearch.vue b/src/views/coreDam/asset/components/toolbar/AssetToolbarSearch.vue index 0d3632a7..514fc499 100644 --- a/src/views/coreDam/asset/components/toolbar/AssetToolbarSearch.vue +++ b/src/views/coreDam/asset/components/toolbar/AssetToolbarSearch.vue @@ -1,8 +1,6 @@ + +