diff options
Diffstat (limited to 'viewer/src/views/layout')
-rw-r--r-- | viewer/src/views/layout/left/LayoutInformation.vue | 8 | ||||
-rw-r--r-- | viewer/src/views/layout/left/LayoutTagInput.vue | 16 | ||||
-rw-r--r-- | viewer/src/views/layout/top/LayoutCommand.vue | 37 | ||||
-rw-r--r-- | viewer/src/views/layout/top/LayoutTop.vue | 10 |
4 files changed, 56 insertions, 15 deletions
diff --git a/viewer/src/views/layout/left/LayoutInformation.vue b/viewer/src/views/layout/left/LayoutInformation.vue index 780a458..9dfb311 100644 --- a/viewer/src/views/layout/left/LayoutInformation.vue +++ b/viewer/src/views/layout/left/LayoutInformation.vue | |||
@@ -67,6 +67,7 @@ const formatDate = computed(() => { | |||
67 | .infopanel { | 67 | .infopanel { |
68 | padding: 2px 2px 7px 7px; | 68 | padding: 2px 2px 7px 7px; |
69 | overflow-wrap: break-word; | 69 | overflow-wrap: break-word; |
70 | max-height: 50%; | ||
70 | 71 | ||
71 | .title { | 72 | .title { |
72 | font-weight: bold; | 73 | font-weight: bold; |
@@ -80,13 +81,6 @@ const formatDate = computed(() => { | |||
80 | > * { | 81 | > * { |
81 | margin-top: 5px; | 82 | margin-top: 5px; |
82 | } | 83 | } |
83 | ul, | ||
84 | ol { | ||
85 | margin-left: 1em; | ||
86 | } | ||
87 | ul { | ||
88 | list-style-type: disc; | ||
89 | } | ||
90 | a { | 84 | a { |
91 | color: $palette-200; | 85 | color: $palette-200; |
92 | &:hover { | 86 | &:hover { |
diff --git a/viewer/src/views/layout/left/LayoutTagInput.vue b/viewer/src/views/layout/left/LayoutTagInput.vue index a37c546..9ee6f8a 100644 --- a/viewer/src/views/layout/left/LayoutTagInput.vue +++ b/viewer/src/views/layout/left/LayoutTagInput.vue | |||
@@ -23,7 +23,7 @@ | |||
23 | v-model="search" | 23 | v-model="search" |
24 | :placeholder="t('tagInput.placeholder')" | 24 | :placeholder="t('tagInput.placeholder')" |
25 | :tabindex="50" | 25 | :tabindex="50" |
26 | @focus="e => (e.target as HTMLInputElement).select()" | 26 | @focus="(e: FocusEvent) => (e.target as HTMLInputElement).select()" |
27 | @keypress.enter="inputEnter" | 27 | @keypress.enter="inputEnter" |
28 | @keydown.backspace="inputBackspace" | 28 | @keydown.backspace="inputBackspace" |
29 | /> | 29 | /> |
@@ -58,7 +58,8 @@ import LdDropdown from '@/components/LdDropdown.vue'; | |||
58 | import LdInput from '@/components/LdInput.vue'; | 58 | import LdInput from '@/components/LdInput.vue'; |
59 | import { useIndexFactory } from '@/services/indexFactory'; | 59 | import { useIndexFactory } from '@/services/indexFactory'; |
60 | import { useGalleryStore } from '@/store/galleryStore'; | 60 | import { useGalleryStore } from '@/store/galleryStore'; |
61 | import { computedEager, useElementBounding, useFocus, useVModel } from '@vueuse/core'; | 61 | import { useUiStore } from '@/store/uiStore'; |
62 | import { computedEager, onKeyStroke, useElementBounding, useFocus, useKeyModifier, useVModel } from '@vueuse/core'; | ||
62 | import { computed, ref, StyleValue, watchEffect } from 'vue'; | 63 | import { computed, ref, StyleValue, watchEffect } from 'vue'; |
63 | import { useI18n } from 'vue-i18n'; | 64 | import { useI18n } from 'vue-i18n'; |
64 | 65 | ||
@@ -69,6 +70,7 @@ const emit = defineEmits(['update:modelValue', 'search', 'opening', 'closing']); | |||
69 | const model = useVModel(props, 'modelValue', emit); | 70 | const model = useVModel(props, 'modelValue', emit); |
70 | 71 | ||
71 | const { t } = useI18n(); | 72 | const { t } = useI18n(); |
73 | const uiStore = useUiStore(); | ||
72 | const galeryStore = useGalleryStore(); | 74 | const galeryStore = useGalleryStore(); |
73 | const indexFactory = useIndexFactory(); | 75 | const indexFactory = useIndexFactory(); |
74 | 76 | ||
@@ -88,6 +90,16 @@ const { focused } = useFocus(input); | |||
88 | 90 | ||
89 | // --- | 91 | // --- |
90 | 92 | ||
93 | const controlState = useKeyModifier('Control'); | ||
94 | onKeyStroke('k', e => { | ||
95 | if (!controlState.value || focused.value) return; | ||
96 | e.preventDefault(); | ||
97 | uiStore.toggleFullWidth(false); | ||
98 | focused.value = true; | ||
99 | }); | ||
100 | |||
101 | // --- | ||
102 | |||
91 | const filteredTags = computed(() => indexFactory.searchTags(galeryStore.tagsIndex, search.value, false) | 103 | const filteredTags = computed(() => indexFactory.searchTags(galeryStore.tagsIndex, search.value, false) |
92 | .filter(filterAlreadyPresent) | 104 | .filter(filterAlreadyPresent) |
93 | .sort((a, b) => b.items.length - a.items.length)); | 105 | .sort((a, b) => b.items.length - a.items.length)); |
diff --git a/viewer/src/views/layout/top/LayoutCommand.vue b/viewer/src/views/layout/top/LayoutCommand.vue index 8919da3..85d47b6 100644 --- a/viewer/src/views/layout/top/LayoutCommand.vue +++ b/viewer/src/views/layout/top/LayoutCommand.vue | |||
@@ -2,7 +2,7 @@ | |||
2 | -- pictures into a searchable web gallery. | 2 | -- pictures into a searchable web gallery. |
3 | -- | 3 | -- |
4 | -- Copyright (C) 2019-2022 Guillaume FOUET | 4 | -- Copyright (C) 2019-2022 Guillaume FOUET |
5 | -- 2020 Pacien TRAN-GIRARD | 5 | -- 2020-2022 Pacien TRAN-GIRARD |
6 | -- | 6 | -- |
7 | -- This program is free software: you can redistribute it and/or modify | 7 | -- This program is free software: you can redistribute it and/or modify |
8 | -- it under the terms of the GNU Affero General Public License as | 8 | -- it under the terms of the GNU Affero General Public License as |
@@ -33,7 +33,24 @@ | |||
33 | size="lg" | 33 | size="lg" |
34 | /> | 34 | /> |
35 | </LdLink> | 35 | </LdLink> |
36 | <LayoutCommandSort :tabindex="20" /> | 36 | |
37 | <LdLink | ||
38 | v-if="itemResourceUrl" | ||
39 | :title="t('command.download')" | ||
40 | :download="navigation.getFileName(props.item)" | ||
41 | :href="itemResourceUrl" | ||
42 | :tabindex="20" | ||
43 | > | ||
44 | <fa-icon | ||
45 | :icon="faFileDownload" | ||
46 | size="lg" | ||
47 | /> | ||
48 | </LdLink> | ||
49 | <LayoutCommandSort | ||
50 | v-else | ||
51 | :tabindex="20" | ||
52 | /> | ||
53 | |||
37 | <LdLink | 54 | <LdLink |
38 | :class="{ disabled: isEntryPoint(), [$style.commandSecondary]: true }" | 55 | :class="{ disabled: isEntryPoint(), [$style.commandSecondary]: true }" |
39 | :title="t('command.back')" | 56 | :title="t('command.back')" |
@@ -66,22 +83,34 @@ | |||
66 | <script setup lang="ts"> | 83 | <script setup lang="ts"> |
67 | import { Item } from '@/@types/gallery'; | 84 | import { Item } from '@/@types/gallery'; |
68 | import LdLink from '@/components/LdLink.vue'; | 85 | import LdLink from '@/components/LdLink.vue'; |
86 | import { useNavigation } from '@/services/navigation'; | ||
87 | import { useItemResource } from '@/services/ui/ldItemResourceUrl'; | ||
69 | import { useUiStore } from '@/store/uiStore'; | 88 | import { useUiStore } from '@/store/uiStore'; |
70 | import { faAngleDoubleLeft, faArrowLeft, faFolder, faLevelUpAlt, faSearch } from '@fortawesome/free-solid-svg-icons'; | 89 | import { |
90 | faAngleDoubleLeft, | ||
91 | faArrowLeft, | ||
92 | faFileDownload, | ||
93 | faFolder, | ||
94 | faLevelUpAlt, | ||
95 | faSearch, | ||
96 | } from '@fortawesome/free-solid-svg-icons'; | ||
71 | import { computedEager } from '@vueuse/shared'; | 97 | import { computedEager } from '@vueuse/shared'; |
72 | import { computed } from 'vue'; | 98 | import { computed, PropType, toRef } from 'vue'; |
73 | import { useI18n } from 'vue-i18n'; | 99 | import { useI18n } from 'vue-i18n'; |
74 | import { useRoute, useRouter } from 'vue-router'; | 100 | import { useRoute, useRouter } from 'vue-router'; |
75 | import LayoutCommandSort from './LayoutCommandSort.vue'; | 101 | import LayoutCommandSort from './LayoutCommandSort.vue'; |
76 | 102 | ||
77 | const props = defineProps({ | 103 | const props = defineProps({ |
78 | currentItemPath: { type: Array<Item>, required: true }, | 104 | currentItemPath: { type: Array<Item>, required: true }, |
105 | item: { type: Object as PropType<Item>, required: true }, | ||
79 | }); | 106 | }); |
80 | 107 | ||
81 | const { t } = useI18n(); | 108 | const { t } = useI18n(); |
82 | const route = useRoute(); | 109 | const route = useRoute(); |
83 | const router = useRouter(); | 110 | const router = useRouter(); |
84 | const uiStore = useUiStore(); | 111 | const uiStore = useUiStore(); |
112 | const navigation = useNavigation(); | ||
113 | const { itemResourceUrl } = useItemResource(toRef(props, 'item')); | ||
85 | 114 | ||
86 | const commandToggleSearchPanelIcon = computed(() => uiStore.fullWidth ? faSearch : faAngleDoubleLeft); | 115 | const commandToggleSearchPanelIcon = computed(() => uiStore.fullWidth ? faSearch : faAngleDoubleLeft); |
87 | const isRoot = computedEager(() => props.currentItemPath.length <= 1 && !uiStore.searchMode); | 116 | const isRoot = computedEager(() => props.currentItemPath.length <= 1 && !uiStore.searchMode); |
diff --git a/viewer/src/views/layout/top/LayoutTop.vue b/viewer/src/views/layout/top/LayoutTop.vue index b755c42..02c8b7b 100644 --- a/viewer/src/views/layout/top/LayoutTop.vue +++ b/viewer/src/views/layout/top/LayoutTop.vue | |||
@@ -18,8 +18,14 @@ | |||
18 | --> | 18 | --> |
19 | 19 | ||
20 | <template> | 20 | <template> |
21 | <div class="flex"> | 21 | <div |
22 | <LayoutCommand :current-item-path="galleryStore.currentItemPath" /> | 22 | v-if="galleryStore.currentItem" |
23 | class="flex" | ||
24 | > | ||
25 | <LayoutCommand | ||
26 | :current-item-path="galleryStore.currentItemPath" | ||
27 | :item="galleryStore.currentItem" | ||
28 | /> | ||
23 | <LayoutBreadcrumb | 29 | <LayoutBreadcrumb |
24 | :current-item-path="galleryStore.currentItemPath" | 30 | :current-item-path="galleryStore.currentItemPath" |
25 | :search-mode="uiStore.searchMode" | 31 | :search-mode="uiStore.searchMode" |