Skip to content

Commit 06337e4

Browse files
committed
Add support for non-existent files being edited
1 parent bfdc1f7 commit 06337e4

File tree

4 files changed

+84
-28
lines changed

4 files changed

+84
-28
lines changed

resources/assets/scripts/components/server/components/filemanager/modals/EditFileModal.vue

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,24 @@
66
<div class="modal-close-icon" v-on:click="closeModal">
77
<Icon name="x" aria-label="Close modal" role="button"/>
88
</div>
9-
<MessageBox class="alert error mb-2" title="Error" :message="error" v-if="error"/>
9+
<MessageBox class="alert error mb-4" title="Error" :message="error" v-if="error"/>
10+
<div class="flex items-center mb-4 bg-white rounded p-2">
11+
<div class="mx-2">
12+
<label class="input-label mb-0" for="file-name-input">File name:</label>
13+
</div>
14+
<div class="flex-1">
15+
<input
16+
type="text"
17+
name="file_name"
18+
class="input"
19+
id="file-name-input"
20+
:disabled="typeof file !== 'undefined'"
21+
v-model="fileName"
22+
v-validate="'required'"
23+
/>
24+
<p class="input-help error" v-show="errors.has('file_name')">{{ errors.first('file_name') }}</p>
25+
</div>
26+
</div>
1027
<div id="editor"></div>
1128
<div class="flex mt-4 bg-white rounded p-2">
1229
<div class="flex-1">
@@ -35,7 +52,7 @@
3552
import {ApplicationState, FileManagerState} from '@/store/types';
3653
import {mapState} from "vuex";
3754
import * as Ace from 'brace';
38-
import { join } from 'path';
55+
import {join} from 'path';
3956
import {DirectoryContentObject} from "@/api/server/types";
4057
import getFileContents from '@/api/server/files/getFileContents';
4158
import SpinnerModal from "@/components/core/SpinnerModal.vue";
@@ -46,18 +63,21 @@
4663
file?: DirectoryContentObject,
4764
serverUuid?: string,
4865
fm?: FileManagerState,
66+
fileName?: string,
4967
error: string | null,
5068
editor: Ace.Editor | null,
5169
isVisible: boolean,
5270
isLoading: boolean,
53-
supportedTypes: {type: string, name: string, default?: boolean}[],
71+
supportedTypes: { type: string, name: string, default?: boolean }[],
5472
}
5573
5674
const defaults = {
5775
error: null,
5876
editor: null,
5977
isVisible: false,
6078
isLoading: true,
79+
file: undefined,
80+
fileName: undefined,
6181
};
6282
6383
export default Vue.extend({
@@ -101,6 +121,8 @@
101121
this.file = file;
102122
this.isVisible = true;
103123
this.isLoading = true;
124+
this.fileName = file ? file.name : undefined;
125+
this.errors.clear();
104126
105127
this.$nextTick(() => {
106128
this.editor = Ace.edit('editor');
@@ -120,13 +142,36 @@
120142
});
121143
},
122144
145+
watch: {
146+
fileName: function (newValue?: string, oldValue?: string) {
147+
if (newValue === oldValue || !newValue) {
148+
return;
149+
}
150+
151+
this.updateFileLanguageFromName(newValue);
152+
},
153+
},
154+
123155
methods: {
124156
submit: function () {
157+
if (!this.file && (!this.fileName || this.fileName.length === 0)) {
158+
this.error = 'You must provide a file name before saving.';
159+
return;
160+
}
161+
125162
this.isLoading = true;
126163
const content = this.editor!.getValue();
127164
128-
writeFileContents(this.serverUuid!, join(this.fm!.currentDirectory, this.file!.name), content)
129-
.then(() => this.error = null)
165+
writeFileContents(this.serverUuid!, join(this.fm!.currentDirectory, this.fileName!), content)
166+
.then(() => {
167+
this.error = null;
168+
169+
// @todo come up with a more graceful solution here
170+
if (!this.file) {
171+
this.$emit('refresh');
172+
this.closeModal();
173+
}
174+
})
130175
.catch(error => {
131176
console.log(error);
132177
this.error = httpErrorToHuman(error);
@@ -136,7 +181,7 @@
136181
137182
loadFileContent: function (): Promise<void> {
138183
return new Promise((resolve, reject) => {
139-
const { editor, file } = this;
184+
const {editor, file} = this;
140185
141186
if (!file || !editor || file.directory) {
142187
return resolve();
@@ -147,29 +192,32 @@
147192
editor.$blockScrolling = Infinity;
148193
editor.setValue(contents, 1);
149194
})
150-
.then(() => {
151-
// Set the correct MIME type on the editor for the user.
152-
const modelist = Ace.acequire('ace/ext/modelist');
153-
if (modelist) {
154-
const mode = modelist.getModeForPath(file.name).mode || 'ace/mode/text';
155-
editor.getSession().setMode(mode);
156-
157-
const parts = mode.split('/');
158-
const element = (this.$refs.fileLanguageSelector as HTMLSelectElement | null);
159-
160-
if (element) {
161-
const index = this.supportedTypes.findIndex(value => value.type === parts[parts.length - 1]);
162-
if (index >= 0) {
163-
element.selectedIndex = index;
164-
}
165-
}
166-
}
167-
})
195+
.then(() => this.updateFileLanguageFromName(file.name))
168196
.then(() => resolve())
169197
.catch(reject);
170198
});
171199
},
172200
201+
updateFileLanguageFromName: function (name: string) {
202+
const modelist = Ace.acequire('ace/ext/modelist');
203+
if (!modelist || !this.editor) {
204+
return;
205+
}
206+
207+
const mode = modelist.getModeForPath(name).mode || 'ace/mode/text';
208+
209+
const parts = mode.split('/');
210+
const element = (this.$refs.fileLanguageSelector as HTMLSelectElement | null);
211+
212+
if (element) {
213+
const index = this.supportedTypes.findIndex(value => value.type === parts[parts.length - 1]);
214+
if (index >= 0) {
215+
element.selectedIndex = index;
216+
this.editor.getSession().setMode(mode);
217+
}
218+
}
219+
},
220+
173221
updateFileLanguage: function (e: MouseEvent) {
174222
if (!this.editor) {
175223
return;
@@ -185,7 +233,7 @@
185233
/* webpackMode: "lazy-once" */
186234
/* webpackInclude: /(dockerfile|golang|html|java|javascript|json|kotlin|lua|markdown|text|php|properties|python|ruby|sh|sql|xml|yaml).js$/ */
187235
`brace/mode/${o.type}`
188-
))
236+
))
189237
);
190238
},
191239

resources/assets/scripts/components/server/subpages/FileManager.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
</div>
5353
</div>
5454
<CreateFolderModal v-on:created="directoryCreated"/>
55-
<EditFileModal/>
55+
<EditFileModal v-on:refresh="listDirectory"/>
5656
</div>
5757
</template>
5858

0 commit comments

Comments
 (0)