Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload files Table #43

Merged
merged 61 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
0b375b6
Add a basic File part.
FledgeXu Aug 8, 2023
5c347d2
Add progress bar.
FledgeXu Aug 9, 2023
9ea4c62
Add deleting single file.
FledgeXu Aug 9, 2023
10b5f97
Add a UploadFilesComponent.
FledgeXu Aug 9, 2023
bfa6385
Add the uploading slot to ProjectView.
FledgeXu Aug 9, 2023
02a263f
Support deleting multiple files.
FledgeXu Aug 9, 2023
4fb3502
Add a placeholder edit button.
FledgeXu Aug 9, 2023
e90453e
Remove a wrong class.
FledgeXu Aug 9, 2023
70d1b09
Add a better information display.
FledgeXu Aug 9, 2023
7c6ba90
Add hidden function.
FledgeXu Aug 9, 2023
bcd3d2c
Change the state name.
FledgeXu Aug 9, 2023
5f28bc6
Show the quota.
FledgeXu Aug 9, 2023
6c934ee
Add better file size inform.
FledgeXu Aug 9, 2023
db08574
Add a basic metadata preview card.
FledgeXu Aug 9, 2023
869c89a
Split the file table row.
FledgeXu Aug 9, 2023
60654e8
Add an edit Mode switcher.
FledgeXu Aug 10, 2023
2345f73
Hide prompt when files are enough.
FledgeXu Aug 10, 2023
4575898
Beautify components.
FledgeXu Aug 10, 2023
1e20c24
Rest quota.
FledgeXu Aug 10, 2023
2dba8a4
Beautify the metadata preview card.
FledgeXu Aug 10, 2023
8c4f5be
Fix alert message index.
FledgeXu Aug 10, 2023
0fd6f16
Add human-filetypes.
FledgeXu Aug 10, 2023
cde41df
Delete unused code.
FledgeXu Aug 10, 2023
d8a6ad3
Add better date display.
FledgeXu Aug 10, 2023
995a7b9
Add the deletion modal.
FledgeXu Aug 11, 2023
2060da6
Add A feedback alert message on deletion.
FledgeXu Aug 11, 2023
202aaab
Add an UI feedback on draggable-zone.
FledgeXu Aug 11, 2023
914e4f1
Status has Icons now.
FledgeXu Aug 11, 2023
3f069f6
Split Table Header.
FledgeXu Aug 11, 2023
384e620
Update the z-index of AlertsComponent.
FledgeXu Aug 11, 2023
1a1b427
Add the sort function.
FledgeXu Aug 11, 2023
93fc2d8
Remove redundant watch.
FledgeXu Aug 11, 2023
e6fbf5e
Fix DragToStartField's border.
FledgeXu Aug 14, 2023
cff6f8d
Finished sorting.
FledgeXu Aug 14, 2023
1508d03
Remove the ungly border.
FledgeXu Aug 14, 2023
18ddc98
Split the Modal Component.
FledgeXu Aug 14, 2023
853b63e
Minimize in-template code.
FledgeXu Aug 14, 2023
e335e41
Fix the Status display bug.
FledgeXu Aug 15, 2023
489be6b
Let modal dialog scrollable.
FledgeXu Aug 15, 2023
41c84ac
Reject to upload zero size file.
FledgeXu Aug 15, 2023
05d4317
Add comments to explain partial.
FledgeXu Aug 15, 2023
e3ac79d
Rename beDeletedFiles to ToBeDeletedFiles.
FledgeXu Aug 15, 2023
d02bc98
Change alert message from warning to success when deleting files is s…
FledgeXu Aug 15, 2023
320388d
Rename RenderFile to ClientVisibleFile.
FledgeXu Aug 15, 2023
1e52b88
Fix checker not in middle.
FledgeXu Aug 15, 2023
018a7b1
Use computed variable to show the uploaded date.
FledgeXu Aug 15, 2023
aefdafd
Add a TODO to reminder change progress display part.
FledgeXu Aug 15, 2023
f099774
Change sort functions' names and orders.
FledgeXu Aug 15, 2023
27a828f
Format code.
FledgeXu Aug 15, 2023
dc76857
Rename increaseByUploadedDate to sortByUploadedDateDescending.
FledgeXu Aug 15, 2023
3086f18
Use Computed variable to dispaly authors.
FledgeXu Aug 15, 2023
04e5dec
Move the determine function to UploadFilesComponent.
FledgeXu Aug 15, 2023
8a0eae3
Display Error text on Tooltip.
FledgeXu Aug 15, 2023
3267073
Reject to upload folders.
FledgeXu Aug 15, 2023
8961a76
Make alert message sticky.
FledgeXu Aug 15, 2023
448ddce
Adjust quota and quota display.
FledgeXu Aug 15, 2023
7af186b
Format code.
FledgeXu Aug 15, 2023
712eb3e
Change the alert message.
FledgeXu Aug 15, 2023
0a51b71
Change the alert message about zero-size file.
FledgeXu Aug 15, 2023
5edd2eb
Remove invalid comments.
FledgeXu Aug 15, 2023
c190f7c
Adjust dev container quota.
FledgeXu Aug 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class BackendConf:
cookie_expiration_days = int(os.getenv("COOKIE_EXPIRATION_DAYS", "30"))
api_version_prefix = "/v1"
project_expire_after = datetime.timedelta(days=7)
project_quota = humanfriendly.parse_size(os.getenv("PROJECT_QUOTA", "100MiB"))
project_quota = humanfriendly.parse_size(os.getenv("PROJECT_QUOTA", "100MB"))

