Skip to content

Commit a6ff766

Browse files
authored
feat: adds Go To File dialog (#1077)
Signed-off-by: Pedro Lamas <pedrolamas@gmail.com>
1 parent fa56a5b commit a6ff766

File tree

8 files changed

+187
-37
lines changed

8 files changed

+187
-37
lines changed

components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,6 @@ declare module 'vue' {
132132
VToolbarItems: typeof import('vuetify/lib')['VToolbarItems']
133133
VToolbarTitle: typeof import('vuetify/lib')['VToolbarTitle']
134134
VTooltip: typeof import('vuetify/lib')['VTooltip']
135+
VVirtualScroll: typeof import('vuetify/lib')['VVirtualScroll']
135136
}
136137
}

src/components/widgets/filesystem/FileSystem.vue

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
@add-dir="handleAddDirDialog"
2727
@upload="handleUpload"
2828
@filter="handleFilter"
29+
@go-to-file="handleGoToFileDialog"
2930
/>
3031

3132
<file-system-bulk-actions
@@ -120,9 +121,12 @@
120121
@remove="handleRemove"
121122
/>
122123

123-
<!-- <pre>roots: {{ availableRoots }}</pre>
124-
<pre>currentRoot: {{ currentRoot }}<br />currentPath: {{ currentPath }}<br />visiblePath: {{ visiblePath }}</pre>
125-
<pre>dragState: {{ dragState }}</pre> -->
124+
<file-system-go-to-file-dialog
125+
v-if="goToFileDialogOpen"
126+
v-model="goToFileDialogOpen"
127+
:root="currentRoot"
128+
@path-change="loadFiles"
129+
/>
126130
</v-card>
127131
</template>
128132

