Skip to content

Commit e32d449

Browse files
authored
Merge pull request #274 from DigitalSlideArchive/ui-improvements
UI improvements
2 parents 1d5a962 + b283bb6 commit e32d449

4 files changed

Lines changed: 139 additions & 70 deletions

File tree

client/src/HomePage.vue

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,8 @@ const forceRedact = () => {
228228
redactionStateFlags.showImageTable
229229
"
230230
/>
231-
<div v-if="redactionStateFlags.redactionComplete">
232-
<ImageDataDisplay />
233-
</div>
234-
<div v-if="redactionStateFlags.redactionSnackbar" class="toast">
231+
<ImageDataDisplay v-if="redactionStateFlags.redactionComplete" />
232+
<div v-if="redactionStateFlags.redactionSnackbar" class="toast z-[100]">
235233
<div class="alert alert-success">
236234
<span class="font-semibold">Redaction Complete</span>
237235
<div>

client/src/components/FileBrowser.vue

Lines changed: 126 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script setup lang="ts">
2-
import { ref, Ref } from "vue";
2+
import { ref, Ref, onMounted, onBeforeUnmount, nextTick } from "vue";
33
import { getDirectoryInfo } from "../api/rest";
44
import { selectedDirectories } from "../store/directoryStore";
55
import { useRedactionPlan } from "../store/imageStore";
66
import { redactionStateFlags } from "../store/redactionStore";
7-
import { DirectoryData } from "../store/types";
7+
import { DirectoryData, Path } from "../store/types";
88
99
const props = defineProps({
1010
modalId: {
@@ -29,25 +29,34 @@ const directoryData: Ref<DirectoryData> = ref({
2929
childrenYaml: [],
3030
});
3131
32+
const loadingData = ref(false);
33+
3234
const updateDirectories = async (currentDirectory?: string) => {
35+
directoryData.value.children = [];
36+
directoryData.value.childrenImages = [];
37+
directoryData.value.childrenYaml = [];
38+
const timeout = setTimeout(() => {
39+
loadingData.value = true;
40+
}, 100);
41+
3342
const data = await getDirectoryInfo(currentDirectory);
43+
clearTimeout(timeout);
44+
loadingData.value = false;
3445
directoryData.value = await {
3546
...data,
3647
children: data.child_directories,
3748
childrenImages: data.child_images,
3849
childrenYaml: data.child_yaml_files,
3950
};
51+
loadingData.value = false;
52+
calculateVisibleItems();
4053
};
4154
updateDirectories();
4255
4356
const closeModal = () => {
4457
modal.value.close();
4558
};
4659
47-
const updateSelectedDirectories = (path: string) => {
48-
selectedDirectories.value[props.modalId] = path;
49-
};
50-
5160
const updateTableData = () => {
5261
redactionStateFlags.value.redactionSnackbar = false;
5362
useRedactionPlan.updateImageData({
@@ -58,19 +67,66 @@ const updateTableData = () => {
5867
update: false,
5968
});
6069
};
70+
const updateSelectedDirectories = async (path: string) => {
71+
selectedDirectories.value[props.modalId] = path;
72+
};
73+
74+
const visibleImages: Ref<Path[]> = ref([]);
75+
const remainingImages = ref(0);
76+
77+
const calculateVisibleItems = () => {
78+
const menuTop = document.querySelector(".menu-top");
79+
const listContainer = document.querySelector(".list-container");
80+
// Determine and set the height of the list container
81+
listContainer?.setAttribute(
82+
"style",
83+
`height: calc(100% - (${menuTop?.clientHeight}px + 3.5rem))`,
84+
);
85+
86+
nextTick(() => {
87+
const listItems = listContainer?.querySelectorAll("li");
88+
const containerHeight = listContainer?.clientHeight;
89+
const listHeight = ref(0);
90+
const visibleItems = ref(0);
91+
// Determine the height of each list item
92+
const listItemHeight = listItems ? listItems[0].clientHeight : 0;
93+
94+
directoryData.value.childrenImages.forEach(() => {
95+
listHeight.value += listItemHeight;
96+
if (containerHeight && listHeight.value < containerHeight) {
97+
visibleItems.value += 1;
98+
}
99+
});
100+
101+
visibleImages.value = directoryData.value.childrenImages.slice(
102+
0,
103+
visibleItems.value,
104+
);
105+
remainingImages.value =
106+
directoryData.value.childrenImages.length - visibleItems.value;
107+
});
108+
};
109+
onMounted(() => {
110+
calculateVisibleItems();
111+
window.addEventListener("resize", calculateVisibleItems);
112+
});
113+
114+
onBeforeUnmount(() => {
115+
window.removeEventListener("resize", calculateVisibleItems);
116+
});
61117
</script>
62118

63119
<template>
64120
<dialog :id="modalId" ref="modal" class="modal">
65121
<div class="w-full max-w-4xl h-4/5 rounded-xl overflow-hidden">
66-
<div class="modal-box w-full max-w-4xl h-full overflow-auto pt-0">
67-
<div class="sticky top-0 pt-6 bg-white">
122+
<div class="modal-box w-full max-w-4xl h-4/5 overflow-auto pt-0">
123+
<div class="sticky top-0 pt-6 bg-white menu-top">
68124
<div class="flex justify-between">
69125
<h2 class="text-lg font-semibold">
70126
{{ title }}
71127
</h2>
72128
<button
73-
class="btn bg-primary float-right text-white uppercase"
129+
class="btn btn-primary float-right text-white uppercase"
74130
type="button"
75131
@click="
76132
$emit('update-image-list'),
@@ -107,56 +163,72 @@ const updateTableData = () => {
107163
</ul>
108164
</div>
109165
</div>
110-
<ul class="text-blue-700">
111-
<li
112-
v-for="child in directoryData.children.sort((a, b) => {
113-
const folder1 = a.name.toLowerCase();
114-
const folder2 = b.name.toLowerCase();
115-
if (folder1 < folder2) {
116-
return -1;
117-
}
118-
if (folder1 > folder2) {
119-
return 1;
120-
}
121-
return 0;
122-
})"
123-
:key="child.path"
124-
class="hover:bg-base-300 cursor-default py-0.5"
125-
@click="
126-
updateDirectories(child.path),
127-
updateSelectedDirectories(child.path)
128-
"
166+
<div
167+
v-if="loadingData"
168+
class="text-center"
169+
>
170+
<span class="loading loading-spinner text-primary"></span>
171+
<span class="ml-2 italic font-light align-top"
172+
>Collecting Directory Data</span
129173
>
130-
<i class="ri-folder-3-fill text-neutral"></i>
131-
{{ child.name }}
132-
</li>
133-
</ul>
134-
<ul class="pl-2">
135-
<template v-if="modalId !== 'rulesetDirectory'">
136-
<li
137-
v-for="child_image in directoryData.childrenImages.slice(0, 10)"
138-
:key="child_image.path"
139-
class="py-0.5"
140-
>
141-
<i class="ri-image-fill text-sky-800"></i>
142-
{{ child_image.name }}
143-
</li>
144-
<li v-if="directoryData.childrenImages.length > 10" class="italic">
145-
{{ directoryData.childrenImages.length - 10 }} More Images
146-
</li>
147-
</template>
148-
<template v-if="modalId === 'rulesetDirectory'">
174+
</div>
175+
<div class="list-container">
176+
<ul class="text-blue-700">
149177
<li
150-
v-for="ruleset in directoryData.childrenYaml"
151-
:key="ruleset.path"
178+
v-for="child in directoryData.children.sort((a, b) => {
179+
const folder1 = a.name.toLowerCase();
180+
const folder2 = b.name.toLowerCase();
181+
if (folder1 < folder2) {
182+
return -1;
183+
}
184+
if (folder1 > folder2) {
185+
return 1;
186+
}
187+
return 0;
188+
})"
189+
:key="child.path"
152190
class="hover:bg-base-300 cursor-default py-0.5"
153-
@click="updateSelectedDirectories(ruleset.path)"
191+
@click="
192+
updateDirectories(child.path),
193+
updateSelectedDirectories(child.path)
194+
"
154195
>
155-
<i class="ri-file-text-line text-neutral"></i>
156-
{{ ruleset.name }}
196+
<i class="ri-folder-3-fill text-neutral"></i>
197+
{{ child.name }}
157198
</li>
158-
</template>
159-
</ul>
199+
</ul>
200+
<div class="list-container">
201+
<ul class="pl-2">
202+
<template v-if="modalId !== 'rulesetDirectory'">
203+
<li
204+
v-for="child_image in visibleImages"
205+
:key="child_image.path"
206+
class="py-0.5"
207+
>
208+
<i class="ri-image-fill text-sky-800"></i>
209+
{{ child_image.name }}
210+
</li>
211+
<li
212+
v-if="directoryData.childrenImages.length > 10"
213+
class="italic"
214+
>
215+
{{ remainingImages }} More Images
216+
</li>
217+
</template>
218+
<template v-if="modalId === 'rulesetDirectory'">
219+
<li
220+
v-for="ruleset in directoryData.childrenYaml"
221+
:key="ruleset.path"
222+
class="hover:bg-base-300 cursor-default py-0.5"
223+
@click="updateSelectedDirectories(ruleset.path)"
224+
>
225+
<i class="ri-file-text-line text-neutral"></i>
226+
{{ ruleset.name }}
227+
</li>
228+
</template>
229+
</ul>
230+
</div>
231+
</div>
160232
</div>
161233
</div>
162234
<form method="dialog" class="modal-backdrop w-screen h-screen absolute">

client/src/components/ImageDataTable.vue

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ defineProps({
1414
<div v-if="!usedColumns" class="m-auto flex justify-center">
1515
Loading.. <span class="loading loading-bars loading-md"></span>
1616
</div>
17-
<table v-if="usedColumns" class="table table-auto text-center bg-base-100">
17+
<table
18+
v-if="usedColumns"
19+
class="table table-xs table-auto text-center bg-base-100"
20+
>
1821
<thead>
1922
<tr class="text-base bg-gray-600">
2023
<th class="bg-neutral text-white py-5 px-6">Image File Name</th>
@@ -36,14 +39,10 @@ defineProps({
3639
</tr>
3740
</thead>
3841
<tbody class="text-base bg-base-100">
39-
<tr
40-
v-for="(image, index) in imageRedactionPlan.data"
41-
:key="index"
42-
class="h-[125px]"
43-
>
42+
<tr v-for="(image, index) in imageRedactionPlan.data" :key="index">
4443
<th>{{ index }}</th>
4544
<td>
46-
<img :src="image.thumbnail" class="w-20 h-20" />
45+
<img :src="image.thumbnail" />
4746
</td>
4847
<td>
4948
<div
@@ -68,7 +67,7 @@ defineProps({
6867
</div>
6968
</td>
7069
<template v-for="tag in usedColumns" :key="tag">
71-
<td class="text-ellipsis overflow-hidden max-w-[300px]">
70+
<td class="text-ellipsis overflow-hidden max-w-[200px]">
7271
<span
7372
v-if="image[tag]"
7473
:class="
@@ -77,13 +76,13 @@ defineProps({
7776
: ''
7877
"
7978
>
80-
<span v-if="image[tag].binary">
79+
<span v-if="image[tag].binary" class="text-nowrap">
8180
{{ image[tag].binary.bytes }} bytes
8281
<span>
83-
{{ image[tag].binary.value.slice(0, 32) }}
82+
{{ image[tag].binary.value.slice(0, 20) }}
8483
</span>
8584
</span>
86-
<span v-else>
85+
<span v-else class="text-nowrap">
8786
{{
8887
typeof image[tag].value === "object"
8988
? image[tag].value.join(", ")

client/src/components/InfiniteScroller.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ onMounted(() => {
2424
<template>
2525
<div
2626
ref="infiniteScroller"
27-
class="card rounded max-h-[90vh] max-w-[75vw] overflow-auto customScroll"
27+
class="card rounded max-h-[calc(100vh-50px)] max-w-[calc(100vw-425px)] overflow-auto customScroll"
2828
>
2929
<slot></slot>
3030
<div ref="endOfTable"></div>

0 commit comments

Comments
 (0)