Skip to content

Commit 7c0c613

Browse files
committed
Fixed cloud file selectors
1 parent d5ac4fc commit 7c0c613

File tree

7 files changed

+409
-405
lines changed

7 files changed

+409
-405
lines changed
Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* The MIT License (MIT)
33
*
4-
* Igor Zinken 2023 - https://www.igorski.nl
4+
* Igor Zinken 2023-2025 - https://www.igorski.nl
55
*
66
* Permission is hereby granted, free of charge, to any person obtaining a copy of
77
* this software and associated documentation files (the "Software"), to deal in
@@ -20,72 +20,74 @@
2020
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2121
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2222
*/
23+
<template src="../cloud-file-selector.html"></template>
24+
2325
<script lang="ts">
2426
import type { Component } from "vue";
25-
import { mapMutations } from "vuex";
26-
import CloudFileSelector from "../cloud-file-selector.vue";
27-
import type { FileNode } from "../cloud-file-selector.vue";
27+
import CloudFileSelector from "../cloud-file-selector";
2828
import S3ImagePreview from "./aws-s3-image-preview.vue";
2929
import { PROJECT_FILE_EXTENSION } from "@/definitions/file-types";
30-
import { STORAGE_TYPES } from "@/definitions/storage-types";
30+
import { type FileNode, STORAGE_TYPES } from "@/definitions/storage-types";
3131
import { getS3Service } from "@/utils/cloud-service-loader";
3232
3333
let listFolder, createFolder, downloadFileAsBlob, deleteEntry;
3434
35-
export default {
36-
extends: CloudFileSelector,
37-
data: () => ({
38-
LAST_FOLDER_STORAGE_KEY: "bpy_s3Db",
39-
STORAGE_PROVIDER: STORAGE_TYPES.S3,
40-
}),
41-
computed: {
42-
imagePreviewComponent(): Component {
43-
return S3ImagePreview;
44-
},
45-
},
46-
async created(): Promise<void> {
47-
({ listFolder, createFolder, downloadFileAsBlob, deleteEntry } = await getS3Service() );
48-
this.tree.path = "";
35+
export default {
36+
mixins: [ CloudFileSelector ],
37+
data: () => ({
38+
LAST_FOLDER_STORAGE_KEY: "bpy_s3Db",
39+
STORAGE_PROVIDER: STORAGE_TYPES.S3,
40+
}),
41+
computed: {
42+
imagePreviewComponent(): Component {
43+
return S3ImagePreview;
44+
},
45+
},
46+
async created(): Promise<void> {
47+
({ listFolder, createFolder, downloadFileAsBlob, deleteEntry } = await getS3Service() );
48+
this.tree.path = "";
4949
50-
let pathToRetrieve = this.tree.path;
51-
try {
52-
const { tree, path } = JSON.parse( sessionStorage.getItem( this.LAST_FOLDER_STORAGE_KEY ));
53-
this.tree = { ...this.tree, ...tree };
54-
pathToRetrieve = path;
55-
} catch {
56-
// no tree stored in SessionStorage, continue.
57-
}
58-
this.retrieveFiles( pathToRetrieve );
59-
},
60-
methods: {
61-
/* base component overrides */
62-
_getServicePathForNode( node: FileNode ): string {
63-
return node.key ?? node.path;
64-
},
65-
async _listFolder( path: string ): Promise<FileNode[]> {
66-
const entries = await listFolder( path );
67-
return entries;
68-
},
69-
async _createFolder( parent: string, name: string ): Promise<Boolean> {
70-
return createFolder( parent, name );
71-
},
72-
async _downloadFile( node: FileNode, returnAsURL = false ): Promise<Blob | string | null> {
50+
let pathToRetrieve = this.tree.path;
51+
try {
52+
const { tree, path } = JSON.parse( sessionStorage.getItem( this.LAST_FOLDER_STORAGE_KEY ));
53+
this.tree = { ...this.tree, ...tree };
54+
pathToRetrieve = path;
55+
} catch {
56+
// no tree stored in SessionStorage, continue.
57+
}
58+
this.retrieveFiles( pathToRetrieve );
59+
},
60+
methods: {
61+
/* base component overrides */
62+
_getServicePathForNode( node: FileNode ): string {
63+
return node.key ?? node.path;
64+
},
65+
async _listFolder( path: string ): Promise<FileNode[]> {
66+
const entries = await listFolder( path );
67+
return entries;
68+
},
69+
async _createFolder( parent: string, name: string ): Promise<boolean> {
70+
return createFolder( parent, name );
71+
},
72+
async _downloadFile( node: FileNode, returnAsURL = false ): Promise<Blob | string | null> {
7373
return downloadFileAsBlob( node.key, returnAsURL );
74-
},
75-
async _deleteEntry( node: FileNode ): Promise<boolean> {
76-
return deleteEntry( node.key );
77-
},
78-
_mapEntry( entry: FileNode, children = [], parent = null ): FileNode {
79-
if ( entry.name.endsWith( PROJECT_FILE_EXTENSION )) {
80-
entry.type = PROJECT_FILE_EXTENSION;
81-
}
82-
return {
83-
...entry,
84-
path : entry.name,
85-
children,
86-
parent,
87-
};
88-
},
89-
}
90-
};
91-
</script>
74+
},
75+
async _deleteEntry( node: FileNode ): Promise<boolean> {
76+
return deleteEntry( node.key );
77+
},
78+
_mapEntry( entry: FileNode, children = [], parent = null ): FileNode {
79+
if ( entry.name.endsWith( PROJECT_FILE_EXTENSION )) {
80+
entry.type = PROJECT_FILE_EXTENSION;
81+
}
82+
return {
83+
...entry,
84+
path : entry.name,
85+
children,
86+
parent,
87+
};
88+
},
89+
}
90+
};
91+
</script>
92+
93+
<style lang="scss" src="../cloud-file-selector.scss" scoped />
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<div class="cloud-file-modal">
2+
<div class="component__header">
3+
<h2 v-t="'files'" class="component__title"></h2>
4+
<button
5+
type="button"
6+
class="component__header-button"
7+
@click="closeModal()"
8+
>&#215;</button>
9+
</div>
10+
<div ref="content" class="component__content">
11+
<div v-if="leaf" class="content__wrapper">
12+
<div class="breadcrumbs">
13+
<!-- parent folders -->
14+
<button
15+
v-for="parent in breadcrumbs"
16+
:key="parent.path"
17+
:disabled="disabled"
18+
type="button"
19+
class="breadcrumbs__button"
20+
@click="handleNodeClick( parent )"
21+
>{{ parent.name || "." }}</button>
22+
<!-- current folder -->
23+
<button
24+
:disabled="disabled"
25+
type="button"
26+
class="breadcrumbs__button breadcrumbs__button--active"
27+
>{{ leaf.name }}</button>
28+
</div>
29+
<div v-if="!loading" class="content__folders">
30+
<!-- files and folders within current leaf -->
31+
<p v-if="!filesAndFolders.length" v-t="'noImageFiles'"></p>
32+
<template v-else>
33+
<div
34+
v-for="node in filesAndFolders"
35+
:key="`entry_${node.path}`"
36+
class="entry"
37+
:class="{ 'entry__disabled': disabled }"
38+
>
39+
<div
40+
v-if="node.type === 'folder'"
41+
class="entry__icon entry__icon--folder"
42+
@click="handleNodeClick( node )"
43+
>
44+
<span class="title">{{ node.name }}</span>
45+
</div>
46+
<div
47+
v-else-if="node.type === 'bpy'"
48+
class="entry__icon entry__icon--document"
49+
@click="handleNodeClick( node )"
50+
>
51+
<span class="title">{{ node.name }}</span>
52+
</div>
53+
<component
54+
v-else
55+
:is="imagePreviewComponent"
56+
:node="node"
57+
class="entry__icon entry__icon--image-preview"
58+
@click="handleNodeClick( node )"
59+
/>
60+
<button
61+
type="button"
62+
class="entry__delete-button"
63+
:title="$t('delete')"
64+
@click="handleDeleteClick( node )"
65+
>x</button>
66+
</div>
67+
</template>
68+
</div>
69+
</div>
70+
</div>
71+
<div class="component__actions">
72+
<div class="component__actions-content">
73+
<div class="form component__actions-form">
74+
<div class="wrapper input">
75+
<input
76+
v-model="newFolderName"
77+
:placeholder="$t('newFolderName')"
78+
:disabled="disabled"
79+
type="text"
80+
class="input-field full"
81+
/>
82+
</div>
83+
</div>
84+
<button
85+
v-t="'createFolder'"
86+
type="button"
87+
class="button"
88+
:disabled="!newFolderName || disabled"
89+
@click="handleCreateFolderClick()"
90+
></button>
91+
</div>
92+
</div>
93+
</div>

0 commit comments

Comments
 (0)