chunk_size = humanfriendly.parse_size(os.getenv("CHUNK_SIZE", "2MiB"))

Expand Down
4 changes: 2 additions & 2 deletions dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ services:
- 8081:80
environment:
- NAUTILUS_WEB_API=http://localhost:8080/v1
- NAUTILUS_FILE_QUOTA=104857600
- NAUTILUS_PROJECT_QUOTA=104857600
- NAUTILUS_FILE_QUOTA=100MB
- NAUTILUS_PROJECT_QUOTA=100MB
depends_on:
- database
backend-tools:
Expand Down
4 changes: 4 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
"@tsconfig/node18": "^2.0.1",
"@types/bootstrap": "^5.2.6",
"@types/node": "^18.16.8",
"@types/uuid": "^9.0.2",
"@vitejs/plugin-vue": "^4.2.3",
Expand All @@ -37,6 +38,9 @@
"@vue/tsconfig": "^0.4.0",
"eslint": "^8.39.0",
"eslint-plugin-vue": "^9.11.0",
"filesize": "^10.0.9",
"human-filetypes": "^0.2.1",
"moment": "^2.29.4",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.8",
"typescript": "~5.0.4",
Expand Down
4 changes: 2 additions & 2 deletions frontend/public/environ.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"NAUTILUS_WEB_API": "http://localhost:8080/v1",
"NAUTILUS_FILE_QUOTA": 104857600,
"NAUTILUS_PROJECT_QUOTA": 104857600
"NAUTILUS_FILE_QUOTA": 100000000,
"NAUTILUS_PROJECT_QUOTA": 100000000
}
73 changes: 0 additions & 73 deletions frontend/src/assets/base.css

This file was deleted.