@@ -149,6 +153,7 @@ import FileSystemContextMenu from './FileSystemContextMenu.vue'
149153
import FileEditorDialog from './FileEditorDialog.vue'
150154
import FileNameDialog from './FileNameDialog.vue'
151155
import FileSystemUploadDialog from './FileSystemUploadDialog.vue'
156+
import FileSystemGoToFileDialog from './FileSystemGoToFileDialog.vue'
152157
import FilePreviewDialog from './FilePreviewDialog.vue'
153158
import { AppTableHeader } from '@/types'
154159
import { FileWithPath, getFilesFromDataTransfer } from '@/util/file-system-entry'
@@ -168,6 +173,7 @@ import { FileWithPath, getFilesFromDataTransfer } from '@/util/file-system-entry
168173
FileEditorDialog,
169174
FileNameDialog,
170175
FileSystemUploadDialog,
176+
FileSystemGoToFileDialog,
171177
FilePreviewDialog
172178
}
173179
})
@@ -259,6 +265,8 @@ export default class FileSystem extends Mixins(StateMixin, FilesMixin, ServicesM
259265
src: ''
260266
}
261267
268+
goToFileDialogOpen = false
269+
262270
@Watch('filePreviewState.open')
263271
onFilePreviewStateChanged (value: boolean) {
264272
if (!value && this.filePreviewState.src.startsWith('blob:')) {
@@ -626,6 +634,11 @@ export default class FileSystem extends Mixins(StateMixin, FilesMixin, ServicesM
626634
}
627635
}
628636
637+
handleGoToFileDialog () {
638+
if (this.disabled) return
639+
this.goToFileDialogOpen = true
640+
}
641+
629642
handleFileOpenDialog (file: AppFile) {
630643
if (this.currentRoot === 'timelapse' && file.extension === 'zip') {
631644
// don't download zipped frames before opening preview

src/components/widgets/filesystem/FileSystemMenu.vue renamed to src/components/widgets/filesystem/FileSystemAddMenu.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ import { getFilesWithPathFromHTMLInputElement } from '@/util/file-system-entry'
128128
import { Component, Vue, Prop, Ref } from 'vue-property-decorator'
129129
130130
@Component({})
131-
export default class FileSystemMenu extends Vue {
131+
export default class FileSystemAddMenu extends Vue {
132132
@Prop({ type: String, required: true })
133133
readonly root!: string
134134

src/components/widgets/filesystem/FileSystemBulkActions.vue

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,8 @@
7272
<script lang="ts">
7373
import { Component, Mixins, Prop } from 'vue-property-decorator'
7474
import StatesMixin from '@/mixins/state'
75-
import FileSystemMenu from './FileSystemMenu.vue'
76-
import FileSystemFilterMenu from './FileSystemFilterMenu.vue'
7775
78-
@Component({
79-
components: {
80-
FileSystemMenu,
81-
FileSystemFilterMenu
82-
}
83-
})
76+
@Component({})
8477
export default class FileSystemBulkActions extends Mixins(StatesMixin) {
8578
@Prop({ type: String, required: true })
8679
readonly root!: string
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<template>
2+
<app-dialog
3+
v-model="open"
4+
:title="$t('app.file_system.title.go_to_file')"
5+
no-actions
6+
max-width="800"
7+
>
8+
<v-card-actions>
9+
<v-text-field
10+
v-model="search"
11+
:loading="loading"
12+
outlined
13+
hide-details
14+
dense
15+
autofocus
16+
class="mx-2"
17+
/>
18+
</v-card-actions>
19+
20+
<v-divider />
21+
22+
<v-virtual-scroll
23+
:items="matchedFiles"
24+
bench="30"
25+
item-height="40"
26+
>
27+
<template #default="{ item }">
28+
<v-list-item
29+
:key="item.path"
30+
dense
31+
class="v-list-item--link"
32+
@click="handleFileClick(item)"
33+
>
34+
<v-list-item-content>
35+
<v-list-item-title class="text-body-2 font-weight-regular">
36+
{{ item.path }}
37+
</v-list-item-title>
38+
</v-list-item-content>
39+
</v-list-item>
40+
41+
<v-divider />
42+
</template>
43+
</v-virtual-scroll>
44+
</app-dialog>
45+
</template>
46+
47+
<script lang="ts">
48+
import { Component, Mixins, Prop, VModel, Watch } from 'vue-property-decorator'
49+
import { SocketActions } from '@/api/socketActions'
50+
import { RootFile } from '@/store/files/types'
51+
import getFilePaths from '@/util/get-file-paths'
52+
import StateMixin from '@/mixins/state'
53+
54+
type File = RootFile &{
55+
filename: string
56+
filepath: string
57+
rootPath: string
58+
}
59+
60+
@Component({})
61+
export default class FileSystemGoToFileDialog extends Mixins(StateMixin) {
62+
@VModel({ type: Boolean, required: true })
63+
open!: boolean
64+
65+
@Prop({ type: String, required: true })
66+
readonly root!: string
67+
68+
search = ''
69+
loaded = false
70+
71+
get rootFiles (): RootFile[] {
72+
return this.$store.getters['files/getRootFiles'](this.root) as RootFile[]
73+
}
74+
75+
get matchedFiles (): File[] {
76+
if (!this.loaded) {
77+
return []
78+
}
79+
80+
const search = this.search
81+
.split('')
82+
.join('.*')
83+
const searchRegExp = new RegExp(search, 'i')
84+
85+
return this.rootFiles
86+
.filter(rootFile => searchRegExp.exec(rootFile.path))
87+
.map(rootFile => {
88+
const { filename, rootPath, path: filepath } = getFilePaths(rootFile.path, this.root)
89+
90+
const file: File = ({
91+
...rootFile,
92+
filename,
93+
filepath,
94+
rootPath
95+
})
96+
97+
return file
98+
})
99+
}
100+
101+
get loading (): boolean {
102+
return this.hasWait(`${this.$waits.onFileSystem}${this.root}`) as boolean
103+
}
104+
105+
@Watch('loading')
106+
onLoading (value: boolean) {
107+
this.loaded = !value
108+
}
109+
110+
handleFileClick (file: File) {
111+
this.$emit('path-change', file.rootPath)
112+
this.open = false
113+
}
114+
115+
mounted () {
116+
this.loaded = false
117+
SocketActions.serverFilesListRoot(this.root)
118+
}
119+
}
120+
</script>

src/components/widgets/filesystem/FileSystemToolbar.vue

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,33 @@
8080
:headers="headers"
8181
/>
8282

83+
<div>
84+
<v-tooltip bottom>
85+
<template #activator="{ on, attrs }">
86+
<v-btn
87+
v-bind="attrs"
88+
:disabled="disabled"
89+
fab
90+
small
91+
text
92+
@click="$emit('go-to-file')"
93+
v-on="on"
94+
>
95+
<v-icon>$magnify</v-icon>
96+
</v-btn>
97+
</template>
98+
<span>{{ $t('app.general.btn.go_to_file') }}</span>
99+
</v-tooltip>
100+
</div>
101+
83102
<file-system-filter-menu
84103
v-if="hasFilterTypes"
85104
:root="root"
86105
:disabled="disabled"
87106
@change="$emit('filter', $event)"
88107
/>
89108

90-
<file-system-menu
109+
<file-system-add-menu
91110
v-if="!readonly || canCreateDirectory"
92111
:root="root"
93112
:disabled="disabled"
@@ -96,22 +115,24 @@
96115
@upload="handleUpload"
97116
/>
98117

99-
<v-tooltip bottom>
100-
<template #activator="{ on, attrs }">
101-
<v-btn
102-
v-bind="attrs"
103-
:disabled="disabled"
104-
fab
105-
small
106-
text
107-
@click="$emit('refresh')"
108-
v-on="on"
109-
>
110-
<v-icon>$refresh</v-icon>
111-
</v-btn>
112-
</template>
113-
<span>{{ $t('app.general.btn.refresh') }}</span>
114-
</v-tooltip>
118+
<div>
119+
<v-tooltip bottom>
120+
<template #activator="{ on, attrs }">
121+
<v-btn
122+
v-bind="attrs"
123+
:disabled="disabled"
124+
fab
125+
small
126+
text
127+
@click="$emit('refresh')"
128+
v-on="on"
129+
>
130+
<v-icon>$refresh</v-icon>
131+
</v-btn>
132+
</template>
133+
<span>{{ $t('app.general.btn.refresh') }}</span>
134+
</v-tooltip>
135+
</div>
115136

116137
<div
117138
style="max-width: 160px;"
@@ -149,13 +170,13 @@
149170
<script lang="ts">
150171
import { Component, Prop, Mixins } from 'vue-property-decorator'
151172
import StatesMixin from '@/mixins/state'
152-
import FileSystemMenu from './FileSystemMenu.vue'
173+
import FileSystemAddMenu from './FileSystemAddMenu.vue'
153174
import FileSystemFilterMenu from './FileSystemFilterMenu.vue'
154175
import { AppTableHeader } from '@/types'
155176
156177
@Component({
157178
components: {
158-
FileSystemMenu,
179+
FileSystemAddMenu,
159180
FileSystemFilterMenu
160181
}
161182
})

src/locales/en.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ app:
9696
add_file: Add File
9797
command_palette: Command Palette
9898
download_file: Retrieving file
99+
go_to_file: Go to file
99100
rename_dir: Rename Directory
100101
rename_file: Rename File
101102
upload_file: Uploading file | Uploading files
@@ -155,6 +156,7 @@ app:
155156
extrude: Extrude
156157
filter: Filter
157158
forgot_password: Forgotten your password?
159+
go_to_file: Go to file
158160
heaters_off: Heaters off
159161
job_queue: Job Queue
160162
load_all: Load all

src/mixins/state.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,22 @@ export default class StateMixin extends Vue {
7575
* Indicates if we have a valid wait(s).
7676
* Supports a single string or a list of.
7777
*/
78-
hasWait (wait: string | string[]) {
79-
return this.$store.getters['wait/hasWait'](wait)
78+
hasWait (wait: string | string[]): boolean {
79+
return this.$store.getters['wait/hasWait'](wait) as boolean
8080
}
8181

8282
/**
8383
* Indicates if we have any waits.
8484
*/
85-
get hasWaits () {
86-
return this.$store.getters['wait/hasWaits']
85+
get hasWaits (): boolean {
86+
return this.$store.getters['wait/hasWaits'] as boolean
8787
}
8888

8989
/**
9090
* Indicates if we have any waits prefixed by.
9191
*/
92-
hasWaitsBy (prefix: string) {
93-
return this.$store.getters['wait/hasWaitsBy'](prefix)
92+
hasWaitsBy (prefix: string): boolean {
93+
return this.$store.getters['wait/hasWaitsBy'](prefix) as boolean
9494
}
9595

9696
/**

0 commit comments

Comments
 (0)