UNPKG

4.9 kBJavaScriptView Raw
1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3import { Dialog, showDialog, showErrorMessage } from '@jupyterlab/apputils';
4import { PathExt } from '@jupyterlab/coreutils';
5import { nullTranslator } from '@jupyterlab/translation';
6import { Widget } from '@lumino/widgets';
7/**
8 * The class name added to file dialogs.
9 */
10const FILE_DIALOG_CLASS = 'jp-FileDialog';
11/**
12 * The class name added for the new name label in the rename dialog
13 */
14const RENAME_NEW_NAME_TITLE_CLASS = 'jp-new-name-title';
15/**
16 * Rename a file with a dialog.
17 */
18export function renameDialog(manager, oldPath, translator) {
19 translator = translator || nullTranslator;
20 const trans = translator.load('jupyterlab');
21 return showDialog({
22 title: trans.__('Rename File'),
23 body: new RenameHandler(oldPath),
24 focusNodeSelector: 'input',
25 buttons: [
26 Dialog.cancelButton({ label: trans.__('Cancel') }),
27 Dialog.okButton({ label: trans.__('Rename') })
28 ]
29 }).then(result => {
30 if (!result.value) {
31 return null;
32 }
33 if (!isValidFileName(result.value)) {
34 void showErrorMessage(trans.__('Rename Error'), Error(trans.__('"%1" is not a valid name for a file. Names must have nonzero length, and cannot include "/", "\\", or ":"', result.value)));
35 return null;
36 }
37 const basePath = PathExt.dirname(oldPath);
38 const newPath = PathExt.join(basePath, result.value);
39 return renameFile(manager, oldPath, newPath);
40 });
41}
42/**
43 * Rename a file, asking for confirmation if it is overwriting another.
44 */
45export function renameFile(manager, oldPath, newPath) {
46 return manager.rename(oldPath, newPath).catch(error => {
47 if (error.response.status !== 409) {
48 // if it's not caused by an already existing file, rethrow
49 throw error;
50 }
51 // otherwise, ask for confirmation
52 return shouldOverwrite(newPath).then((value) => {
53 if (value) {
54 return manager.overwrite(oldPath, newPath);
55 }
56 return Promise.reject('File not renamed');
57 });
58 });
59}
60/**
61 * Ask the user whether to overwrite a file.
62 */
63export function shouldOverwrite(path, translator) {
64 translator = translator || nullTranslator;
65 const trans = translator.load('jupyterlab');
66 const options = {
67 title: trans.__('Overwrite file?'),
68 body: trans.__('"%1" already exists, overwrite?', path),
69 buttons: [
70 Dialog.cancelButton({ label: trans.__('Cancel') }),
71 Dialog.warnButton({ label: trans.__('Overwrite') })
72 ]
73 };
74 return showDialog(options).then(result => {
75 return Promise.resolve(result.button.accept);
76 });
77}
78/**
79 * Test whether a name is a valid file name
80 *
81 * Disallows "/", "\", and ":" in file names, as well as names with zero length.
82 */
83export function isValidFileName(name) {
84 const validNameExp = /[\/\\:]/;
85 return name.length > 0 && !validNameExp.test(name);
86}
87/**
88 * A widget used to rename a file.
89 */
90class RenameHandler extends Widget {
91 /**
92 * Construct a new "rename" dialog.
93 */
94 constructor(oldPath) {
95 super({ node: Private.createRenameNode(oldPath) });
96 this.addClass(FILE_DIALOG_CLASS);
97 const ext = PathExt.extname(oldPath);
98 const value = (this.inputNode.value = PathExt.basename(oldPath));
99 this.inputNode.setSelectionRange(0, value.length - ext.length);
100 }
101 /**
102 * Get the input text node.
103 */
104 get inputNode() {
105 return this.node.getElementsByTagName('input')[0];
106 }
107 /**
108 * Get the value of the widget.
109 */
110 getValue() {
111 return this.inputNode.value;
112 }
113}
114/**
115 * A namespace for private data.
116 */
117var Private;
118(function (Private) {
119 /**
120 * Create the node for a rename handler.
121 */
122 function createRenameNode(oldPath, translator) {
123 translator = translator || nullTranslator;
124 const trans = translator.load('jupyterlab');
125 const body = document.createElement('div');
126 const existingLabel = document.createElement('label');
127 existingLabel.textContent = trans.__('File Path');
128 const existingPath = document.createElement('span');
129 existingPath.textContent = oldPath;
130 const nameTitle = document.createElement('label');
131 nameTitle.textContent = trans.__('New Name');
132 nameTitle.className = RENAME_NEW_NAME_TITLE_CLASS;
133 const name = document.createElement('input');
134 body.appendChild(existingLabel);
135 body.appendChild(existingPath);
136 body.appendChild(nameTitle);
137 body.appendChild(name);
138 return body;
139 }
140 Private.createRenameNode = createRenameNode;
141})(Private || (Private = {}));
142//# sourceMappingURL=dialogs.js.map
\No newline at end of file