28 changes: 16 additions & 12 deletions frontend/src/components/AlertsComponent.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
<template>
<div class="position-absolute top-0 end-0 mt-1 me-1">
<div v-for="[key, item] in storeApp.alertMessages" :key="key">
<div class="alert px-1" :class="'alert-' + item.type" role="alert">
<div class="container">
<div class="row justify-content-between">
<div class="col-md-auto">
{{ item.message }}
</div>
<div class="col-md-auto">
<button type="button" class="btn p-0" @click="storeApp.clearError(key)">
<font-awesome-icon :icon="['fas', 'xmark']" />
</button>
<!-- The alert component should have the same z-index as modal-backdrop. -->
<!-- See: https://getbootstrap.com/docs/5.3/layout/z-index/ -->
<div class="position-fixed top-0 end-0 mt-1 me-1" style="z-index: 1050">
<div class="position-sticky">
<div v-for="[key, item] in storeApp.alertMessages" :key="key">
<div class="alert px-1" :class="'alert-' + item.type" role="alert">
<div class="container">
<div class="row justify-content-between">
<div class="col-md-auto">
{{ item.message }}
</div>
<div class="col-md-auto">
<button type="button" class="btn p-0" @click="storeApp.clearError(key)">
<font-awesome-icon :icon="['fas', 'xmark']" />
</button>
</div>
</div>
</div>
</div>
Expand Down
66 changes: 16 additions & 50 deletions frontend/src/components/DragToStartField.vue
Original file line number Diff line number Diff line change
@@ -1,62 +1,33 @@
<template>
<div class="d-flex justify-content-md-center">
<div
class="card border-3 border-3 rounded-3 drop"
:data-active="isActive"
@dragenter.prevent="setActive"
@dragover.prevent="setActive"
@dragleave.prevent="setInactive"
@drop.prevent="dropFiles"
:class="{ 'bg-light': isActive }"
>
<div class="card-body d-flex justify-content-center align-items-center">
<h3 class="card-title">Drop File to Start!</h3>
<UploadFilesComponent @drop-files-handler="dropFiles" @update-is-active="updateIsActive">
<div
class="card border-3 rounded-3 drop"
:data-active="isActive"
:class="{ 'bg-light': isActive }"
>
<div class="card-body d-flex justify-content-center align-items-center">
<h3 class="card-title">Drop File to Start!</h3>
</div>
</div>
</div>
</UploadFilesComponent>
</div>
</template>

<script setup lang="ts">
import { useAppStore } from '@/stores/stores'
import { ref } from 'vue'
import UploadFilesComponent from './UploadFilesComponent.vue'
const isActive = ref(false)
const storeApp = useAppStore()

function updateIsActive(newValue: boolean) {
isActive.value = newValue
}
const emit = defineEmits<{
dropFilesHandler: [files: FileList, uploadFileSize: number]
}>()

