web/satellite: use pinia object browser module instead of old vuex module
Start using object browser pinia module instead of old files vuex module. Also removed vuex related code. Note: dependency will be removed in a follow-up change Change-Id: I78cfb62a1ecc32bd86381bd3bfd3be4bd0f38e14
This commit is contained in:
parent
2405bc8f3b
commit
8d31e13db6
@ -64,7 +64,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { Download } from '@/utils/download';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
@ -83,7 +83,6 @@ const props = defineProps<{
|
||||
onContinue: () => void;
|
||||
}>();
|
||||
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -45,7 +45,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useStore } from '@/utils/hooks';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
|
||||
@ -58,8 +57,6 @@ const props = defineProps<{
|
||||
onContinue: () => void;
|
||||
}>();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const isDontShow = ref<boolean>(false);
|
||||
|
||||
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
|
@ -48,8 +48,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useStore } from '@/utils/hooks';
|
||||
|
||||
import ButtonsContainer from '@/components/accessGrants/createFlow/components/ButtonsContainer.vue';
|
||||
import Toggle from '@/components/accessGrants/createFlow/components/Toggle.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -64,8 +62,6 @@ const props = defineProps<{
|
||||
onContinue: () => void;
|
||||
}>();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const isPassphraseSaved = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { Download } from '@/utils/download';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
@ -92,7 +92,6 @@ const props = defineProps<{
|
||||
onContinue: () => void;
|
||||
}>();
|
||||
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const isPassphraseSaved = ref<boolean>(false);
|
||||
|
@ -77,7 +77,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { Download } from '@/utils/download';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
@ -94,7 +94,6 @@ const props = defineProps<{
|
||||
credentials: EdgeCredentials;
|
||||
}>();
|
||||
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -31,7 +31,7 @@ import {
|
||||
PaymentsHistoryItemType,
|
||||
} from '@/types/payments';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { useBillingStore } from '@/store/modules/billingStore';
|
||||
|
||||
import BillingHistoryHeader
|
||||
@ -41,7 +41,6 @@ import BillingHistoryItem
|
||||
import VTable from '@/components/common/VTable.vue';
|
||||
|
||||
const billingStore = useBillingStore();
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
|
||||
async function fetchHistory(): Promise<void> {
|
||||
|
@ -35,8 +35,6 @@
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { CreditCard } from '@/types/payments';
|
||||
import { useStore } from '@/utils/hooks';
|
||||
import { useBillingStore } from '@/store/modules/billingStore';
|
||||
|
||||
import AmericanExpressIcon from '@/../static/images/payments/cardIcons/americanexpress.svg';
|
||||
import DefaultIcon from '@/../static/images/payments/cardIcons/default.svg';
|
||||
@ -63,9 +61,6 @@ const props = withDefaults(defineProps<{
|
||||
creditCard: () => new CreditCard(),
|
||||
});
|
||||
|
||||
const billingStore = useBillingStore();
|
||||
const store = useStore();
|
||||
|
||||
const emit = defineEmits(['edit', 'remove']);
|
||||
|
||||
const cardIcon = computed(() => {
|
||||
@ -79,13 +74,6 @@ function edit(): void {
|
||||
function remove(): void {
|
||||
emit('remove', props.creditCard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle card selection dialog.
|
||||
*/
|
||||
function toggleSelection(): void {
|
||||
billingStore.toggleCardSelection(props.creditCard.id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -50,9 +50,10 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useRouter, useStore } from '@/utils/hooks';
|
||||
import { useRouter } from '@/utils/hooks';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
const router = useRouter();
|
||||
|
||||
const emit = defineEmits(['onUpdate', 'bucketClick']);
|
||||
@ -61,14 +62,14 @@ const emit = defineEmits(['onUpdate', 'bucketClick']);
|
||||
* Retrieves the current bucket name from the store.
|
||||
*/
|
||||
const bucketName = computed((): string => {
|
||||
return store.state.files.bucket;
|
||||
return obStore.state.bucket;
|
||||
});
|
||||
|
||||
/**
|
||||
* Retrieves the current path from the store and creates an array of folders for the bread crumbs that the user can click on.
|
||||
*/
|
||||
const crumbs = computed((): string[] => {
|
||||
let path: string[] = store.state.files.path.split('/');
|
||||
let path: string[] = obStore.state.path.split('/');
|
||||
path =
|
||||
path.length > 1
|
||||
? [bucketName.value, ...path.slice(0, path.length - 1)]
|
||||
@ -84,7 +85,7 @@ function bucketClick() {
|
||||
* Redirects to partial upload to bucket buckets path.
|
||||
*/
|
||||
async function redirectToCrumb(idx: number): Promise<void> {
|
||||
await router.push(link(idx)).catch(err => {});
|
||||
await router.push(link(idx)).catch(_ => {});
|
||||
emit('onUpdate');
|
||||
}
|
||||
|
||||
@ -96,7 +97,7 @@ function link(idx: number): string {
|
||||
|
||||
if (idx > 0) path = crumbs.value.slice(1, idx + 1).join('/') + '/';
|
||||
|
||||
return store.state.files.browserRoot + path;
|
||||
return obStore.state.browserRoot + path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,10 +203,10 @@ import BreadCrumbs from './BreadCrumbs.vue';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { Bucket } from '@/types/buckets';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { BrowserObject } from '@/store/modules/files';
|
||||
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
|
||||
@ -222,7 +222,8 @@ import UploadIcon from '@/../static/images/browser/upload.svg';
|
||||
|
||||
const bucketsStore = useBucketsStore();
|
||||
const appStore = useAppStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
const notify = useNotify();
|
||||
@ -241,35 +242,35 @@ const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
* Check if the s3 client has been initialized in the store.
|
||||
*/
|
||||
const isInitialized = computed((): boolean => {
|
||||
return store.getters['files/isInitialized'];
|
||||
return obStore.isInitialized;
|
||||
});
|
||||
|
||||
/**
|
||||
* Retrieve the current path from the store.
|
||||
*/
|
||||
const path = computed((): string => {
|
||||
return store.state.files.path;
|
||||
return obStore.state.path;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return files that are currently being uploaded from the store.
|
||||
*/
|
||||
const filesUploading = computed((): BrowserObject[] => {
|
||||
return store.state.files.uploading;
|
||||
return obStore.state.uploading;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return file browser path from store.
|
||||
*/
|
||||
const currentPath = computed((): string => {
|
||||
return store.state.files.path;
|
||||
return obStore.state.path;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return locked files number.
|
||||
*/
|
||||
const lockedFilesNumber = computed((): number => {
|
||||
const ownObjectsCount = store.state.files.objectsCount;
|
||||
const ownObjectsCount = obStore.state.objectsCount;
|
||||
|
||||
return objectsCount.value - ownObjectsCount;
|
||||
});
|
||||
@ -278,7 +279,7 @@ const lockedFilesNumber = computed((): number => {
|
||||
* Returns bucket objects count from store.
|
||||
*/
|
||||
const objectsCount = computed((): number => {
|
||||
const name: string = store.state.files.bucket;
|
||||
const name: string = obStore.state.bucket;
|
||||
const data: Bucket | undefined = bucketsStore.state.page.buckets.find((bucket: Bucket) => bucket.name === name);
|
||||
|
||||
return data?.objectCount || 0;
|
||||
@ -319,7 +320,7 @@ const formattedFilesWaitingToBeUploaded = computed((): string => {
|
||||
});
|
||||
|
||||
const bucketName = computed((): string => {
|
||||
return store.state.files.bucket;
|
||||
return obStore.state.bucket;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -329,9 +330,9 @@ const allFilesSelected = computed((): boolean => {
|
||||
if (files.value.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const shiftSelectedFiles = store.state.files.shiftSelectedFiles;
|
||||
const selectedFiles = store.state.files.selectedFiles;
|
||||
const selectedAnchorFile = store.state.files.selectedAnchorFile;
|
||||
const shiftSelectedFiles = obStore.state.shiftSelectedFiles;
|
||||
const selectedFiles = obStore.state.selectedFiles;
|
||||
const selectedAnchorFile = obStore.state.selectedAnchorFile;
|
||||
const allSelectedFiles = [
|
||||
...selectedFiles,
|
||||
...shiftSelectedFiles,
|
||||
@ -344,7 +345,7 @@ const allFilesSelected = computed((): boolean => {
|
||||
});
|
||||
|
||||
const files = computed((): BrowserObject[] => {
|
||||
return store.getters['files/sortedFiles'];
|
||||
return obStore.sortedFiles;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -395,7 +396,7 @@ async function onBack(): Promise<void> {
|
||||
|
||||
async function onRouteChange(): Promise<void> {
|
||||
routePath.value = calculateRoutePath();
|
||||
await store.dispatch('files/closeDropdown');
|
||||
obStore.closeDropdown();
|
||||
await list(routePath.value);
|
||||
}
|
||||
|
||||
@ -403,11 +404,11 @@ async function onRouteChange(): Promise<void> {
|
||||
* Close modal, file share modal, dropdown, and remove all selected files from the store.
|
||||
*/
|
||||
function closeModalDropdown(): void {
|
||||
if (store.state.files.openedDropdown) {
|
||||
store.dispatch('files/closeDropdown');
|
||||
if (obStore.state.openedDropdown) {
|
||||
obStore.closeDropdown();
|
||||
}
|
||||
|
||||
store.dispatch('files/clearAllSelectedFiles');
|
||||
obStore.clearAllSelectedFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -430,7 +431,7 @@ function filename(file: BrowserObject): string {
|
||||
* Upload the current selected or dragged-and-dropped file.
|
||||
*/
|
||||
async function upload(e: Event): Promise<void> {
|
||||
await store.dispatch('files/upload', { e });
|
||||
await obStore.upload({ e });
|
||||
await analytics.eventTriggered(AnalyticsEvent.OBJECT_UPLOADED);
|
||||
const target = e.target as HTMLInputElement;
|
||||
target.value = '';
|
||||
@ -440,7 +441,7 @@ async function upload(e: Event): Promise<void> {
|
||||
* Cancel the upload of the current file that's passed in as an argument.
|
||||
*/
|
||||
function cancelUpload(fileName: string): void {
|
||||
store.dispatch('files/cancelUpload', fileName);
|
||||
obStore.cancelUpload(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -448,9 +449,7 @@ function cancelUpload(fileName: string): void {
|
||||
*/
|
||||
async function list(path: string): Promise<void> {
|
||||
try {
|
||||
await store.dispatch('files/list', path, {
|
||||
root: true,
|
||||
});
|
||||
await obStore.list(path);
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.FILE_BROWSER_LIST_CALL);
|
||||
}
|
||||
@ -503,16 +502,17 @@ async function goToBuckets(): Promise<void> {
|
||||
/**
|
||||
* Toggles the selection of all files.
|
||||
* */
|
||||
async function toggleSelectAllFiles(): Promise<void> {
|
||||
function toggleSelectAllFiles(): void {
|
||||
if (files.value.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (allFilesSelected.value) {
|
||||
await store.dispatch('files/clearAllSelectedFiles');
|
||||
obStore.clearAllSelectedFiles();
|
||||
} else {
|
||||
await store.dispatch('files/clearAllSelectedFiles');
|
||||
store.commit('files/setSelectedAnchorFile', files.value[0]);
|
||||
await store.dispatch('files/updateSelectedFiles', files.value.slice(1, files.value.length));
|
||||
obStore.clearAllSelectedFiles();
|
||||
obStore.setSelectedAnchorFile(files.value[0]);
|
||||
obStore.updateSelectedFiles(files.value.slice(1, files.value.length));
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,7 +531,7 @@ onBeforeMount(async () => {
|
||||
}
|
||||
|
||||
// clear previous file selections.
|
||||
store.dispatch('files/clearAllSelectedFiles');
|
||||
obStore.clearAllSelectedFiles();
|
||||
|
||||
// display the spinner while files are being fetched
|
||||
fetchingFilesSpinner.value = true;
|
||||
@ -539,7 +539,7 @@ onBeforeMount(async () => {
|
||||
try {
|
||||
await Promise.all([
|
||||
list(''),
|
||||
store.dispatch('files/getObjectCount'),
|
||||
obStore.getObjectCount(),
|
||||
]);
|
||||
} catch (err) {
|
||||
await notify.error(err.message, AnalyticsErrorEventSource.FILE_BROWSER_LIST_CALL);
|
||||
|
@ -93,37 +93,38 @@
|
||||
import { Fragment } from 'vue-fragment';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useStore } from '@/utils/hooks';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import AscIcon from '@/../static/images/objects/asc.svg';
|
||||
import CloseIcon from '@/../static/images/common/closeCross.svg';
|
||||
import DescIcon from '@/../static/images/objects/desc.svg';
|
||||
import DeleteIcon from '@/../static/images/objects/delete.svg';
|
||||
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const hover = ref('');
|
||||
|
||||
function fromFilesStore(prop: string): string {
|
||||
return store.state.files[prop];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the trashcan to delete selected files/folder should be displayed.
|
||||
*/
|
||||
const filesToDelete = computed((): boolean => {
|
||||
return (!!store.state.files.selectedAnchorFile || (
|
||||
!!store.state.files.unselectedAnchorFile &&
|
||||
(store.state.files.selectedFiles.length > 0 ||
|
||||
store.state.files.shiftSelectedFiles.length > 0)
|
||||
));
|
||||
return (
|
||||
!!obStore.state.selectedAnchorFile ||
|
||||
(
|
||||
!!obStore.state.unselectedAnchorFile &&
|
||||
(
|
||||
obStore.state.selectedFiles.length > 0 ||
|
||||
obStore.state.shiftSelectedFiles.length > 0
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Check if the files/folders deletion dropdown should be displayed.
|
||||
*/
|
||||
const isDropdownDisplayed = computed((): boolean => {
|
||||
return store.state.files.openedDropdown === 'FileBrowser';
|
||||
return obStore.state.openedDropdown === 'FileBrowser';
|
||||
});
|
||||
|
||||
const nameSortData = computed((): { isHidden: boolean, isDesc: boolean } => {
|
||||
@ -151,14 +152,14 @@ const dateSortData = computed((): { isHidden: boolean, isDesc: boolean } => {
|
||||
* Check if a heading is sorted in descending order.
|
||||
*/
|
||||
function isDesc(heading: string): boolean {
|
||||
return fromFilesStore('headingSorted') === heading && fromFilesStore('orderBy') === 'desc';
|
||||
return obStore.state.headingSorted === heading && obStore.state.orderBy === 'desc';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if sorting arrow should be displayed.
|
||||
*/
|
||||
function showArrow(heading: string): boolean {
|
||||
return fromFilesStore('headingSorted') === heading || hover.value === heading;
|
||||
return obStore.state.headingSorted === heading || hover.value === heading;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +173,7 @@ function mouseOver(heading: string): void {
|
||||
* Set the heading for files/folders to be sorted by in the store.
|
||||
*/
|
||||
function sortBy(heading: string): void {
|
||||
store.commit('files/sort', heading);
|
||||
obStore.sort(heading);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,22 +187,22 @@ function mouseLeave(): void {
|
||||
* Open the deletion of files/folders dropdown.
|
||||
*/
|
||||
function deleteSelectedDropdown(): void {
|
||||
store.dispatch('files/openFileBrowserDropdown');
|
||||
obStore.openFileBrowserDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the selected files/folders.
|
||||
*/
|
||||
function confirmDeleteSelection(): void {
|
||||
store.dispatch('files/deleteSelected');
|
||||
store.dispatch('files/closeDropdown');
|
||||
obStore.deleteSelected();
|
||||
obStore.closeDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort files/folder selected for deletion.
|
||||
*/
|
||||
function cancelDeleteSelection(): void {
|
||||
store.dispatch('files/closeDropdown');
|
||||
obStore.closeDropdown();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -112,10 +112,10 @@
|
||||
import { computed, ref } from 'vue';
|
||||
import prettyBytes from 'pretty-bytes';
|
||||
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { BrowserObject } from '@/store/modules/files';
|
||||
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
|
||||
import TableItem from '@/components/common/TableItem.vue';
|
||||
@ -128,7 +128,7 @@ import DotsIcon from '@/../static/images/objects/dots.svg';
|
||||
import CloseIcon from '@/../static/images/common/closeCross.svg';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
const notify = useNotify();
|
||||
const router = useRouter();
|
||||
|
||||
@ -189,15 +189,15 @@ const uploadDate = computed((): string => {
|
||||
* Check with the store to see if the dropdown is open for the current file/folder.
|
||||
*/
|
||||
const dropdownOpen = computed((): boolean => {
|
||||
return store.state.files.openedDropdown === props.file.Key;
|
||||
return obStore.state.openedDropdown === props.file.Key;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return a link to the current folder for navigation.
|
||||
*/
|
||||
const link = computed((): string => {
|
||||
const browserRoot = store.state.files.browserRoot;
|
||||
const uriParts = (store.state.files.path + props.file.Key).split('/');
|
||||
const browserRoot = obStore.state.browserRoot;
|
||||
const uriParts = (obStore.state.path + props.file.Key).split('/');
|
||||
const pathAndKey = uriParts.map(part => encodeURIComponent(part)).join('/');
|
||||
return pathAndKey.length > 0
|
||||
? browserRoot + pathAndKey + '/'
|
||||
@ -209,13 +209,13 @@ const link = computed((): string => {
|
||||
*/
|
||||
const isFileSelected = computed((): boolean => {
|
||||
return Boolean(
|
||||
store.state.files.selectedAnchorFile === props.file ||
|
||||
store.state.files.selectedFiles.find(
|
||||
(file) => file === props.file,
|
||||
) ||
|
||||
store.state.files.shiftSelectedFiles.find(
|
||||
(file) => file === props.file,
|
||||
),
|
||||
obStore.state.selectedAnchorFile === props.file ||
|
||||
obStore.state.selectedFiles.find(
|
||||
(file) => file === props.file,
|
||||
) ||
|
||||
obStore.state.shiftSelectedFiles.find(
|
||||
(file) => file === props.file,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -237,16 +237,16 @@ const fileTypeIsFile = computed((): boolean => {
|
||||
* Open the modal for the current file.
|
||||
*/
|
||||
function openModal(): void {
|
||||
store.commit('files/setObjectPathForModal', props.path + props.file.Key);
|
||||
obStore.setObjectPathForModal(props.path + props.file.Key);
|
||||
appStore.updateActiveModal(MODALS.objectDetails);
|
||||
store.dispatch('files/closeDropdown');
|
||||
obStore.closeDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a boolean signifying whether the current file/folder is in the process of being deleted, therefore a spinner shoud be shown.
|
||||
*/
|
||||
function loadingSpinner(): boolean {
|
||||
return Boolean(store.state.files.filesToBeDeleted.find(
|
||||
return Boolean(obStore.state.filesToBeDeleted.find(
|
||||
(file) => file === props.file,
|
||||
));
|
||||
}
|
||||
@ -255,8 +255,8 @@ function loadingSpinner(): boolean {
|
||||
* Select the current file/folder whether it be a click, click + shiftKey, click + metaKey or ctrlKey, or unselect the rest.
|
||||
*/
|
||||
function selectFile(event: KeyboardEvent): void {
|
||||
if (store.state.files.openedDropdown) {
|
||||
store.dispatch('files/closeDropdown');
|
||||
if (obStore.state.openedDropdown) {
|
||||
obStore.closeDropdown();
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
@ -270,9 +270,9 @@ function selectFile(event: KeyboardEvent): void {
|
||||
setSelectedFile(isSelectedFile);
|
||||
}
|
||||
|
||||
async function openFolder(): Promise<void> {
|
||||
await router.push(link.value);
|
||||
store.dispatch('files/clearAllSelectedFiles');
|
||||
function openFolder(): void {
|
||||
router.push(link.value);
|
||||
obStore.clearAllSelectedFiles();
|
||||
emit('onUpdate');
|
||||
}
|
||||
|
||||
@ -281,70 +281,51 @@ async function openFolder(): Promise<void> {
|
||||
*/
|
||||
function setSelectedFile(command: boolean): void {
|
||||
/* this function is responsible for selecting and unselecting a file on file click or [CMD + click] AKA command. */
|
||||
const shiftSelectedFiles =
|
||||
store.state.files.shiftSelectedFiles;
|
||||
const selectedFiles = store.state.files.selectedFiles;
|
||||
const shiftSelectedFiles = obStore.state.shiftSelectedFiles;
|
||||
const selectedFiles = obStore.state.selectedFiles;
|
||||
|
||||
const files = [
|
||||
...selectedFiles,
|
||||
...shiftSelectedFiles,
|
||||
];
|
||||
|
||||
const selectedAnchorFile =
|
||||
store.state.files.selectedAnchorFile;
|
||||
const selectedAnchorFile = obStore.state.selectedAnchorFile;
|
||||
|
||||
if (command && props.file === selectedAnchorFile) {
|
||||
/* if it's [CMD + click] and the file selected is the actual selectedAnchorFile, then unselect the file but store it under unselectedAnchorFile in case the user decides to do a [shift + click] right after this action. */
|
||||
|
||||
store.commit('files/setUnselectedAnchorFile', props.file);
|
||||
store.commit('files/setSelectedAnchorFile', null);
|
||||
/* if it's [CMD + click] and the file selected is the actual selectedAnchorFile, then unselect the file but store it under unselectedAnchorFile in case the user decides to do a [shift + click] right after this action. */
|
||||
obStore.setUnselectedAnchorFile(props.file);
|
||||
obStore.setSelectedAnchorFile(null);
|
||||
} else if (command && files.includes(props.file)) {
|
||||
/* if it's [CMD + click] and the file selected is a file that has already been selected in selectedFiles and shiftSelectedFiles, then unselect it by filtering it out. */
|
||||
|
||||
store.dispatch(
|
||||
'files/updateSelectedFiles',
|
||||
selectedFiles.filter(
|
||||
(fileSelected) => fileSelected !== props.file,
|
||||
),
|
||||
);
|
||||
|
||||
store.dispatch(
|
||||
'files/updateShiftSelectedFiles',
|
||||
shiftSelectedFiles.filter(
|
||||
(fileSelected) => fileSelected !== props.file,
|
||||
),
|
||||
);
|
||||
/* if it's [CMD + click] and the file selected is a file that has already been selected in selectedFiles and shiftSelectedFiles, then unselect it by filtering it out. */
|
||||
obStore.updateSelectedFiles(selectedFiles.filter((fileSelected) => fileSelected !== props.file));
|
||||
obStore.updateShiftSelectedFiles(shiftSelectedFiles.filter((fileSelected) => fileSelected !== props.file));
|
||||
} else if (command && selectedAnchorFile) {
|
||||
/* if it's [CMD + click] and there is already a selectedAnchorFile, then add the selectedAnchorFile and shiftSelectedFiles into the array of selectedFiles, set selectedAnchorFile to the file that was clicked, set unselectedAnchorFile to null, and set shiftSelectedFiles to an empty array. */
|
||||
|
||||
/* if it's [CMD + click] and there is already a selectedAnchorFile, then add the selectedAnchorFile and shiftSelectedFiles into the array of selectedFiles, set selectedAnchorFile to the file that was clicked, set unselectedAnchorFile to null, and set shiftSelectedFiles to an empty array. */
|
||||
const filesSelected = [...selectedFiles];
|
||||
|
||||
if (!filesSelected.includes(selectedAnchorFile)) {
|
||||
filesSelected.push(selectedAnchorFile);
|
||||
}
|
||||
|
||||
store.dispatch('files/updateSelectedFiles', [
|
||||
obStore.updateSelectedFiles([
|
||||
...filesSelected,
|
||||
...shiftSelectedFiles.filter(
|
||||
(file) => !filesSelected.includes(file),
|
||||
),
|
||||
]);
|
||||
|
||||
store.commit('files/setSelectedAnchorFile', props.file);
|
||||
store.commit('files/setUnselectedAnchorFile', null);
|
||||
store.dispatch('files/updateShiftSelectedFiles', []);
|
||||
obStore.setSelectedAnchorFile(props.file);
|
||||
obStore.setUnselectedAnchorFile(null);
|
||||
obStore.updateShiftSelectedFiles([]);
|
||||
} else if (command) {
|
||||
/* if it's [CMD + click] and it has not met any of the above conditions, then set selectedAnchorFile to file and set unselectedAnchorfile to null, update the selectedFiles, and update the shiftSelectedFiles */
|
||||
|
||||
store.commit('files/setSelectedAnchorFile', props.file);
|
||||
store.commit('files/setUnselectedAnchorFile', null);
|
||||
|
||||
store.dispatch('files/updateSelectedFiles', [
|
||||
/* if it's [CMD + click] and it has not met any of the above conditions, then set selectedAnchorFile to file and set unselectedAnchorfile to null, update the selectedFiles, and update the shiftSelectedFiles */
|
||||
obStore.setSelectedAnchorFile(props.file);
|
||||
obStore.setUnselectedAnchorFile(null);
|
||||
obStore.updateSelectedFiles([
|
||||
...selectedFiles,
|
||||
...shiftSelectedFiles,
|
||||
]);
|
||||
|
||||
store.dispatch('files/updateShiftSelectedFiles', []);
|
||||
obStore.updateShiftSelectedFiles([]);
|
||||
} else {
|
||||
/* if it's just a file click without any modifier ... */
|
||||
const newSelection = [...files];
|
||||
@ -356,20 +337,21 @@ function setSelectedFile(command: boolean): void {
|
||||
break;
|
||||
case selectedAnchorFile === props.file:
|
||||
// this file is already selected, deselect.
|
||||
store.commit('files/setSelectedAnchorFile', null);
|
||||
store.commit('files/setUnselectedAnchorFile', props.file);
|
||||
obStore.setSelectedAnchorFile(null);
|
||||
obStore.setUnselectedAnchorFile(props.file);
|
||||
break;
|
||||
case !!selectedAnchorFile:
|
||||
// there's an anchor file, but not this file.
|
||||
// add the anchor file to the selection arr and make this file the anchor file.
|
||||
newSelection.push(selectedAnchorFile as BrowserObject);
|
||||
store.commit('files/setSelectedAnchorFile', props.file);
|
||||
obStore.setSelectedAnchorFile(props.file);
|
||||
break;
|
||||
default:
|
||||
store.commit('files/setSelectedAnchorFile', props.file);
|
||||
obStore.setSelectedAnchorFile(props.file);
|
||||
}
|
||||
store.dispatch('files/updateShiftSelectedFiles', []);
|
||||
store.dispatch('files/updateSelectedFiles', newSelection);
|
||||
|
||||
obStore.updateShiftSelectedFiles([]);
|
||||
obStore.updateSelectedFiles(newSelection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,25 +360,18 @@ function setSelectedFile(command: boolean): void {
|
||||
*/
|
||||
function setShiftSelectedFiles(): void {
|
||||
/* this function is responsible for selecting all files from selectedAnchorFile to the file that was selected with [shift + click] */
|
||||
|
||||
const files = store.getters['files/sortedFiles'];
|
||||
const unselectedAnchorFile =
|
||||
store.state.files.unselectedAnchorFile;
|
||||
const files = obStore.sortedFiles;
|
||||
const unselectedAnchorFile = obStore.state.unselectedAnchorFile;
|
||||
|
||||
if (unselectedAnchorFile) {
|
||||
/* if there is an unselectedAnchorFile, meaning that in the previous action the user unselected the anchor file but is now chosing to do a [shift + click] on another file, then reset the selectedAnchorFile, the achor file, to unselectedAnchorFile. */
|
||||
store.commit(
|
||||
'files/setSelectedAnchorFile',
|
||||
unselectedAnchorFile,
|
||||
);
|
||||
|
||||
store.commit('files/setUnselectedAnchorFile', null);
|
||||
/* if there is an unselectedAnchorFile, meaning that in the previous action the user unselected the anchor file but is now chosing to do a [shift + click] on another file, then reset the selectedAnchorFile, the achor file, to unselectedAnchorFile. */
|
||||
obStore.setSelectedAnchorFile(unselectedAnchorFile);
|
||||
obStore.setUnselectedAnchorFile(null);
|
||||
}
|
||||
|
||||
const selectedAnchorFile = store.state.files.selectedAnchorFile;
|
||||
|
||||
const selectedAnchorFile = obStore.state.selectedAnchorFile;
|
||||
if (!selectedAnchorFile) {
|
||||
store.commit('files/setSelectedAnchorFile', props.file);
|
||||
obStore.setSelectedAnchorFile(props.file);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -409,16 +384,10 @@ function setShiftSelectedFiles(): void {
|
||||
const start = Math.min(anchorIdx, shiftIdx);
|
||||
const end = Math.max(anchorIdx, shiftIdx) + 1;
|
||||
|
||||
store.dispatch(
|
||||
'files/updateShiftSelectedFiles',
|
||||
obStore.updateShiftSelectedFiles(
|
||||
files
|
||||
.slice(start, end)
|
||||
.filter(
|
||||
(file) =>
|
||||
!store.state.files.selectedFiles.includes(
|
||||
file,
|
||||
) && file !== selectedAnchorFile,
|
||||
),
|
||||
.filter((file) => !obStore.state.selectedFiles.includes(file) && file !== selectedAnchorFile),
|
||||
);
|
||||
}
|
||||
|
||||
@ -426,8 +395,8 @@ function setShiftSelectedFiles(): void {
|
||||
* Open the share modal for the current file.
|
||||
*/
|
||||
function share(): void {
|
||||
store.dispatch('files/closeDropdown');
|
||||
store.commit('files/setObjectPathForModal', props.path + props.file.Key);
|
||||
obStore.closeDropdown();
|
||||
obStore.setObjectPathForModal(props.path + props.file.Key);
|
||||
appStore.updateActiveModal(MODALS.shareObject);
|
||||
}
|
||||
|
||||
@ -435,7 +404,7 @@ function share(): void {
|
||||
* Close the dropdown.
|
||||
*/
|
||||
function closeDropdown(): void {
|
||||
store.dispatch('files/closeDropdown');
|
||||
obStore.closeDropdown();
|
||||
|
||||
// remove the dropdown delete confirmation
|
||||
deleteConfirmation.value = false;
|
||||
@ -445,7 +414,7 @@ function closeDropdown(): void {
|
||||
* Open the dropdown for the current file/folder.
|
||||
*/
|
||||
function openDropdown(): void {
|
||||
store.dispatch('files/openDropdown', props.file.Key);
|
||||
obStore.openDropdown(props.file.Key);
|
||||
|
||||
// remove the dropdown delete confirmation
|
||||
deleteConfirmation.value = false;
|
||||
@ -456,14 +425,13 @@ function openDropdown(): void {
|
||||
*/
|
||||
function download(): void {
|
||||
try {
|
||||
store.dispatch('files/download', props.file);
|
||||
obStore.download(props.file);
|
||||
notify.warning('Do not share download link with other people. If you want to share this data better use "Share" option.');
|
||||
} catch (error) {
|
||||
notify.error('Can not download your file', AnalyticsErrorEventSource.FILE_BROWSER_ENTRY);
|
||||
}
|
||||
|
||||
store.dispatch('files/closeDropdown');
|
||||
deleteConfirmation.value = false;
|
||||
closeDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -477,21 +445,21 @@ function confirmDeletion(): void {
|
||||
* Delete the selected file/folder.
|
||||
*/
|
||||
async function finalDelete(): Promise<void> {
|
||||
store.dispatch('files/closeDropdown');
|
||||
store.dispatch('files/addFileToBeDeleted', props.file);
|
||||
obStore.closeDropdown();
|
||||
obStore.addFileToBeDeleted(props.file);
|
||||
|
||||
const params = { ...props };
|
||||
|
||||
(props.file.type === 'file') ? await store.dispatch('files/delete', params) : store.dispatch('files/deleteFolder', params);
|
||||
props.file.type === 'file' ?
|
||||
await obStore.deleteObject(props.path, props.file) :
|
||||
await obStore.deleteFolder(props.file, props.path);
|
||||
|
||||
// refresh the files displayed
|
||||
try {
|
||||
await store.dispatch('files/list');
|
||||
await obStore.list();
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.FILE_BROWSER_ENTRY);
|
||||
}
|
||||
|
||||
store.dispatch('files/removeFileFromToBeDeleted', props.file);
|
||||
obStore.removeFileFromToBeDeleted(props.file);
|
||||
deleteConfirmation.value = false;
|
||||
}
|
||||
|
||||
@ -499,7 +467,7 @@ async function finalDelete(): Promise<void> {
|
||||
* Abort the deletion of the current file/folder.
|
||||
*/
|
||||
function cancelDeletion(): void {
|
||||
store.dispatch('files/closeDropdown');
|
||||
obStore.closeDropdown();
|
||||
deleteConfirmation.value = false;
|
||||
}
|
||||
</script>
|
||||
|
@ -34,11 +34,11 @@
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { Bucket } from '@/types/buckets';
|
||||
import { useStore } from '@/utils/hooks';
|
||||
import { ManageProjectPassphraseStep } from '@/types/managePassphrase';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import LockedIcon from '@/../static/images/browser/locked.svg';
|
||||
import CloseIcon from '@/../static/images/browser/close.svg';
|
||||
@ -51,7 +51,7 @@ const props = withDefaults(defineProps<{
|
||||
|
||||
const appStore = useAppStore();
|
||||
const bucketsStore = useBucketsStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const NUMBER_OF_DISPLAYED_OBJECTS = 1000;
|
||||
|
||||
@ -59,7 +59,7 @@ const NUMBER_OF_DISPLAYED_OBJECTS = 1000;
|
||||
* Returns locked files number.
|
||||
*/
|
||||
const lockedFilesNumber = computed((): number => {
|
||||
const ownObjectsCount = store.state.files.objectsCount;
|
||||
const ownObjectsCount = obStore.state.objectsCount;
|
||||
|
||||
return objectsCount.value - ownObjectsCount;
|
||||
});
|
||||
@ -68,7 +68,7 @@ const lockedFilesNumber = computed((): number => {
|
||||
* Returns bucket objects count from store.
|
||||
*/
|
||||
const objectsCount = computed((): number => {
|
||||
const name: string = store.state.files.bucket;
|
||||
const name: string = obStore.state.bucket;
|
||||
const data: Bucket | undefined = bucketsStore.state.page.buckets.find((bucket: Bucket) => bucket.name === name);
|
||||
|
||||
return data?.objectCount || 0;
|
||||
|
@ -69,7 +69,7 @@ import { computed, reactive, ref } from 'vue';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useRouter, useStore } from '@/utils/hooks';
|
||||
import { useRouter } from '@/utils/hooks';
|
||||
import { useBillingStore } from '@/store/modules/billingStore';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -79,7 +79,6 @@ import VButton from '@/components/common/VButton.vue';
|
||||
import CheckIcon from '@/../static/images/common/validCheck.svg';
|
||||
|
||||
const billingStore = useBillingStore();
|
||||
const store = useStore();
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
|
||||
|
@ -33,7 +33,7 @@ import { ref } from 'vue';
|
||||
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
import { useBillingStore } from '@/store/modules/billingStore';
|
||||
|
||||
@ -42,7 +42,6 @@ import ValidationMessage from '@/components/common/ValidationMessage.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
const billingStore = useBillingStore();
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
|
||||
|
@ -49,11 +49,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { useNotify, useRoute } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
@ -68,7 +68,8 @@ const props = withDefaults(defineProps<{
|
||||
showManualActivationMsg: true,
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
const notify = useNotify();
|
||||
|
||||
const auth: AuthHttpApi = new AuthHttpApi();
|
||||
@ -78,14 +79,7 @@ const secondsToWait = ref<number>(30);
|
||||
const intervalId = ref<ReturnType<typeof setInterval>>();
|
||||
|
||||
const userEmail = computed((): string => {
|
||||
return props.email || route.query.email.toString();
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks if page is inside iframe.
|
||||
*/
|
||||
const isInsideIframe = computed((): boolean => {
|
||||
return window.self !== window.top;
|
||||
return props.email || router.currentRoute.query.email.toString();
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ import { ref } from 'vue';
|
||||
import { DisableMFARequest } from '@/types/users';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
|
||||
@ -60,7 +60,6 @@ interface ClearInput {
|
||||
|
||||
const appStore = useAppStore();
|
||||
const usersStore = useUsersStore();
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const isError = ref<boolean>(false);
|
||||
|
@ -40,19 +40,19 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { BrowserFile } from '@/types/browser';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
|
||||
const obStore = useObjectBrowserStore();
|
||||
const appStore = useAppStore();
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const createFolderName = ref<string>('');
|
||||
@ -62,8 +62,8 @@ const isLoading = ref<boolean>(false);
|
||||
/**
|
||||
* Retrieve all the files sorted from the store.
|
||||
*/
|
||||
const files = computed((): BrowserFile[] => {
|
||||
return store.getters['files/sortedFiles'];
|
||||
const files = computed((): BrowserObject[] => {
|
||||
return obStore.sortedFiles;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -123,7 +123,7 @@ async function createFolder(): Promise<void> {
|
||||
isLoading.value = true;
|
||||
|
||||
try {
|
||||
await store.dispatch('files/createFolder', createFolderName.value.trim());
|
||||
await obStore.createFolder(createFolderName.value.trim());
|
||||
} catch (error) {
|
||||
await notify.error(error.message, AnalyticsErrorEventSource.CREATE_FOLDER_MODAL);
|
||||
}
|
||||
|
@ -119,8 +119,8 @@ import prettyBytes from 'pretty-bytes';
|
||||
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { BrowserObject } from '@/store/modules/files';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
@ -130,7 +130,7 @@ import VLoader from '@/components/common/VLoader.vue';
|
||||
import PlaceholderImage from '@/../static/images/browser/placeholder.svg';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const isLoading = ref<boolean>(false);
|
||||
@ -144,7 +144,7 @@ const copyText = ref<string>('Copy Link');
|
||||
* Retrieve the file object that the modal is set to from the store.
|
||||
*/
|
||||
const file = computed((): BrowserObject | undefined => {
|
||||
return store.state.files.files.find(
|
||||
return obStore.state.files.find(
|
||||
(file) => file.Key === filePath.value.split('/').slice(-1)[0],
|
||||
);
|
||||
});
|
||||
@ -153,7 +153,7 @@ const file = computed((): BrowserObject | undefined => {
|
||||
* Retrieve the filepath of the modal from the store.
|
||||
*/
|
||||
const filePath = computed((): string => {
|
||||
return store.state.files.objectPathForModal;
|
||||
return obStore.state.objectPathForModal;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -161,7 +161,7 @@ const filePath = computed((): string => {
|
||||
*/
|
||||
const size = computed((): string => {
|
||||
return prettyBytes(
|
||||
store.state.files.files.find((f) => f.Key === file.value?.Key)?.Size || 0,
|
||||
obStore.state.files.find((f) => f.Key === file.value?.Key)?.Size || 0,
|
||||
);
|
||||
});
|
||||
|
||||
@ -233,7 +233,7 @@ const placeHolderDisplayable = computed((): boolean => {
|
||||
async function fetchPreviewAndMapUrl(): Promise<void> {
|
||||
isLoading.value = true;
|
||||
|
||||
const url: string = await store.state.files.fetchPreviewAndMapUrl(
|
||||
const url: string = await obStore.state.fetchPreviewAndMapUrl(
|
||||
filePath.value,
|
||||
);
|
||||
|
||||
@ -263,7 +263,7 @@ async function fetchPreviewAndMapUrl(): Promise<void> {
|
||||
*/
|
||||
function download(): void {
|
||||
try {
|
||||
store.dispatch('files/download', file.value);
|
||||
obStore.download(file.value);
|
||||
notify.warning('Do not share download link with other people. If you want to share this data better use "Share" option.');
|
||||
} catch (error) {
|
||||
notify.error('Can not download your file', AnalyticsErrorEventSource.OBJECT_DETAILS_MODAL);
|
||||
@ -294,7 +294,7 @@ async function copy(): Promise<void> {
|
||||
* Get the share link of the current opened file.
|
||||
*/
|
||||
async function getSharedLink(): Promise<void> {
|
||||
objectLink.value = await store.state.files.fetchSharedLink(
|
||||
objectLink.value = await obStore.state.fetchSharedLink(
|
||||
filePath.value,
|
||||
);
|
||||
}
|
||||
|
@ -43,8 +43,9 @@
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -59,7 +60,7 @@ enum ButtonStates {
|
||||
}
|
||||
|
||||
const appStore = useAppStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const isLoading = ref<boolean>(true);
|
||||
@ -70,7 +71,7 @@ const copyButtonState = ref<ButtonStates>(ButtonStates.Copy);
|
||||
* Retrieve the path to the current file that has the fileShareModal opened from the store.
|
||||
*/
|
||||
const filePath = computed((): string => {
|
||||
return store.state.files.objectPathForModal;
|
||||
return obStore.state.objectPathForModal;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -101,7 +102,7 @@ function closeModal(): void {
|
||||
* Sets share link.
|
||||
*/
|
||||
onMounted(async (): Promise<void> => {
|
||||
link.value = await store.state.files.fetchSharedLink(
|
||||
link.value = await obStore.state.fetchSharedLink(
|
||||
filePath.value,
|
||||
);
|
||||
|
||||
|
@ -56,7 +56,7 @@ import { AuthHttpApi } from '@/api/auth';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { APP_STATE_DROPDOWNS } from '@/utils/constants/appStatePopUps';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { useABTestingStore } from '@/store/modules/abTestingStore';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
|
||||
@ -66,6 +66,7 @@ import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import BillingIcon from '@/../static/images/navigation/billing.svg';
|
||||
import InfoIcon from '@/../static/images/navigation/info.svg';
|
||||
@ -77,14 +78,14 @@ import LogoutIcon from '@/../static/images/navigation/logout.svg';
|
||||
import TierBadgeFree from '@/../static/images/navigation/tierBadgeFree.svg';
|
||||
import TierBadgePro from '@/../static/images/navigation/tierBadgePro.svg';
|
||||
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const obStore = useObjectBrowserStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const bucketsStore = useBucketsStore();
|
||||
const appStore = useAppStore();
|
||||
const agStore = useAccessGrantsStore();
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const billingStore = useBillingStore();
|
||||
const usersStore = useUsersStore();
|
||||
const abTestingStore = useABTestingStore();
|
||||
@ -165,7 +166,7 @@ async function onLogout(): Promise<void> {
|
||||
appStore.clear(),
|
||||
billingStore.clear(),
|
||||
abTestingStore.reset(),
|
||||
store.dispatch('files/clear'),
|
||||
obStore.clear(),
|
||||
]);
|
||||
|
||||
try {
|
||||
|
@ -170,7 +170,7 @@ import { User } from '@/types/users';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { useABTestingStore } from '@/store/modules/abTestingStore';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
|
||||
@ -180,6 +180,7 @@ import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import ResourcesLinks from '@/components/navigation/ResourcesLinks.vue';
|
||||
import QuickStartLinks from '@/components/navigation/QuickStartLinks.vue';
|
||||
@ -226,7 +227,8 @@ const usersStore = useUsersStore();
|
||||
const abTestingStore = useABTestingStore();
|
||||
const notificationsStore = useNotificationsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
@ -477,7 +479,7 @@ async function onLogout(): Promise<void> {
|
||||
appStore.clear(),
|
||||
billingStore.clear(),
|
||||
abTestingStore.reset(),
|
||||
store.dispatch('files/clear'),
|
||||
obStore.clear(),
|
||||
]);
|
||||
|
||||
try {
|
||||
|
@ -30,17 +30,18 @@
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { useRouter, useStore } from '@/utils/hooks';
|
||||
import { useRouter } from '@/utils/hooks';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import ArrowDownIcon from '@/../static/images/common/dropIcon.svg';
|
||||
import DetailsIcon from '@/../static/images/objects/details.svg';
|
||||
import ShareIcon from '@/../static/images/objects/share.svg';
|
||||
import GearIcon from '@/../static/images/common/gearIcon.svg';
|
||||
|
||||
const obStore = useObjectBrowserStore();
|
||||
const appStore = useAppStore();
|
||||
const store = useStore();
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
|
||||
@ -55,7 +56,7 @@ const isHoveredOver = ref(false);
|
||||
* Returns files amount from store.
|
||||
*/
|
||||
const filesCount = computed((): number => {
|
||||
return store.getters['files/sortedFiles'].length;
|
||||
return obStore.sortedFiles.length;
|
||||
});
|
||||
|
||||
function closeDropdown(): void {
|
||||
|
@ -72,7 +72,7 @@ import { computed, onBeforeUnmount, ref } from 'vue';
|
||||
import { BucketPage } from '@/types/buckets';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { EdgeCredentials } from '@/types/accessGrants';
|
||||
|
@ -19,20 +19,21 @@ import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { BucketPage } from '@/types/buckets';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import FileBrowser from '@/components/browser/FileBrowser.vue';
|
||||
import UploadCancelPopup from '@/components/objects/UploadCancelPopup.vue';
|
||||
|
||||
const obStore = useObjectBrowserStore();
|
||||
const bucketsStore = useBucketsStore();
|
||||
const appStore = useAppStore();
|
||||
const agStore = useAccessGrantsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
@ -215,7 +216,7 @@ async function generateCredentials(cleanApiKey: string, path: string, areEndless
|
||||
onBeforeMount(() => {
|
||||
setWorker();
|
||||
|
||||
store.commit('files/init', {
|
||||
obStore.init({
|
||||
endpoint: edgeCredentials.value.endpoint,
|
||||
accessKey: edgeCredentials.value.accessKeyId,
|
||||
secretKey: edgeCredentials.value.secretKey,
|
||||
@ -241,17 +242,18 @@ watch(passphrase, async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
await router.push(RouteConfig.Buckets.with(RouteConfig.UploadFile).path).catch(() => {return;});
|
||||
store.commit('files/reinit', {
|
||||
router.push(RouteConfig.Buckets.with(RouteConfig.UploadFile).path).catch(() => {return;});
|
||||
obStore.reinit({
|
||||
endpoint: edgeCredentials.value.endpoint,
|
||||
accessKey: edgeCredentials.value.accessKeyId,
|
||||
secretKey: edgeCredentials.value.secretKey,
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
bucketsStore.getBuckets(bucketPage.value.currentPage, projectID),
|
||||
store.dispatch('files/list', ''),
|
||||
store.dispatch('files/getObjectCount'),
|
||||
obStore.list(''),
|
||||
obStore.getObjectCount(),
|
||||
]);
|
||||
} catch (error) {
|
||||
await notify.error(error.message, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
|
@ -45,7 +45,6 @@
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { APP_STATE_DROPDOWNS } from '@/utils/constants/appStatePopUps';
|
||||
import { useStore } from '@/utils/hooks';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
|
||||
@ -53,7 +52,6 @@ import ExpandIcon from '@/../static/images/common/BlackArrowExpand.svg';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const agStore = useAccessGrantsStore();
|
||||
const store = useStore();
|
||||
|
||||
const isLoading = ref<boolean>(true);
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
import { RouteConfig } from '@/router';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -41,7 +41,6 @@ import VButton from '@/components/common/VButton.vue';
|
||||
import Icon from '@/../static/images/onboardingTour/successStep.svg';
|
||||
|
||||
const usersStore = useUsersStore();
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -7,7 +7,6 @@ import { createPinia, setActivePinia, PiniaVuePlugin } from 'pinia';
|
||||
|
||||
import App from './App.vue';
|
||||
import { router } from './router';
|
||||
import { store } from './store';
|
||||
|
||||
import { Size } from '@/utils/bytesSize';
|
||||
import { NotificatorPlugin } from '@/utils/plugins/notificator';
|
||||
@ -95,7 +94,6 @@ Vue.filter('leadingZero', (value: number): string => {
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
pinia,
|
||||
render: (h) => h(App),
|
||||
}).$mount('#app');
|
||||
|
@ -1,22 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import { FilesState, makeFilesModule } from '@/store/modules/files';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export interface ModulesState {
|
||||
files: FilesState;
|
||||
}
|
||||
|
||||
// Satellite store (vuex)
|
||||
export const store = new Vuex.Store<ModulesState>({
|
||||
modules: {
|
||||
files: makeFilesModule(),
|
||||
},
|
||||
});
|
||||
|
||||
export default store;
|
@ -1,781 +0,0 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import S3, { CommonPrefix } from 'aws-sdk/clients/s3';
|
||||
|
||||
import { StoreModule } from '@/types/store';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
|
||||
const listCache = new Map();
|
||||
|
||||
type Promisable<T> = T | PromiseLike<T>;
|
||||
|
||||
export type BrowserObject = {
|
||||
Key: string;
|
||||
Size: number;
|
||||
LastModified: number;
|
||||
type?: 'file' | 'folder';
|
||||
progress?: number;
|
||||
upload?: {
|
||||
abort: () => void;
|
||||
};
|
||||
path?: string;
|
||||
};
|
||||
|
||||
export type FilesState = {
|
||||
s3: S3 | null;
|
||||
accessKey: null | string;
|
||||
|
||||
path: string;
|
||||
bucket: string;
|
||||
browserRoot: string;
|
||||
files: BrowserObject[];
|
||||
uploadChain: Promise<void>;
|
||||
uploading: BrowserObject[];
|
||||
selectedAnchorFile: BrowserObject | null;
|
||||
unselectedAnchorFile: null | string;
|
||||
selectedFiles: BrowserObject[];
|
||||
shiftSelectedFiles: BrowserObject[];
|
||||
filesToBeDeleted: BrowserObject[];
|
||||
|
||||
fetchSharedLink: (arg0: string) => Promisable<string>;
|
||||
fetchPreviewAndMapUrl: (arg0: string) => Promisable<string>;
|
||||
|
||||
openedDropdown: null | string;
|
||||
headingSorted: string;
|
||||
orderBy: 'asc' | 'desc';
|
||||
openModalOnFirstUpload: boolean;
|
||||
objectPathForModal: string;
|
||||
objectsCount: number;
|
||||
};
|
||||
|
||||
type InitializedFilesState = FilesState & {
|
||||
s3: S3;
|
||||
};
|
||||
|
||||
function assertIsInitialized(
|
||||
state: FilesState,
|
||||
): asserts state is InitializedFilesState {
|
||||
if (state.s3 === null) {
|
||||
throw new Error(
|
||||
'FilesModule: S3 Client is uninitialized. "state.s3" is null.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface FilesContext {
|
||||
state: FilesState;
|
||||
commit: (string, ...unknown) => void;
|
||||
dispatch: (string, ...unknown) => Promise<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
rootState: {
|
||||
files: FilesState;
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface FileSystemEntry {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry/file
|
||||
file: (
|
||||
successCallback: (arg0: File) => void,
|
||||
errorCallback?: (arg0: Error) => void
|
||||
) => void;
|
||||
createReader: () => FileSystemDirectoryReader;
|
||||
}
|
||||
}
|
||||
|
||||
type FilesModule = StoreModule<FilesState, FilesContext> & { namespaced: true };
|
||||
|
||||
export const makeFilesModule = (): FilesModule => ({
|
||||
namespaced: true,
|
||||
state: {
|
||||
s3: null,
|
||||
accessKey: null,
|
||||
|
||||
path: '',
|
||||
bucket: '',
|
||||
browserRoot: '/',
|
||||
files: [],
|
||||
uploadChain: Promise.resolve(),
|
||||
uploading: [],
|
||||
selectedAnchorFile: null,
|
||||
unselectedAnchorFile: null,
|
||||
selectedFiles: [],
|
||||
shiftSelectedFiles: [],
|
||||
filesToBeDeleted: [],
|
||||
fetchSharedLink: () => 'javascript:null',
|
||||
fetchPreviewAndMapUrl: () => 'javascript:null',
|
||||
openedDropdown: null,
|
||||
headingSorted: 'name',
|
||||
orderBy: 'asc',
|
||||
openModalOnFirstUpload: false,
|
||||
objectPathForModal: '',
|
||||
objectsCount: 0,
|
||||
},
|
||||
getters: {
|
||||
sortedFiles: (state: FilesState) => {
|
||||
// key-specific sort cases
|
||||
const fns = {
|
||||
date: (a: BrowserObject, b: BrowserObject): number =>
|
||||
new Date(a.LastModified).getTime() - new Date(b.LastModified).getTime(),
|
||||
name: (a: BrowserObject, b: BrowserObject): number =>
|
||||
a.Key.localeCompare(b.Key),
|
||||
size: (a: BrowserObject, b: BrowserObject): number => a.Size - b.Size,
|
||||
};
|
||||
|
||||
// TODO(performance): avoid several passes over the slice.
|
||||
|
||||
// sort by appropriate function
|
||||
const sortedFiles = state.files.slice();
|
||||
sortedFiles.sort(fns[state.headingSorted]);
|
||||
// reverse if descending order
|
||||
if (state.orderBy !== 'asc') {
|
||||
sortedFiles.reverse();
|
||||
}
|
||||
|
||||
// display folders and then files
|
||||
const groupedFiles = [
|
||||
...sortedFiles.filter((file) => file.type === 'folder'),
|
||||
...sortedFiles.filter((file) => file.type === 'file'),
|
||||
];
|
||||
|
||||
return groupedFiles;
|
||||
},
|
||||
|
||||
isInitialized: (state: FilesState): boolean => state.s3 !== null,
|
||||
uploadingLength: (state: FilesState): number => state.uploading.length,
|
||||
},
|
||||
mutations: {
|
||||
init(
|
||||
state: FilesState,
|
||||
{
|
||||
accessKey,
|
||||
secretKey,
|
||||
bucket,
|
||||
endpoint,
|
||||
browserRoot,
|
||||
openModalOnFirstUpload = true,
|
||||
fetchSharedLink = () => 'javascript:null',
|
||||
fetchPreviewAndMapUrl = () => 'javascript:null',
|
||||
}: {
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
bucket: string;
|
||||
endpoint: string;
|
||||
browserRoot: string;
|
||||
openModalOnFirstUpload: boolean;
|
||||
fetchSharedLink: (arg0: string) => Promisable<string>;
|
||||
fetchPreviewAndMapUrl: (arg0: string) => Promisable<string>;
|
||||
},
|
||||
) {
|
||||
const s3Config = {
|
||||
accessKeyId: accessKey,
|
||||
secretAccessKey: secretKey,
|
||||
endpoint,
|
||||
s3ForcePathStyle: true,
|
||||
signatureVersion: 'v4',
|
||||
connectTimeout: 0,
|
||||
httpOptions: { timeout: 0 },
|
||||
};
|
||||
|
||||
state.s3 = new S3(s3Config);
|
||||
state.accessKey = accessKey;
|
||||
state.bucket = bucket;
|
||||
state.browserRoot = browserRoot;
|
||||
state.openModalOnFirstUpload = openModalOnFirstUpload;
|
||||
state.fetchSharedLink = fetchSharedLink;
|
||||
state.fetchPreviewAndMapUrl = fetchPreviewAndMapUrl;
|
||||
state.path = '';
|
||||
state.files = [];
|
||||
},
|
||||
|
||||
reinit(state: FilesState, {
|
||||
accessKey,
|
||||
secretKey,
|
||||
endpoint,
|
||||
}: {
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
endpoint: string;
|
||||
}) {
|
||||
const s3Config = {
|
||||
accessKeyId: accessKey,
|
||||
secretAccessKey: secretKey,
|
||||
endpoint,
|
||||
s3ForcePathStyle: true,
|
||||
signatureVersion: 'v4',
|
||||
connectTimeout: 0,
|
||||
httpOptions: { timeout: 0 },
|
||||
};
|
||||
|
||||
state.files = [];
|
||||
state.s3 = new S3(s3Config);
|
||||
state.accessKey = accessKey;
|
||||
},
|
||||
|
||||
updateFiles(state: FilesState, { path, files }) {
|
||||
state.path = path;
|
||||
state.files = files;
|
||||
},
|
||||
|
||||
setSelectedFiles(state: FilesState, files) {
|
||||
state.selectedFiles = files;
|
||||
},
|
||||
|
||||
setSelectedAnchorFile(state: FilesState, file) {
|
||||
state.selectedAnchorFile = file;
|
||||
},
|
||||
|
||||
setUnselectedAnchorFile(state: FilesState, file) {
|
||||
state.unselectedAnchorFile = file;
|
||||
},
|
||||
|
||||
setFilesToBeDeleted(state: FilesState, files) {
|
||||
state.filesToBeDeleted = [...state.filesToBeDeleted, ...files];
|
||||
},
|
||||
|
||||
removeFileToBeDeleted(state: FilesState, file) {
|
||||
state.filesToBeDeleted = state.filesToBeDeleted.filter(
|
||||
(singleFile) => singleFile.Key !== file.Key,
|
||||
);
|
||||
},
|
||||
|
||||
removeAllFilesToBeDeleted(state: FilesState) {
|
||||
state.filesToBeDeleted = [];
|
||||
},
|
||||
|
||||
removeAllSelectedFiles(state: FilesState) {
|
||||
state.selectedAnchorFile = null;
|
||||
state.unselectedAnchorFile = null;
|
||||
state.shiftSelectedFiles = [];
|
||||
state.selectedFiles = [];
|
||||
},
|
||||
|
||||
setShiftSelectedFiles(state: FilesState, files) {
|
||||
state.shiftSelectedFiles = files;
|
||||
},
|
||||
|
||||
pushUpload(state: FilesState, file) {
|
||||
state.uploading.push(file);
|
||||
},
|
||||
|
||||
setProgress(state: FilesState, { Key, progress }) {
|
||||
const file = state.uploading.find((file) => file.Key === Key);
|
||||
|
||||
if (file === undefined) {
|
||||
throw new Error(`No file found with key ${JSON.stringify(Key)}`);
|
||||
}
|
||||
|
||||
file.progress = progress;
|
||||
},
|
||||
|
||||
finishUpload(state: FilesState, Key) {
|
||||
state.uploading = state.uploading.filter((file) => file.Key !== Key);
|
||||
},
|
||||
|
||||
setOpenedDropdown(state: FilesState, id) {
|
||||
state.openedDropdown = id;
|
||||
},
|
||||
|
||||
sort(state: FilesState, headingSorted) {
|
||||
const flip = (orderBy) => (orderBy === 'asc' ? 'desc' : 'asc');
|
||||
|
||||
state.orderBy = state.headingSorted === headingSorted ? flip(state.orderBy) : 'asc';
|
||||
state.headingSorted = headingSorted;
|
||||
},
|
||||
|
||||
setObjectPathForModal(state: FilesState, path) {
|
||||
state.objectPathForModal = path;
|
||||
},
|
||||
|
||||
setObjectsCount(state: FilesState, count: number) {
|
||||
state.objectsCount = count;
|
||||
},
|
||||
|
||||
addUploadToChain(state: FilesState, fn) {
|
||||
state.uploadChain = state.uploadChain.then(fn);
|
||||
},
|
||||
|
||||
clear(state: FilesState) {
|
||||
state.s3 = null;
|
||||
state.accessKey = null;
|
||||
state.path = '';
|
||||
state.bucket = '';
|
||||
state.browserRoot = '/';
|
||||
state.files = [];
|
||||
state.uploadChain = Promise.resolve();
|
||||
state.uploading = [];
|
||||
state.selectedAnchorFile = null;
|
||||
state.unselectedAnchorFile = null;
|
||||
state.selectedFiles = [];
|
||||
state.shiftSelectedFiles = [];
|
||||
state.filesToBeDeleted = [];
|
||||
state.fetchSharedLink = () => 'javascript:null';
|
||||
state.fetchPreviewAndMapUrl = () => 'javascript:null';
|
||||
state.openedDropdown = null;
|
||||
state.headingSorted = 'name';
|
||||
state.orderBy = 'asc';
|
||||
state.openModalOnFirstUpload = false;
|
||||
state.objectPathForModal = '';
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async list({ commit, state, dispatch }, path = state.path) {
|
||||
if (listCache.has(path)) {
|
||||
commit('updateFiles', {
|
||||
path,
|
||||
files: listCache.get(path),
|
||||
});
|
||||
}
|
||||
|
||||
assertIsInitialized(state);
|
||||
|
||||
const response = await state.s3
|
||||
.listObjects({
|
||||
Bucket: state.bucket,
|
||||
Delimiter: '/',
|
||||
Prefix: path,
|
||||
})
|
||||
.promise();
|
||||
|
||||
const { Contents, CommonPrefixes } = response;
|
||||
|
||||
if (Contents === undefined) {
|
||||
throw new Error('Bad S3 listObjects() response: "Contents" undefined');
|
||||
}
|
||||
|
||||
if (CommonPrefixes === undefined) {
|
||||
throw new Error(
|
||||
'Bad S3 listObjects() response: "CommonPrefixes" undefined',
|
||||
);
|
||||
}
|
||||
|
||||
Contents.sort((a, b) => {
|
||||
if (
|
||||
a === undefined ||
|
||||
a.LastModified === undefined ||
|
||||
b === undefined ||
|
||||
b.LastModified === undefined ||
|
||||
a.LastModified === b.LastModified
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return a.LastModified < b.LastModified ? -1 : 1;
|
||||
});
|
||||
|
||||
type DefinedCommonPrefix = CommonPrefix & {
|
||||
Prefix: string;
|
||||
};
|
||||
|
||||
const isPrefixDefined = (
|
||||
value: CommonPrefix,
|
||||
): value is DefinedCommonPrefix => value.Prefix !== undefined;
|
||||
|
||||
const prefixToFolder = ({
|
||||
Prefix,
|
||||
}: {
|
||||
Prefix: string;
|
||||
}): BrowserObject => ({
|
||||
Key: Prefix.slice(path.length, -1),
|
||||
LastModified: 0,
|
||||
Size: 0,
|
||||
type: 'folder',
|
||||
});
|
||||
|
||||
const makeFileRelative = (file) => ({
|
||||
...file,
|
||||
Key: file.Key.slice(path.length),
|
||||
type: 'file',
|
||||
});
|
||||
|
||||
const isFileVisible = (file) =>
|
||||
file.Key.length > 0 && file.Key !== '.file_placeholder';
|
||||
|
||||
const files = [
|
||||
...CommonPrefixes.filter(isPrefixDefined).map(prefixToFolder),
|
||||
...Contents.map(makeFileRelative).filter(isFileVisible),
|
||||
];
|
||||
|
||||
listCache.set(path, files);
|
||||
commit('updateFiles', {
|
||||
path,
|
||||
files,
|
||||
});
|
||||
},
|
||||
|
||||
async back({ state, dispatch }) {
|
||||
const getParentDirectory = (path) => {
|
||||
let i = path.length - 2;
|
||||
|
||||
while (path[i - 1] !== '/' && i > 0) {
|
||||
i--;
|
||||
}
|
||||
|
||||
return path.slice(0, i);
|
||||
};
|
||||
|
||||
dispatch('list', getParentDirectory(state.path));
|
||||
},
|
||||
|
||||
async getObjectCount({ commit, state }) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
const responseV2 = await state.s3
|
||||
.listObjectsV2({
|
||||
Bucket: state.bucket,
|
||||
})
|
||||
.promise();
|
||||
|
||||
commit('setObjectsCount', responseV2.KeyCount === undefined ? 0 : responseV2.KeyCount);
|
||||
},
|
||||
|
||||
async upload({ commit, state, dispatch }, { e }: { e: DragEvent }) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
type Item = DataTransferItem | FileSystemEntry;
|
||||
|
||||
const items: Item[] = e.dataTransfer
|
||||
? [...e.dataTransfer.items]
|
||||
: e.target !== null
|
||||
? ((e.target as unknown) as { files: FileSystemEntry[] }).files
|
||||
: [];
|
||||
|
||||
async function* traverse(item: Item | Item[], path = '') {
|
||||
if ('isFile' in item && item.isFile === true) {
|
||||
const file = await new Promise(item.file.bind(item));
|
||||
yield { path, file };
|
||||
} else if (item instanceof File) {
|
||||
let relativePath = '';
|
||||
// on Firefox mobile, item.webkitRelativePath might be `undefined`
|
||||
if (item.webkitRelativePath) {
|
||||
relativePath = item.webkitRelativePath
|
||||
.split('/')
|
||||
.slice(0, -1)
|
||||
.join('/');
|
||||
}
|
||||
|
||||
if (relativePath.length) {
|
||||
relativePath += '/';
|
||||
}
|
||||
|
||||
yield { path: relativePath, file: item };
|
||||
} else if ('isFile' in item && item.isDirectory) {
|
||||
const dirReader = item.createReader();
|
||||
|
||||
const entries = await new Promise(
|
||||
dirReader.readEntries.bind(dirReader),
|
||||
);
|
||||
|
||||
for (const entry of entries) {
|
||||
yield* traverse(
|
||||
(entry as FileSystemEntry) as Item,
|
||||
path + item.name + '/',
|
||||
);
|
||||
}
|
||||
} else if ('length' in item && typeof item.length === 'number') {
|
||||
for (const i of item) {
|
||||
yield* traverse(i);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Item is not directory or file');
|
||||
}
|
||||
}
|
||||
|
||||
const isFileSystemEntry = (
|
||||
a: FileSystemEntry | null,
|
||||
): a is FileSystemEntry => a !== null;
|
||||
|
||||
const iterator = [...items]
|
||||
.map((item) =>
|
||||
'webkitGetAsEntry' in item ? item.webkitGetAsEntry() : item,
|
||||
)
|
||||
.filter(isFileSystemEntry) as FileSystemEntry[];
|
||||
|
||||
const fileNames = state.files.map((file) => file.Key);
|
||||
|
||||
function getUniqueFileName(fileName) {
|
||||
for (let count = 1; fileNames.includes(fileName); count++) {
|
||||
if (count > 1) {
|
||||
fileName = fileName.replace(/\((\d+)\)(.*)/, `(${count})$2`);
|
||||
} else {
|
||||
fileName = fileName.replace(/([^.]*)(.*)/, `$1 (${count})$2`);
|
||||
}
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
for await (const { path, file } of traverse(iterator)) {
|
||||
const directories = path.split('/');
|
||||
directories[0] = getUniqueFileName(directories[0]);
|
||||
|
||||
const fileName = getUniqueFileName(directories.join('/') + file.name);
|
||||
|
||||
const params = {
|
||||
Bucket: state.bucket,
|
||||
Key: state.path + fileName,
|
||||
Body: file,
|
||||
};
|
||||
|
||||
// If file size exceeds 1 GB, show warning notification
|
||||
if (file.size > (1024 * 1024 * 1024)) {
|
||||
const appStore = useAppStore();
|
||||
appStore.setLargeUploadWarningNotification(true);
|
||||
}
|
||||
|
||||
const upload = state.s3.upload(
|
||||
{ ...params },
|
||||
{ partSize: 64 * 1024 * 1024 },
|
||||
);
|
||||
|
||||
upload.on('httpUploadProgress', async (progress) => {
|
||||
commit('setProgress', {
|
||||
Key: params.Key,
|
||||
progress: Math.round((progress.loaded / progress.total) * 100),
|
||||
});
|
||||
});
|
||||
|
||||
commit('pushUpload', {
|
||||
...params,
|
||||
upload,
|
||||
progress: 0,
|
||||
});
|
||||
|
||||
commit('addUploadToChain', async () => {
|
||||
if (
|
||||
state.uploading.findIndex((file) => file.Key === params.Key) === -1
|
||||
) {
|
||||
// upload cancelled or removed
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
await upload.promise();
|
||||
} catch (error) {
|
||||
const limitExceededError = 'storage limit exceeded';
|
||||
if (error.message.includes(limitExceededError)) {
|
||||
dispatch('error', { message: `Error: ${limitExceededError}`, source: AnalyticsErrorEventSource.OBJECT_UPLOAD_ERROR }, { root: true });
|
||||
} else {
|
||||
dispatch('error', { message: error.message, source: AnalyticsErrorEventSource.OBJECT_UPLOAD_ERROR }, { root: true });
|
||||
}
|
||||
}
|
||||
|
||||
await dispatch('list');
|
||||
|
||||
const uploadedFiles = state.files.filter(
|
||||
(file) => file.type === 'file',
|
||||
);
|
||||
|
||||
if (uploadedFiles.length === 1 && !path && state.openModalOnFirstUpload) {
|
||||
commit('setObjectPathForModal', params.Key);
|
||||
const appStore = useAppStore();
|
||||
appStore.updateActiveModal(MODALS.objectDetails);
|
||||
}
|
||||
|
||||
commit('finishUpload', params.Key);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async createFolder({ state, dispatch }, name) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
await state.s3
|
||||
.putObject({
|
||||
Bucket: state.bucket,
|
||||
Key: state.path + name + '/.file_placeholder',
|
||||
})
|
||||
.promise();
|
||||
|
||||
dispatch('list');
|
||||
},
|
||||
|
||||
async delete(
|
||||
{ commit, dispatch, state }: FilesContext,
|
||||
{ path, file, folder },
|
||||
) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
await state.s3
|
||||
.deleteObject({
|
||||
Bucket: state.bucket,
|
||||
Key: path + file.Key,
|
||||
})
|
||||
.promise();
|
||||
|
||||
if (!folder) {
|
||||
await dispatch('list');
|
||||
commit('removeFileToBeDeleted', file);
|
||||
}
|
||||
},
|
||||
|
||||
async deleteFolder({ commit, dispatch, state }: FilesContext, { file, path }) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
async function recurse(filePath) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
const { Contents, CommonPrefixes } = await state.s3
|
||||
.listObjects({
|
||||
Bucket: state.bucket,
|
||||
Delimiter: '/',
|
||||
Prefix: filePath,
|
||||
})
|
||||
.promise();
|
||||
|
||||
if (Contents === undefined) {
|
||||
throw new Error(
|
||||
'Bad S3 listObjects() response: "Contents" undefined',
|
||||
);
|
||||
}
|
||||
|
||||
if (CommonPrefixes === undefined) {
|
||||
throw new Error(
|
||||
'Bad S3 listObjects() response: "CommonPrefixes" undefined',
|
||||
);
|
||||
}
|
||||
|
||||
async function thread() {
|
||||
if (Contents === undefined) {
|
||||
throw new Error(
|
||||
'Bad S3 listObjects() response: "Contents" undefined',
|
||||
);
|
||||
}
|
||||
|
||||
while (Contents.length) {
|
||||
const file = Contents.pop();
|
||||
|
||||
await dispatch('delete', {
|
||||
path: '',
|
||||
file,
|
||||
folder: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([thread(), thread(), thread()]);
|
||||
|
||||
for (const { Prefix } of CommonPrefixes) {
|
||||
await recurse(Prefix);
|
||||
}
|
||||
}
|
||||
|
||||
await recurse(path.length > 0 ? path + file.Key : file.Key + '/');
|
||||
|
||||
commit('removeFileToBeDeleted', file);
|
||||
await dispatch('list');
|
||||
},
|
||||
|
||||
async deleteSelected({ state, dispatch, commit }) {
|
||||
const filesToDelete = [
|
||||
...state.selectedFiles,
|
||||
...state.shiftSelectedFiles,
|
||||
];
|
||||
|
||||
if (state.selectedAnchorFile) {
|
||||
filesToDelete.push(state.selectedAnchorFile);
|
||||
}
|
||||
|
||||
commit('setFilesToBeDeleted', filesToDelete);
|
||||
|
||||
await Promise.all(
|
||||
filesToDelete.map(async (file) => {
|
||||
if (file.type === 'file')
|
||||
await dispatch('delete', {
|
||||
file,
|
||||
path: state.path,
|
||||
});
|
||||
else
|
||||
await dispatch('deleteFolder', {
|
||||
file,
|
||||
path: state.path,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
dispatch('clearAllSelectedFiles');
|
||||
},
|
||||
|
||||
async download({ state }, file) {
|
||||
assertIsInitialized(state);
|
||||
|
||||
const url = state.s3.getSignedUrl('getObject', {
|
||||
Bucket: state.bucket,
|
||||
Key: state.path + file.Key,
|
||||
});
|
||||
const downloadURL = function(data, fileName) {
|
||||
const a = document.createElement('a');
|
||||
a.href = data;
|
||||
a.download = fileName;
|
||||
a.click();
|
||||
};
|
||||
|
||||
downloadURL(url, file.Key);
|
||||
},
|
||||
|
||||
updateSelectedFiles({ commit }, files) {
|
||||
commit('setSelectedFiles', [...files]);
|
||||
},
|
||||
|
||||
updateShiftSelectedFiles({ commit }, files) {
|
||||
commit('setShiftSelectedFiles', files);
|
||||
},
|
||||
|
||||
addFileToBeDeleted({ commit }, file) {
|
||||
commit('setFilesToBeDeleted', [file]);
|
||||
},
|
||||
|
||||
removeFileFromToBeDeleted({ commit }, file) {
|
||||
commit('removeFileToBeDeleted', file);
|
||||
},
|
||||
|
||||
clearAllSelectedFiles({ commit, state }) {
|
||||
if (state.selectedAnchorFile || state.unselectedAnchorFile) {
|
||||
commit('removeAllSelectedFiles');
|
||||
}
|
||||
},
|
||||
|
||||
openDropdown({ commit, dispatch }, id) {
|
||||
dispatch('clearAllSelectedFiles');
|
||||
commit('setOpenedDropdown', id);
|
||||
},
|
||||
|
||||
closeDropdown({ commit }) {
|
||||
commit('setOpenedDropdown', null);
|
||||
},
|
||||
|
||||
openFileBrowserDropdown({ commit }) {
|
||||
commit('setOpenedDropdown', 'FileBrowser');
|
||||
},
|
||||
|
||||
cancelUpload({ commit, state }, key) {
|
||||
const file = state.uploading.find((file) => file.Key === key);
|
||||
|
||||
if (typeof file === 'object') {
|
||||
if (file.progress !== undefined && file.upload && file.progress > 0) {
|
||||
file.upload.abort();
|
||||
}
|
||||
|
||||
commit('finishUpload', key);
|
||||
} else {
|
||||
throw new Error(`File ${JSON.stringify(key)} not found`);
|
||||
}
|
||||
},
|
||||
|
||||
closeAllInteractions({ state, dispatch }) {
|
||||
if (state.openedDropdown) {
|
||||
dispatch('closeDropdown');
|
||||
}
|
||||
|
||||
if (state.selectedAnchorFile) {
|
||||
dispatch('clearAllSelectedFiles');
|
||||
}
|
||||
},
|
||||
|
||||
clear({ commit }) {
|
||||
commit('clear');
|
||||
},
|
||||
},
|
||||
});
|
@ -36,7 +36,7 @@ export class FilesState {
|
||||
uploadChain: Promise<void> = Promise.resolve();
|
||||
uploading: BrowserObject[] = [];
|
||||
selectedAnchorFile: BrowserObject | null = null;
|
||||
unselectedAnchorFile: null | string = null;
|
||||
unselectedAnchorFile: BrowserObject | null = null;
|
||||
selectedFiles: BrowserObject[] = [];
|
||||
shiftSelectedFiles: BrowserObject[] = [];
|
||||
filesToBeDeleted: BrowserObject[] = [];
|
||||
@ -75,7 +75,7 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export const useFilesStore = defineStore('files', () => {
|
||||
export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
||||
const state = reactive<FilesState>(new FilesState());
|
||||
|
||||
const sortedFiles = computed(() => {
|
||||
@ -128,7 +128,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
bucket: string;
|
||||
endpoint: string;
|
||||
browserRoot: string;
|
||||
openModalOnFirstUpload: boolean;
|
||||
openModalOnFirstUpload?: boolean;
|
||||
fetchSharedLink: (arg0: string) => Promisable<string>;
|
||||
fetchPreviewAndMapUrl: (arg0: string) => Promisable<string>;
|
||||
}): void {
|
||||
@ -182,7 +182,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
state.files = files;
|
||||
}
|
||||
|
||||
async function list(path = state.path) {
|
||||
async function list(path = state.path): Promise<void> {
|
||||
if (listCache.has(path)) {
|
||||
updateFiles(path, listCache.get(path));
|
||||
}
|
||||
@ -274,7 +274,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
list(getParentDirectory(state.path));
|
||||
}
|
||||
|
||||
async function getObjectCount() {
|
||||
async function getObjectCount(): Promise<void> {
|
||||
assertIsInitialized(state);
|
||||
|
||||
const responseV2 = await state.s3
|
||||
@ -286,12 +286,12 @@ export const useFilesStore = defineStore('files', () => {
|
||||
state.objectsCount = responseV2.KeyCount === undefined ? 0 : responseV2.KeyCount;
|
||||
}
|
||||
|
||||
async function upload({ e }: { e: DragEvent }) {
|
||||
async function upload({ e }: { e: DragEvent | Event }): Promise<void> {
|
||||
assertIsInitialized(state);
|
||||
|
||||
type Item = DataTransferItem | FileSystemEntry;
|
||||
|
||||
const items: Item[] = e.dataTransfer
|
||||
const items: Item[] = 'dataTransfer' in e && e.dataTransfer
|
||||
? [...e.dataTransfer.items]
|
||||
: e.target !== null
|
||||
? ((e.target as unknown) as { files: FileSystemEntry[] }).files
|
||||
@ -362,6 +362,8 @@ export const useFilesStore = defineStore('files', () => {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
for await (const { path, file } of traverse(iterator)) {
|
||||
const directories = path.split('/');
|
||||
directories[0] = getUniqueFileName(directories[0]);
|
||||
@ -374,6 +376,11 @@ export const useFilesStore = defineStore('files', () => {
|
||||
Body: file,
|
||||
};
|
||||
|
||||
// If file size exceeds 1 GB, show warning notification
|
||||
if (file.size > (1024 * 1024 * 1024)) {
|
||||
appStore.setLargeUploadWarningNotification(true);
|
||||
}
|
||||
|
||||
const upload = state.s3.upload(
|
||||
{ ...params },
|
||||
{ partSize: 64 * 1024 * 1024 },
|
||||
@ -425,7 +432,6 @@ export const useFilesStore = defineStore('files', () => {
|
||||
|
||||
if (uploadedFiles.length === 1 && !path && state.openModalOnFirstUpload) {
|
||||
state.objectPathForModal = params.Key;
|
||||
const appStore = useAppStore();
|
||||
appStore.updateActiveModal(MODALS.objectDetails);
|
||||
}
|
||||
|
||||
@ -434,7 +440,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function createFolder(name) {
|
||||
async function createFolder(name): Promise<void> {
|
||||
assertIsInitialized(state);
|
||||
|
||||
await state.s3
|
||||
@ -447,7 +453,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
list();
|
||||
}
|
||||
|
||||
async function deleteObject(path: string, file?: S3.Object | BrowserObject, isFolder = false) {
|
||||
async function deleteObject(path: string, file?: S3.Object | BrowserObject, isFolder = false): Promise<void> {
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
@ -467,7 +473,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFolder(file: BrowserObject, path: string) {
|
||||
async function deleteFolder(file: BrowserObject, path: string): Promise<void> {
|
||||
assertIsInitialized(state);
|
||||
|
||||
async function recurse(filePath) {
|
||||
@ -520,7 +526,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
await list();
|
||||
}
|
||||
|
||||
async function deleteSelected() {
|
||||
async function deleteSelected(): Promise<void> {
|
||||
const filesToDelete = [
|
||||
...state.selectedFiles,
|
||||
...state.shiftSelectedFiles,
|
||||
@ -545,7 +551,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
clearAllSelectedFiles();
|
||||
}
|
||||
|
||||
async function download(file) {
|
||||
function download(file): void {
|
||||
assertIsInitialized(state);
|
||||
|
||||
const url = state.s3.getSignedUrl('getObject', {
|
||||
@ -562,25 +568,25 @@ export const useFilesStore = defineStore('files', () => {
|
||||
downloadURL(url, file.Key);
|
||||
}
|
||||
|
||||
function updateSelectedFiles(files) {
|
||||
function updateSelectedFiles(files): void {
|
||||
state.selectedFiles = [...files];
|
||||
}
|
||||
|
||||
function updateShiftSelectedFiles(files) {
|
||||
function updateShiftSelectedFiles(files): void {
|
||||
state.shiftSelectedFiles = files;
|
||||
}
|
||||
|
||||
function addFileToBeDeleted(file) {
|
||||
function addFileToBeDeleted(file): void {
|
||||
state.filesToBeDeleted = [...state.filesToBeDeleted, file];
|
||||
}
|
||||
|
||||
function removeFileFromToBeDeleted(file) {
|
||||
function removeFileFromToBeDeleted(file): void {
|
||||
state.filesToBeDeleted = state.filesToBeDeleted.filter(
|
||||
(singleFile) => singleFile.Key !== file.Key,
|
||||
);
|
||||
}
|
||||
|
||||
function clearAllSelectedFiles() {
|
||||
function clearAllSelectedFiles(): void {
|
||||
if (state.selectedAnchorFile || state.unselectedAnchorFile) {
|
||||
state.selectedAnchorFile = null;
|
||||
state.unselectedAnchorFile = null;
|
||||
@ -589,20 +595,20 @@ export const useFilesStore = defineStore('files', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function openDropdown(id) {
|
||||
function openDropdown(id): void {
|
||||
clearAllSelectedFiles();
|
||||
state.openedDropdown = id;
|
||||
}
|
||||
|
||||
function closeDropdown() {
|
||||
function closeDropdown(): void {
|
||||
state.openedDropdown = null;
|
||||
}
|
||||
|
||||
function openFileBrowserDropdown() {
|
||||
function openFileBrowserDropdown(): void {
|
||||
state.openedDropdown = 'FileBrowser';
|
||||
}
|
||||
|
||||
function cancelUpload(key) {
|
||||
function cancelUpload(key): void {
|
||||
const file = state.uploading.find((file) => file.Key === key);
|
||||
|
||||
if (typeof file === 'object') {
|
||||
@ -616,7 +622,26 @@ export const useFilesStore = defineStore('files', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function closeAllInteractions() {
|
||||
function sort(headingSorted: string): void {
|
||||
const flip = (orderBy) => (orderBy === 'asc' ? 'desc' : 'asc');
|
||||
|
||||
state.orderBy = state.headingSorted === headingSorted ? flip(state.orderBy) : 'asc';
|
||||
state.headingSorted = headingSorted;
|
||||
}
|
||||
|
||||
function setObjectPathForModal(path: string): void {
|
||||
state.objectPathForModal = path;
|
||||
}
|
||||
|
||||
function setSelectedAnchorFile(file: BrowserObject | null): void {
|
||||
state.selectedAnchorFile = file;
|
||||
}
|
||||
|
||||
function setUnselectedAnchorFile(file: BrowserObject | null): void {
|
||||
state.unselectedAnchorFile = file;
|
||||
}
|
||||
|
||||
function closeAllInteractions(): void {
|
||||
if (state.openedDropdown) {
|
||||
closeDropdown();
|
||||
}
|
||||
@ -626,7 +651,7 @@ export const useFilesStore = defineStore('files', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function clear() {
|
||||
function clear(): void {
|
||||
state.s3 = null;
|
||||
state.accessKey = null;
|
||||
state.path = '';
|
||||
@ -650,6 +675,36 @@ export const useFilesStore = defineStore('files', () => {
|
||||
}
|
||||
|
||||
return {
|
||||
filesState: state,
|
||||
state,
|
||||
sortedFiles,
|
||||
isInitialized,
|
||||
uploadingLength,
|
||||
init,
|
||||
reinit,
|
||||
updateFiles,
|
||||
list,
|
||||
back,
|
||||
sort,
|
||||
getObjectCount,
|
||||
upload,
|
||||
createFolder,
|
||||
deleteObject,
|
||||
deleteFolder,
|
||||
deleteSelected,
|
||||
download,
|
||||
updateSelectedFiles,
|
||||
updateShiftSelectedFiles,
|
||||
addFileToBeDeleted,
|
||||
removeFileFromToBeDeleted,
|
||||
clearAllSelectedFiles,
|
||||
setObjectPathForModal,
|
||||
openDropdown,
|
||||
closeDropdown,
|
||||
openFileBrowserDropdown,
|
||||
setSelectedAnchorFile,
|
||||
setUnselectedAnchorFile,
|
||||
cancelUpload,
|
||||
closeAllInteractions,
|
||||
clear,
|
||||
};
|
||||
});
|
||||
|
@ -1,21 +0,0 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
type Mutation<State> =
|
||||
(state: State, ...args: any[]) => any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
type Action<Context> =
|
||||
(context: Context, ...args: any[]) => (Promise<any> | void | any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
type Getter<State, Context> =
|
||||
Context extends {rootGetters: any} ? ( // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
((state: State) => any) | // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
((state: State, rootGetters: Context['rootGetters']) => any) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
) : ((state: State) => any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
export interface StoreModule<State, Context> { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
state: State;
|
||||
mutations: Record<string, Mutation<State>>
|
||||
actions: Record<string, Action<Context>>
|
||||
getters?: Record<string, Getter<State, Context>>
|
||||
}
|
@ -2,24 +2,15 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import VueRouter, { Route } from 'vue-router';
|
||||
import VueRouter from 'vue-router';
|
||||
|
||||
import { store } from '@/store';
|
||||
import { Notificator } from '@/utils/plugins/notificator';
|
||||
|
||||
// TODO: remove after updating router and store deps.
|
||||
export function useRoute() {
|
||||
return getCurrentInstance()?.proxy.$route || {} as Route;
|
||||
}
|
||||
|
||||
export function useRouter() {
|
||||
return getCurrentInstance()?.proxy.$router || {} as VueRouter;
|
||||
}
|
||||
|
||||
export function useStore() {
|
||||
return (getCurrentInstance()?.proxy.$store || {}) as typeof store;
|
||||
}
|
||||
|
||||
export function useNotify() {
|
||||
return getCurrentInstance()?.proxy.$notify || {} as Notificator;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ import { User } from '@/types/users';
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { MODALS } from '@/utils/constants/appStatePopUps';
|
||||
import { useABTestingStore } from '@/store/modules/abTestingStore';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
@ -150,6 +150,7 @@ import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import UploadNotification from '@/components/notifications/UploadNotification.vue';
|
||||
import NavigationArea from '@/components/navigation/NavigationArea.vue';
|
||||
@ -177,7 +178,8 @@ const usersStore = useUsersStore();
|
||||
const abTestingStore = useABTestingStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const notificationsStore = useNotificationsStore();
|
||||
const store = useStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const notify = useNotify();
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
@ -493,7 +495,7 @@ function restartSessionTimers(): void {
|
||||
}, sessionRefreshInterval.value);
|
||||
|
||||
inactivityTimerId.value = setTimeout(async () => {
|
||||
if (store.getters['files/uploadingLength']) {
|
||||
if (obStore.uploadingLength) {
|
||||
await refreshSession();
|
||||
return;
|
||||
}
|
||||
@ -584,7 +586,7 @@ async function handleInactive(): Promise<void> {
|
||||
appStore.clear(),
|
||||
billingStore.clear(),
|
||||
abTestingStore.reset(),
|
||||
store.dispatch('files/clear'),
|
||||
obStore.clear(),
|
||||
]);
|
||||
|
||||
resetActivityEvents.forEach((eventName: string) => {
|
||||
|
@ -161,7 +161,7 @@
|
||||
<script setup lang="ts">
|
||||
import VueRecaptcha from 'vue-recaptcha';
|
||||
import VueHcaptcha from '@hcaptcha/vue-hcaptcha';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { ErrorMFARequired } from '@/api/errors/ErrorMFARequired';
|
||||
@ -173,7 +173,7 @@ import { ErrorBadRequest } from '@/api/errors/ErrorBadRequest';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { TokenInfo } from '@/types/users';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { useNotify, useRoute, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { useAppStore } from '@/store/modules/appStore';
|
||||
import { MultiCaptchaConfig, PartneredSatellite } from '@/types/config';
|
||||
@ -224,9 +224,9 @@ const analytics = new AnalyticsHttpApi();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const usersStore = useUsersStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
const route = useRoute();
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
|
||||
/**
|
||||
* Name of the current satellite.
|
||||
@ -254,14 +254,14 @@ const captchaConfig = computed((): MultiCaptchaConfig => {
|
||||
* Makes activated banner visible on successful account activation.
|
||||
*/
|
||||
onMounted(() => {
|
||||
isActivatedBannerShown.value = !!route.query.activated;
|
||||
isActivatedError.value = route.query.activated === 'false';
|
||||
isActivatedBannerShown.value = !!router.currentRoute.query.activated;
|
||||
isActivatedError.value = router.currentRoute.query.activated === 'false';
|
||||
|
||||
if (appStore.state.config.allProjectsDashboard) {
|
||||
returnURL.value = RouteConfig.AllProjectsDashboard.path;
|
||||
}
|
||||
|
||||
returnURL.value = route.query.return_url as string || returnURL.value;
|
||||
returnURL.value = router.currentRoute.query.return_url as string || returnURL.value;
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -121,7 +121,7 @@ import {
|
||||
AnalyticsErrorEventSource,
|
||||
} from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
|
||||
import { FetchState } from '@/utils/constants/fetchStateEnum';
|
||||
@ -138,6 +138,7 @@ import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import InactivityModal from '@/components/modals/InactivityModal.vue';
|
||||
import BetaSatBar from '@/components/infoBars/BetaSatBar.vue';
|
||||
@ -152,7 +153,6 @@ import LoaderImage from '@/../static/images/common/loadIcon.svg';
|
||||
|
||||
const nativeRouter = useRouter();
|
||||
const router = reactive(nativeRouter);
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const bucketsStore = useBucketsStore();
|
||||
@ -164,6 +164,7 @@ const agStore = useAccessGrantsStore();
|
||||
const appStore = useAppStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const notificationsStore = useNotificationsStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const analytics = new AnalyticsHttpApi();
|
||||
const auth: AuthHttpApi = new AuthHttpApi();
|
||||
@ -387,7 +388,7 @@ async function handleInactive(): Promise<void> {
|
||||
appStore.clear(),
|
||||
billingStore.clear(),
|
||||
abTestingStore.reset(),
|
||||
store.dispatch('files/clear'),
|
||||
obStore.clear(),
|
||||
]);
|
||||
|
||||
resetActivityEvents.forEach((eventName: string) => {
|
||||
@ -482,7 +483,7 @@ function restartSessionTimers(): void {
|
||||
}, sessionRefreshInterval.value);
|
||||
|
||||
inactivityTimerId.value = setTimeout(async () => {
|
||||
if (store.getters['files/uploadingLength']) {
|
||||
if (obStore.uploadingLength) {
|
||||
await refreshSession();
|
||||
return;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import MyAccountButton from '@/views/all-dashboard/components/MyAccountButton.vue';
|
||||
import {
|
||||
AnalyticsErrorEventSource,
|
||||
@ -112,6 +112,7 @@ import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
@ -129,7 +130,6 @@ import ArrowIcon from '@/../static/images/navigation/arrowExpandRight.svg';
|
||||
import CrossIcon from '@/../static/images/common/closeCross.svg';
|
||||
import MenuIcon from '@/../static/images/navigation/menu.svg';
|
||||
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
@ -142,6 +142,7 @@ const abTestingStore = useABTestingStore();
|
||||
const billingStore = useBillingStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const notificationsStore = useNotificationsStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const analytics = new AnalyticsHttpApi();
|
||||
const auth = new AuthHttpApi();
|
||||
@ -242,7 +243,7 @@ async function onLogout(): Promise<void> {
|
||||
appStore.clear(),
|
||||
billingStore.clear(),
|
||||
abTestingStore.reset(),
|
||||
store.dispatch('files/clear'),
|
||||
obStore.clear(),
|
||||
]);
|
||||
|
||||
try {
|
||||
|
@ -52,7 +52,7 @@
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter } from '@/utils/hooks';
|
||||
import {
|
||||
AnalyticsErrorEventSource,
|
||||
AnalyticsEvent,
|
||||
@ -69,6 +69,7 @@ import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
|
||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||
|
||||
import AccountIcon from '@/../static/images/navigation/account.svg';
|
||||
import ArrowDownIcon from '@/../static/images/common/dropIcon.svg';
|
||||
@ -79,7 +80,6 @@ import BillingIcon from '@/../static/images/navigation/billing.svg';
|
||||
import SettingsIcon from '@/../static/images/navigation/settings.svg';
|
||||
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const analytics = new AnalyticsHttpApi();
|
||||
@ -94,6 +94,7 @@ const billingStore = useBillingStore();
|
||||
const usersStore = useUsersStore();
|
||||
const abTestingStore = useABTestingStore();
|
||||
const notificationsStore = useNotificationsStore();
|
||||
const obStore = useObjectBrowserStore();
|
||||
|
||||
const isHoveredOver = ref(false);
|
||||
|
||||
@ -167,7 +168,7 @@ async function onLogout(): Promise<void> {
|
||||
appStore.clear(),
|
||||
billingStore.clear(),
|
||||
abTestingStore.reset(),
|
||||
store.dispatch('files/clear'),
|
||||
obStore.clear(),
|
||||
]);
|
||||
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user