|
2 | 2 | <transition name="modal"> |
3 | 3 | <div class="modal-mask" v-show="isVisible"> |
4 | 4 | <div class="modal-container full-screen" @click.stop> |
5 | | - <div class="modal-close-icon" v-on:click="isVisible = false"> |
| 5 | + <SpinnerModal :visible="isVisible && isLoading"/> |
| 6 | + <div class="modal-close-icon" v-on:click="closeModal"> |
6 | 7 | <Icon name="x" aria-label="Close modal" role="button"/> |
7 | 8 | </div> |
8 | | - <MessageBox class="alert error mb-8" title="Error" :message="error" v-if="error"/> |
| 9 | + <MessageBox class="alert error mb-2" title="Error" :message="error" v-if="error"/> |
9 | 10 | <div id="editor"></div> |
10 | 11 | <div class="flex mt-4 bg-white rounded p-2"> |
11 | 12 | <div class="flex-1"> |
12 | | - <select v-on:change="updateFileLanguage"> |
13 | | - <option v-for="item in supportedTypes" :value="item.type">{{ item.name }}</option> |
| 13 | + <select v-on:change="updateFileLanguage" ref="fileLanguageSelector"> |
| 14 | + <option v-for="item in supportedTypes" :value="item.type"> |
| 15 | + {{ item.name }} |
| 16 | + </option> |
14 | 17 | </select> |
15 | 18 | </div> |
16 | | - <button class="btn btn-secondary btn-sm" v-on:click="isVisible = false"> |
| 19 | + <button class="btn btn-secondary btn-sm" v-on:click="closeModal"> |
17 | 20 | Cancel |
18 | 21 | </button> |
19 | 22 | <button class="ml-2 btn btn-primary btn-sm"> |
|
35 | 38 | import { join } from 'path'; |
36 | 39 | import {DirectoryContentObject} from "@/api/server/types"; |
37 | 40 | import getFileContents from '@/api/server/files/getFileContents'; |
| 41 | + import SpinnerModal from "@/components/core/SpinnerModal.vue"; |
38 | 42 |
|
39 | 43 | interface Data { |
40 | 44 | file?: DirectoryContentObject, |
|
44 | 48 | editor: Ace.Editor | null, |
45 | 49 | isVisible: boolean, |
46 | 50 | isLoading: boolean, |
47 | | - supportedTypes: {type: string, name: string}[], |
| 51 | + supportedTypes: {type: string, name: string, default?: boolean}[], |
48 | 52 | } |
49 | 53 |
|
| 54 | + const defaults = { |
| 55 | + error: null, |
| 56 | + editor: null, |
| 57 | + isVisible: false, |
| 58 | + isLoading: true, |
| 59 | + }; |
| 60 | +
|
50 | 61 | export default Vue.extend({ |
51 | 62 | name: 'NewFileModal', |
52 | 63 |
|
53 | | - components: {Icon, MessageBox}, |
| 64 | + components: {Icon, SpinnerModal, MessageBox}, |
54 | 65 |
|
55 | 66 | data: function (): Data { |
56 | 67 | return { |
57 | | - error: null, |
58 | | - editor: null, |
59 | | - isVisible: false, |
60 | | - isLoading: false, |
| 68 | + ...defaults, |
61 | 69 | supportedTypes: [ |
| 70 | + {type: 'text', name: 'Text'}, |
62 | 71 | {type: 'dockerfile', name: 'Docker'}, |
63 | 72 | {type: 'golang', name: 'Go'}, |
64 | 73 | {type: 'html', name: 'HTML'}, |
|
68 | 77 | {type: 'kotlin', name: 'Kotlin'}, |
69 | 78 | {type: 'lua', name: 'Lua'}, |
70 | 79 | {type: 'markdown', name: 'Markdown'}, |
71 | | - {type: 'plain_text', name: 'Text'}, |
72 | 80 | {type: 'php', name: 'PHP'}, |
73 | 81 | {type: 'properties', name: 'Properties'}, |
74 | 82 | {type: 'python', name: 'Python'}, |
|
90 | 98 | window.events.$on('server:files:open-edit-file-modal', (file?: DirectoryContentObject) => { |
91 | 99 | this.file = file; |
92 | 100 | this.isVisible = true; |
| 101 | + this.isLoading = true; |
93 | 102 |
|
94 | 103 | this.$nextTick(() => { |
95 | 104 | this.editor = Ace.edit('editor'); |
96 | 105 | this.loadDependencies() |
97 | 106 | .then(() => this.loadLanguages()) |
98 | 107 | .then(() => this.configureEditor()) |
99 | 108 | .then(() => this.loadFileContent()) |
| 109 | + .then(() => { |
| 110 | + this.isLoading = false; |
| 111 | + }) |
| 112 | + .catch(error => { |
| 113 | + console.error(error); |
| 114 | + this.isLoading = false; |
| 115 | + this.error = error.message; |
| 116 | + }); |
100 | 117 | }); |
101 | 118 | }); |
102 | 119 | }, |
|
106 | 123 |
|
107 | 124 | }, |
108 | 125 |
|
109 | | - loadFileContent: function () { |
110 | | - if (!this.file || !this.editor || this.file.directory) { |
111 | | - return; |
112 | | - } |
113 | | -
|
114 | | - getFileContents(this.serverUuid!, join(this.fm!.currentDirectory, this.file.name)) |
115 | | - .then(contents => { |
116 | | - this.editor!.$blockScrolling = Infinity; |
117 | | - this.editor!.setValue(contents, 1); |
118 | | - }); |
| 126 | + loadFileContent: function (): Promise<void> { |
| 127 | + return new Promise((resolve, reject) => { |
| 128 | + const { editor, file } = this; |
| 129 | +
|
| 130 | + if (!file || !editor || file.directory) { |
| 131 | + return resolve(); |
| 132 | + } |
| 133 | +
|
| 134 | + getFileContents(this.serverUuid!, join(this.fm!.currentDirectory, file.name)) |
| 135 | + .then(contents => { |
| 136 | + editor.$blockScrolling = Infinity; |
| 137 | + editor.setValue(contents, 1); |
| 138 | + }) |
| 139 | + .then(() => { |
| 140 | + // Set the correct MIME type on the editor for the user. |
| 141 | + const modelist = Ace.acequire('ace/ext/modelist'); |
| 142 | + if (modelist) { |
| 143 | + const mode = modelist.getModeForPath(file.name).mode || 'ace/mode/text'; |
| 144 | + editor.getSession().setMode(mode); |
| 145 | +
|
| 146 | + const parts = mode.split('/'); |
| 147 | + const element = (this.$refs.fileLanguageSelector as HTMLSelectElement | null); |
| 148 | +
|
| 149 | + if (element) { |
| 150 | + const index = this.supportedTypes.findIndex(value => value.type === parts[parts.length - 1]); |
| 151 | + if (index >= 0) { |
| 152 | + element.selectedIndex = index; |
| 153 | + } |
| 154 | + } |
| 155 | + } |
| 156 | + }) |
| 157 | + .then(() => resolve()) |
| 158 | + .catch(reject); |
| 159 | + }); |
119 | 160 | }, |
120 | 161 |
|
121 | 162 | updateFileLanguage: function (e: MouseEvent) { |
|
131 | 172 | this.supportedTypes.map(o => import( |
132 | 173 | /* webpackChunkName: "ace_editor" */ |
133 | 174 | /* webpackMode: "lazy-once" */ |
134 | | - /* webpackInclude: /(dockerfile|golang|html|java|javascript|json|kotlin|lua|markdown|plain_text|php|properties|python|ruby|sh|sql|xml|yaml).js$/ */ |
| 175 | + /* webpackInclude: /(dockerfile|golang|html|java|javascript|json|kotlin|lua|markdown|text|php|properties|python|ruby|sh|sql|xml|yaml).js$/ */ |
135 | 176 | `brace/mode/${o.type}` |
136 | 177 | )) |
137 | 178 | ); |
|
153 | 194 | return; |
154 | 195 | } |
155 | 196 |
|
156 | | - // const modelist = Ace.acequire('brace/ext/whitespace'); |
157 | 197 | const whitespace = Ace.acequire('ace/ext/whitespace'); |
158 | 198 |
|
159 | 199 | this.editor.setTheme('ace/theme/chrome'); |
|
167 | 207 | this.editor!.commands.addCommand(c); |
168 | 208 | }); |
169 | 209 | whitespace.detectIndentation(this.editor.session); |
170 | | - } |
| 210 | + }, |
| 211 | +
|
| 212 | + closeModal: function () { |
| 213 | + if (this.editor) { |
| 214 | + this.editor.setValue('', -1); |
| 215 | + } |
| 216 | +
|
| 217 | + Object.assign(this.$data, defaults); |
| 218 | + }, |
171 | 219 | } |
172 | 220 | }) |
173 | 221 | </script> |
|
0 commit comments