laravel-vue-file-share/resources/js/Pages/SharedBy.vue
2023-10-17 22:45:04 -07:00

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">&#x27A4;</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>