258 lines
9.6 KiB
Vue
258 lines
9.6 KiB
Vue
<script setup>
|
|
import { ref, computed } from "vue";
|
|
import { router, Link } from "@inertiajs/vue3";
|
|
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
|
|
import FileIcon from "@/Components/custom/FileIcon.vue";
|
|
import Checkbox from "@/Components/Checkbox.vue";
|
|
import DownloadButton from "@/Components/custom/DownloadButton.vue";
|
|
import MainBreadcrumbButton from "@/Components/custom/MainBreadcrumbButton.vue";
|
|
import UnshareButton from "@/Components/custom/UnshareButton.vue";
|
|
|
|
// defines refs
|
|
const allSelected = ref(false);
|
|
const fileSelectedStatus = ref({});
|
|
|
|
// defines props
|
|
const { files } = defineProps({
|
|
files: Object,
|
|
folder: Object,
|
|
ancestors: Array,
|
|
});
|
|
|
|
// defines computed properties
|
|
// gets a formatted array of all currently-selected files
|
|
const currentlySelected = computed(() => {
|
|
// casts the ref object of currently selected files to array
|
|
// { id: bool } becomes [id, bool]
|
|
let array = Object.entries(fileSelectedStatus.value);
|
|
// filters array for all the id's in [id, bool] where bool === true
|
|
array = array.filter((idBool) => idBool[1]);
|
|
// maps filtered array from [id, bool] to [id]
|
|
array = array.map((idBool) => idBool[0]);
|
|
// returns
|
|
return array;
|
|
});
|
|
|
|
// opens folder when clicked
|
|
const openFile = (file) => {
|
|
// if the file is a regular file, download on double click
|
|
if (!file.is_folder) {
|
|
// create a URL parameter string based on conditions
|
|
const parameters = new URLSearchParams();
|
|
// append value of all
|
|
parameters.append("all", false);
|
|
// append file
|
|
parameters.append("Ids[]", file.id);
|
|
|
|
// define opts
|
|
const opts = {
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
};
|
|
|
|
// fetch download link
|
|
fetch(route("file.downloadShared") + `?${parameters.toString()}`, opts)
|
|
// then get response
|
|
.then((res) => {
|
|
return res.json();
|
|
})
|
|
// then get the json
|
|
.then((json) => {
|
|
// if response contains no link, return - shouldn't be happening
|
|
if (!json.url) return;
|
|
// else create a link to the document for download
|
|
const link = document.createElement("a");
|
|
link.href = json.url;
|
|
link.download = json.filename;
|
|
// then access it
|
|
link.click();
|
|
});
|
|
return;
|
|
}
|
|
// else visit folder
|
|
router.visit(
|
|
route("sharedBy", {
|
|
folder: file.id,
|
|
})
|
|
);
|
|
};
|
|
|
|
// selects all files
|
|
const selectAll = () => {
|
|
files.data.forEach((file) => {
|
|
// set each fileSelectedStatus value to the value of allSelected
|
|
fileSelectedStatus.value[file.id] = allSelected.value;
|
|
});
|
|
};
|
|
|
|
// selects file
|
|
const selectFile = (file) => {
|
|
// get current value
|
|
const currentValue = fileSelectedStatus.value[file.id];
|
|
// invert
|
|
const newValue = !currentValue;
|
|
// set file's value
|
|
fileSelectedStatus.value[file.id] = newValue;
|
|
|
|
// if new value is negative, disable allSelected
|
|
if (!newValue) {
|
|
allSelected.value = false;
|
|
} else {
|
|
// else check if this "completes" the selection of all files in folder
|
|
let isallSelected = true;
|
|
|
|
files.data.forEach((entry) => {
|
|
// get current value at id
|
|
const status = fileSelectedStatus.value[entry.id];
|
|
// if the fileSelectedStatus value at id is falsy, set isallSelected to false
|
|
if (!status) isallSelected = false;
|
|
});
|
|
|
|
// update allSelected value
|
|
allSelected.value = isallSelected;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<AuthenticatedLayout>
|
|
<nav class="flex items-center justify-between mb-2">
|
|
<ol class="inline-flex items-center">
|
|
<MainBreadcrumbButton
|
|
:href="route('sharedBy')"
|
|
:active="$page.url === '/shared-by-me'"
|
|
>
|
|
Shared by Me
|
|
</MainBreadcrumbButton>
|
|
<li
|
|
v-if="ancestors"
|
|
v-for="(ancestor, index) of ancestors.data"
|
|
:key="ancestor.id"
|
|
class="inline-flex items-center"
|
|
>
|
|
<div class="flex items-center" v-if="ancestor.parent_id">
|
|
<div class="mx-2">➤</div>
|
|
<Link
|
|
v-if="index == ancestors.data.length - 1"
|
|
class="border-sky-600 border px-3 py-2 rounded bg-sky-600"
|
|
:href="route('sharedBy', { folder: ancestor.id })"
|
|
>
|
|
{{ ancestor.name }}
|
|
</Link>
|
|
<Link
|
|
v-else
|
|
class="border-gray-700 border px-3 py-2 rounded hover:border-sky-600"
|
|
:href="route('sharedBy', { folder: ancestor.id })"
|
|
>
|
|
{{ ancestor.name }}
|
|
</Link>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
<div class="flex gap-4">
|
|
<UnshareButton
|
|
:unshareall="allSelected"
|
|
:selected="currentlySelected"
|
|
/>
|
|
<DownloadButton
|
|
:getall="allSelected"
|
|
:selected="currentlySelected"
|
|
/>
|
|
</div>
|
|
</nav>
|
|
<div class="overflow-auto h-full w-full" v-if="files.data.length">
|
|
<table class="w-full border-separate">
|
|
<colgroup>
|
|
<col />
|
|
<col />
|
|
<col />
|
|
<col />
|
|
<col />
|
|
</colgroup>
|
|
<thead>
|
|
<tr class="sticky top-0 z-20">
|
|
<th class="p-3 rounded bg-zinc-600 rounded font-medium">
|
|
<Checkbox
|
|
v-model:checked="allSelected"
|
|
@change="selectAll()"
|
|
/>
|
|
</th>
|
|
<th
|
|
class="py-3 px-1 rounded bg-zinc-600 rounded font-medium"
|
|
>
|
|
Name
|
|
</th>
|
|
<th
|
|
class="py-3 px-1 rounded bg-zinc-600 rounded font-medium"
|
|
>
|
|
Modified
|
|
</th>
|
|
<th
|
|
class="py-3 px-1 rounded bg-zinc-600 rounded font-medium"
|
|
>
|
|
Shared With
|
|
</th>
|
|
<th
|
|
class="py-3 px-1 rounded bg-zinc-600 rounded font-medium"
|
|
>
|
|
Size
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="file of files.data"
|
|
:key="file.id"
|
|
@dblclick="openFile(file)"
|
|
>
|
|
<td
|
|
class="text-center whitespace-nowrap border-gray-700 border rounded hover:border-sky-600 hover:ring-sky-600 w-12"
|
|
@click="selectFile(file)"
|
|
>
|
|
<Checkbox
|
|
:checked="fileSelectedStatus[file.id]"
|
|
:v-model="
|
|
fileSelectedStatus[file.id] || allSelected
|
|
"
|
|
/>
|
|
</td>
|
|
<td
|
|
class="py-3 px-1 text-center whitespace-nowrap border-gray-700 border rounded hover:border-sky-600 hover:ring-sky-600 flex items-center justify-center relative"
|
|
>
|
|
<span
|
|
class="absolute left-0 bg-zinc-900 w-11 h-10 pl-1"
|
|
>
|
|
<FileIcon :file="file" />
|
|
</span>
|
|
<span class="pl-10 pr-10">
|
|
{{ file.name }}
|
|
</span>
|
|
</td>
|
|
<td
|
|
class="py-3 px-1 text-center whitespace-nowrap border-gray-700 border rounded hover:border-sky-600 hover:ring-sky-600"
|
|
>
|
|
{{ file.updated_at }}
|
|
</td>
|
|
<td
|
|
class="py-3 px-1 text-center whitespace-nowrap border-gray-700 border rounded hover:border-sky-600 hover:ring-sky-600"
|
|
>
|
|
{{ file.shared_with }}
|
|
</td>
|
|
<td
|
|
class="py-3 px-1 text-center whitespace-nowrap border-gray-700 border rounded hover:border-sky-600 hover:ring-sky-600"
|
|
>
|
|
{{ file.size }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="h-full" v-else>
|
|
<div
|
|
class="flex flex-col items-center justify-center h-full text-3xl"
|
|
>
|
|
This folder is empty
|
|
</div>
|
|
</div>
|
|
</AuthenticatedLayout>
|
|
</template>
|