function setActive() {
isActive.value = true
}
function setInactive() {
isActive.value = false
}
async function dropFiles(event: DragEvent) {
isActive.value = false
let files = event.dataTransfer?.files

if (files == undefined) {
return
}

let totalSize = 0

for (const file of files) {
if (file.size > storeApp.constants.env.NAUTILUS_FILE_QUOTA) {
storeApp.alertsWarning(`${file.name}'s exceeds the quota`)
return
}

if (file.size + totalSize > storeApp.constants.env.NAUTILUS_PROJECT_QUOTA) {
storeApp.alertsWarning('Uploading files exceed the quota')
return
}

totalSize += file.size
}

emit('dropFilesHandler', files, totalSize)
async function dropFiles(files: FileList, uploadFileSize: number) {
emit('dropFilesHandler', files, uploadFileSize)
}
</script>

Expand All @@ -68,9 +39,4 @@ async function dropFiles(event: DragEvent) {
border-color: var(--main-color);
color: var(--main-color);
}

.isActive {
background-color: var(--main-color);
opacity: 0.6;
}
</style>
135 changes: 135 additions & 0 deletions frontend/src/components/FileTableHeaderComponent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<template>
<tr>
<th scope="col">
<input
class="form-check-input"
type="checkbox"
value=""
:indeterminate="isIndeterminate"
:checked="isCheckedAll"
@change.prevent="toggleSelectAllFiles"
/>
</th>
<th scope="col">
<SortButton
title="Name"
:increase-function="sortByName"
:decrease-function="sortByNameReversed"
@update-compare-function="updateCompareFunction"
/>
</th>
<th scope=" col">
<SortButton
title="File Size"
:increase-function="sortBySizeDescending"
:decrease-function="sortBySizeAscending"
@update-compare-function="updateCompareFunction"
/>
</th>
<th scope="col">
<SortButton
title="Kind"
:increase-function="sortByKindNameReversed"
:decrease-function="sortByKindName"
@update-compare-function="updateCompareFunction"
/>
</th>
<th scope="col">
<SortButton
title="Date Uploaded"
:increase-function="sortByUploadedDateDescending"
:decrease-function="sortByUploadedDateAscending"
@update-compare-function="updateCompareFunction"
/>
</th>
<th scope="col">
<SortButton
title="Status"
:increase-function="sortByStatusNameReversed"
:decrease-function="sortByStatusName"
@update-compare-function="updateCompareFunction"
/>
</th>
<th scope="align-middle">Metadata</th>
<th scope="col">
<button
type="button"
class="btn border-0"
:disabled="isDisableDeleteButton"
@click.prevent="emit('deleteSelectedFiles')"
>
<font-awesome-icon :icon="['fas', 'trash']" />
</button>
</th>
</tr>
</template>

<script setup lang="ts">
import type { ClientVisibleFile } from '@/constants'
import SortButton from './SortButton.vue'
import type { CompareFunctionType } from '@/constants'
import { computed } from 'vue'

const props = defineProps<{
selectedFiles: Map<string, boolean>
files: Map<string, ClientVisibleFile>
}>()

const emit = defineEmits<{
updateSelectFiles: [newValue: Map<string, boolean>]
deleteSelectedFiles: []
updateCompareFunction: [
newFunction: (a: [string, ClientVisibleFile], b: [string, ClientVisibleFile]) => number
]
}>()

const isIndeterminate = computed(
() => props.selectedFiles.size != 0 && props.selectedFiles.size < props.files.size
)
const isCheckedAll = computed(
() => props.selectedFiles.size != 0 && props.selectedFiles.size == props.files.size
)
const isDisableDeleteButton = computed(() => props.selectedFiles.size == 0)

/** Start to define compare functions **/
const sortByName: CompareFunctionType = (a, b) => (a[1].file.title > b[1].file.title ? 1 : -1)
const sortByNameReversed: CompareFunctionType = (a, b) =>
a[1].file.title < b[1].file.title ? 1 : -1

const sortBySizeAscending: CompareFunctionType = (a, b) =>
a[1].file.filesize > b[1].file.filesize ? 1 : -1
const sortBySizeDescending: CompareFunctionType = (a, b) =>
a[1].file.filesize < b[1].file.filesize ? 1 : -1

const sortByKindName: CompareFunctionType = (a, b) => (a[1].file.type > b[1].file.type ? 1 : -1)
const sortByKindNameReversed: CompareFunctionType = (a, b) =>
a[1].file.type < b[1].file.type ? 1 : -1

const sortByUploadedDateAscending: CompareFunctionType = (a, b) =>
a[1].file.uploaded_on > b[1].file.uploaded_on ? 1 : -1
const sortByUploadedDateDescending: CompareFunctionType = (a, b) =>
a[1].file.uploaded_on < b[1].file.uploaded_on ? 1 : -1

const sortByStatusName: CompareFunctionType = (a, b) =>
a[1].file.status > b[1].file.status ? 1 : -1
const sortByStatusNameReversed: CompareFunctionType = (a, b) =>
a[1].file.status < b[1].file.status ? 1 : -1

/** End of definition**/

async function toggleSelectAllFiles() {
let newSelectedFiles: Map<string, boolean> = new Map()
if (props.selectedFiles.size < props.files.size) {
props.files.forEach((_, key) => {
newSelectedFiles.set(key, true)
})
} else {
newSelectedFiles.clear()
}
emit('updateSelectFiles', newSelectedFiles)
}

function updateCompareFunction(newValue: CompareFunctionType) {
emit('updateCompareFunction', newValue)
}
</script>
Loading