Skip to content
Snippets Groups Projects

Filter Buckets and objects by their name

Merged Daniel Göbel requested to merge feature/8-10-filter-by-name into development
2 files
+ 77
34
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -17,7 +17,7 @@ import CopyObjectModal from "@/components/Modals/CopyObjectModal.vue";
@@ -17,7 +17,7 @@ import CopyObjectModal from "@/components/Modals/CopyObjectModal.vue";
import PermissionModal from "@/components/Modals/PermissionModal.vue";
import PermissionModal from "@/components/Modals/PermissionModal.vue";
import ObjectDetailModal from "@/components/Modals/ObjectDetailModal.vue";
import ObjectDetailModal from "@/components/Modals/ObjectDetailModal.vue";
import CreateFolderModal from "@/components/Modals/CreateFolderModal.vue";
import CreateFolderModal from "@/components/Modals/CreateFolderModal.vue";
import DeleteModal from "@/components/Modals/DeleteModal.vue"
import DeleteModal from "@/components/Modals/DeleteModal.vue";
import {
import {
S3Client,
S3Client,
DeleteObjectCommand,
DeleteObjectCommand,
@@ -114,16 +114,25 @@ type FolderTree = {
@@ -114,16 +114,25 @@ type FolderTree = {
// Reactive State
// Reactive State
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
 
 
const deleteObjectsState = reactive({
 
deletedItem: "",
 
potentialObjectToDelete: "",
 
deleteFolder: true,
 
} as {
 
deletedItem: string;
 
potentialObjectToDelete: string;
 
deleteFolder: boolean;
 
});
 
const objectState = reactive({
const objectState = reactive({
objects: [],
objects: [],
loading: true,
loading: true,
 
filterString: "",
bucketNotFoundError: false,
bucketNotFoundError: false,
bucketPermissionError: false,
bucketPermissionError: false,
createdPermission: undefined,
createdPermission: undefined,
deletedItem: "",
editObjectKey: "",
editObjectKey: "",
potentialObjectToDelete: "",
deleteFolder: true,
copyObject: {
copyObject: {
key: "",
key: "",
size: 0,
size: 0,
@@ -139,13 +148,11 @@ const objectState = reactive({
@@ -139,13 +148,11 @@ const objectState = reactive({
} as {
} as {
objects: S3ObjectMetaInformation[];
objects: S3ObjectMetaInformation[];
loading: boolean;
loading: boolean;
 
filterString: string;
bucketNotFoundError: boolean;
bucketNotFoundError: boolean;
bucketPermissionError: boolean;
bucketPermissionError: boolean;
createdPermission: undefined | BucketPermission;
createdPermission: undefined | BucketPermission;
deletedItem: string;
editObjectKey: string;
editObjectKey: string;
potentialObjectToDelete: string;
deleteFolder: boolean;
copyObject: S3ObjectMetaInformation;
copyObject: S3ObjectMetaInformation;
viewDetailObject: S3ObjectMetaInformation;
viewDetailObject: S3ObjectMetaInformation;
});
});
@@ -164,6 +171,15 @@ watch(
@@ -164,6 +171,15 @@ watch(
// Computed Properties
// Computed Properties
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
 
const filteredObjects: ComputedRef<(S3ObjectWithFolder | S3PseudoFolder)[]> =
 
computed(() => {
 
return objectState.filterString.length > 0
 
? visibleObjects.value.filter((obj) =>
 
obj.key.includes(objectState.filterString)
 
)
 
: visibleObjects.value;
 
});
 
const folderStructure: ComputedRef<FolderTree> = computed(() => {
const folderStructure: ComputedRef<FolderTree> = computed(() => {
/**
/**
* Store the entire folder structure in a bucket in a tree-like data structure
* Store the entire folder structure in a bucket in a tree-like data structure
@@ -394,8 +410,8 @@ function objectCopied(copiedObject: S3ObjectMetaInformation) {
@@ -394,8 +410,8 @@ function objectCopied(copiedObject: S3ObjectMetaInformation) {
}
}
function deleteObject(key: string) {
function deleteObject(key: string) {
objectState.potentialObjectToDelete = key;
deleteObjectsState.potentialObjectToDelete = key;
objectState.deleteFolder = false;
deleteObjectsState.deleteFolder = false;
}
}
/**
/**
@@ -411,7 +427,7 @@ function confirmedDeleteObject(key: string) {
@@ -411,7 +427,7 @@ function confirmedDeleteObject(key: string) {
.send(command)
.send(command)
.then(() => {
.then(() => {
const splittedKey = key.split("/");
const splittedKey = key.split("/");
objectState.deletedItem = splittedKey[splittedKey.length - 1];
deleteObjectsState.deletedItem = splittedKey[splittedKey.length - 1];
successToast?.show();
successToast?.show();
objectState.objects = objectState.objects.filter(
objectState.objects = objectState.objects.filter(
(obj) => obj.key !== key
(obj) => obj.key !== key
@@ -443,8 +459,8 @@ async function downloadObject(key: string, bucket: string) {
@@ -443,8 +459,8 @@ async function downloadObject(key: string, bucket: string) {
}
}
function deleteFolder(folderPath: string) {
function deleteFolder(folderPath: string) {
objectState.potentialObjectToDelete = folderPath;
deleteObjectsState.potentialObjectToDelete = folderPath;
objectState.deleteFolder = true;
deleteObjectsState.deleteFolder = true;
}
}
/**
/**
@@ -466,7 +482,7 @@ function confirmedDeleteFolder(folderPath: string) {
@@ -466,7 +482,7 @@ function confirmedDeleteFolder(folderPath: string) {
.send(command)
.send(command)
.then(() => {
.then(() => {
const splittedPath = folderPath.split("/");
const splittedPath = folderPath.split("/");
objectState.deletedItem = splittedPath[splittedPath.length - 2];
deleteObjectsState.deletedItem = splittedPath[splittedPath.length - 2];
successToast?.show();
successToast?.show();
objectState.objects = objectState.objects.filter(
objectState.objects = objectState.objects.filter(
(obj) => !obj.key.startsWith(folderPath)
(obj) => !obj.key.startsWith(folderPath)
@@ -510,7 +526,7 @@ watch(
@@ -510,7 +526,7 @@ watch(
>
>
<div class="d-flex">
<div class="d-flex">
<div class="toast-body">
<div class="toast-body">
Successfully deleted {{ objectState.deletedItem }}
Successfully deleted {{ deleteObjectsState.deletedItem }}
</div>
</div>
<button
<button
type="button"
type="button"
@@ -524,9 +540,13 @@ watch(
@@ -524,9 +540,13 @@ watch(
<DeleteModal
<DeleteModal
modalID="delete-object-modal"
modalID="delete-object-modal"
modal-label="some-label"
modal-label="some-label"
:object-name-delete="objectState.potentialObjectToDelete"
:object-name-delete="deleteObjectsState.potentialObjectToDelete"
:back-modal-id="undefined"
:back-modal-id="undefined"
@confirm-delete="objectState.deleteFolder ? confirmedDeleteFolder(objectState.potentialObjectToDelete) : confirmedDeleteObject(objectState.potentialObjectToDelete)"
@confirm-delete="
 
deleteObjectsState.deleteFolder
 
? confirmedDeleteFolder(deleteObjectsState.potentialObjectToDelete)
 
: confirmedDeleteObject(deleteObjectsState.potentialObjectToDelete)
 
"
/>
/>
<!-- Navbar Breadcrumb -->
<!-- Navbar Breadcrumb -->
<nav aria-label="breadcrumb" class="fs-2">
<nav aria-label="breadcrumb" class="fs-2">
@@ -577,7 +597,7 @@ watch(
@@ -577,7 +597,7 @@ watch(
placeholder="Search Objects"
placeholder="Search Objects"
aria-label="Search Objects"
aria-label="Search Objects"
aria-describedby="objects-search-wrapping"
aria-describedby="objects-search-wrapping"
disabled
v-model.trim="objectState.filterString"
/>
/>
</div>
</div>
</div>
</div>
@@ -723,8 +743,8 @@ watch(
@@ -723,8 +743,8 @@ watch(
<td></td>
<td></td>
</tr>
</tr>
</tbody>
</tbody>
<!-- Table body when no objects are in the bcuket -->
<!-- Table body when no objects are in the bucket -->
<tbody v-else-if="visibleObjects.length === 0">
<tbody v-else-if="filteredObjects.length === 0">
<tr>
<tr>
<td colspan="4" class="text-center fst-italic fw-light">
<td colspan="4" class="text-center fst-italic fw-light">
No objects to display
No objects to display
@@ -733,7 +753,7 @@ watch(
@@ -733,7 +753,7 @@ watch(
</tbody>
</tbody>
<!-- Table body when showing objects -->
<!-- Table body when showing objects -->
<tbody v-else>
<tbody v-else>
<tr v-for="obj in visibleObjects" :key="obj.key">
<tr v-for="obj in filteredObjects" :key="obj.key">
<th scope="row" class="text-truncate">
<th scope="row" class="text-truncate">
<!-- Show file name if row is an object -->
<!-- Show file name if row is an object -->
<div v-if="isS3Object(obj)">{{ obj.pseudoFileName }}</div>
<div v-if="isS3Object(obj)">{{ obj.pseudoFileName }}</div>
Loading