Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3c2f6ab

Browse files
authored
Merge pull request #18 from kpinnipa/firsttry
Save highlighted code snippet without refreshing
2 parents 555f5f6 + 14af799 commit 3c2f6ab

File tree

3 files changed

+230
-233
lines changed

3 files changed

+230
-233
lines changed

‎src/CodeSnippetForm.ts

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
2+
import { Widget } from '@lumino/widgets';
3+
import { RequestHandler } from '@elyra/application';
4+
5+
import checkSVGstr from '../style/check.svg';
6+
import { showMessage } from './ConfirmMessage';
7+
8+
import { Dialog, showDialog} from '@jupyterlab/apputils';
9+
10+
import { Contents } from '@jupyterlab/services';
11+
12+
import { JSONObject } from '@lumino/coreutils';
13+
14+
import {ICodeSnippet} from './CodeSnippetService'
15+
16+
import { IDocumentManager } from '@jupyterlab/docmanager';
17+
import { CodeSnippetWidget } from './CodeSnippetWidget';
18+
19+
/**
20+
* The class name added to file dialogs.
21+
*/
22+
const FILE_DIALOG_CLASS = 'jp-FileDialog';
23+
24+
/**
25+
* The class name added for the new name label in the rename dialog
26+
*/
27+
const INPUT_NEWNAME_TITLE_CLASS = 'jp-new-name-title';
28+
29+
/**
30+
* A stripped-down interface for a file container.
31+
*/
32+
export interface IFileContainer extends JSONObject {
33+
/**
34+
* The list of item names in the current working directory.
35+
*/
36+
items: string[];
37+
/**
38+
* The current working directory of the file container.
39+
*/
40+
path: string;
41+
}
42+
43+
/**
44+
* Save an input with a dialog. This is what actually displays everything.
45+
* Result.value is the value retrieved from .getValue(). ---> .getValue() returns an array of inputs.
46+
*/
47+
export function inputDialog(
48+
codeSnippet: CodeSnippetWidget,
49+
url: string,
50+
inputCode: string
51+
): Promise<Contents.IModel | null> {
52+
return showDialog({
53+
title: 'Save Code Snippet',
54+
body: new InputHandler(),
55+
focusNodeSelector: 'input',
56+
buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'Save' })]
57+
}).then(result => {
58+
console.log(result.value);
59+
if (!result.value) {
60+
return null;
61+
}
62+
else {
63+
/* TODO: if name is already there call shouldOverwrite and change to a put request*/
64+
// Workaround: make a get request with result.value[0] to check... but could be slow
65+
RequestHandler.makePostRequest( //If i use their handler then I can't interrupt any error messages without editing their stuff.
66+
url,
67+
JSON.stringify({
68+
display_name: result.value[0],
69+
metadata: {
70+
code: [
71+
inputCode
72+
],
73+
description: result.value[1],
74+
language: result.value[2],
75+
},
76+
name: result.value[0].replace(' ','').toLowerCase(),
77+
schema_name: "code-snippet",
78+
}),
79+
false
80+
);
81+
codeSnippet.fetchData().then((codeSnippets: ICodeSnippet[]) => {
82+
console.log("HELLLO");
83+
codeSnippet.renderCodeSnippetsSignal.emit(codeSnippets)});
84+
showMessage({
85+
body: /*"Saved as Snippet"*/new MessageHandler()
86+
});
87+
}
88+
// if (!isValidFileName(result.value)) {
89+
// void showErrorMessage(
90+
// 'Rename Error',
91+
// Error(
92+
// `"${result.value}" is not a valid name for a file. ` +
93+
// `Names must have nonzero length, ` +
94+
// `and cannot include "/", "\\", or ":"`
95+
// )
96+
// );
97+
// return null;
98+
// }
99+
//const basePath = PathExt.dirname(oldPath);
100+
//const newPath = PathExt.join(basePath, result.value);
101+
});
102+
}
103+
104+
/**
105+
* Rename a file, asking for confirmation if it is overwriting another.
106+
*/
107+
export function renameFile(
108+
manager: IDocumentManager,
109+
oldPath: string,
110+
newPath: string
111+
): Promise<Contents.IModel | null> {
112+
return manager.rename(oldPath, newPath).catch(error => {
113+
if (error.message.indexOf('409') === -1) {
114+
throw error;
115+
}
116+
return shouldOverwrite(newPath).then(value => {
117+
if (value) {
118+
return manager.overwrite(oldPath, newPath);
119+
}
120+
return Promise.reject('File not renamed');
121+
});
122+
});
123+
}
124+
125+
/**
126+
* Ask the user whether to overwrite a file.
127+
*/
128+
export function shouldOverwrite(path: string): Promise<boolean> {
129+
const options = {
130+
title: 'Overwrite file?',
131+
body: `"${path}" already exists, overwrite?`,
132+
buttons: [Dialog.cancelButton(), Dialog.warnButton({ label: 'Overwrite' })]
133+
};
134+
return showDialog(options).then(result => {
135+
return Promise.resolve(result.button.accept);
136+
});
137+
}
138+
139+
/**
140+
* Test whether a name is a valid file name
141+
*
142+
* Disallows "/", "\", and ":" in file names, as well as names with zero length.
143+
*/
144+
export function isValidFileName(name: string): boolean {
145+
const validNameExp = /[\/\\:]/;
146+
return name.length > 0 && !validNameExp.test(name);
147+
}
148+
149+
/**
150+
* A widget used to get input data.
151+
*/
152+
class InputHandler extends Widget {
153+
/**
154+
* Construct a new "rename" dialog.
155+
* readonly inputNode: HTMLInputElement; <--- in Widget class
156+
*/
157+
constructor() {
158+
super({ node: Private.createInputNode() });
159+
this.addClass(FILE_DIALOG_CLASS);
160+
}
161+
162+
getValue(): string[] {
163+
let inputs = [];
164+
inputs.push((this.node.getElementsByTagName('input')[0] as HTMLInputElement).value,
165+
(this.node.getElementsByTagName('input')[1] as HTMLInputElement).value,
166+
(this.node.getElementsByTagName('input')[2] as HTMLInputElement).value);
167+
return inputs;
168+
}
169+
}
170+
171+
172+
class MessageHandler extends Widget {
173+
constructor() {
174+
super({ node: Private.createConfirmMessageNode() });
175+
}
176+
}
177+
178+
/**
179+
* A namespace for private data.
180+
*/
181+
namespace Private {
182+
/**
183+
* Create the node for a rename handler. This is what's creating all of the elements to be displayed.
184+
*/
185+
export function createInputNode(): HTMLElement {
186+
const body = document.createElement('div');
187+
188+
const nameTitle = document.createElement('label');
189+
nameTitle.textContent = 'Snippet Name*';
190+
nameTitle.className = INPUT_NEWNAME_TITLE_CLASS;
191+
const name = document.createElement('input');
192+
193+
const descriptionTitle = document.createElement('label');
194+
descriptionTitle.textContent = 'Description*';
195+
descriptionTitle.className = INPUT_NEWNAME_TITLE_CLASS;
196+
const description = document.createElement('input');
197+
198+
const languageTitle = document.createElement('label');
199+
languageTitle.textContent = 'Language*';
200+
languageTitle.className = INPUT_NEWNAME_TITLE_CLASS;
201+
const language = document.createElement('input');
202+
203+
body.appendChild(nameTitle);
204+
body.appendChild(name);
205+
body.appendChild(descriptionTitle);
206+
body.appendChild(description);
207+
body.appendChild(languageTitle);
208+
body.appendChild(language);
209+
return body;
210+
}
211+
212+
export function createConfirmMessageNode(): HTMLElement {
213+
const body = document.createElement('div');
214+
body.innerHTML = checkSVGstr;
215+
216+
const messageContainer = document.createElement('div');
217+
messageContainer.className = 'jp-confirm-text';
218+
const message = document.createElement('text');
219+
message.textContent = 'Saved as Snippet!';
220+
messageContainer.appendChild(message)
221+
body.append(messageContainer);
222+
return body;
223+
}
224+
}

‎src/CodeSnippetWidget.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import '../style/index.css';
1818

19-
import { inputDialog } from './index';
19+
import { inputDialog } from './CodeSnippetForm';
2020
import { URLExt } from '@jupyterlab/coreutils';
2121
import { ServerConnection } from '@jupyterlab/services';
2222
import { ExpandableComponent } from '@elyra/ui-components';
@@ -292,6 +292,7 @@ export class CodeSnippetWidget extends ReactWidget {
292292
this.codeSnippetManager = new CodeSnippetService();
293293
this.renderCodeSnippetsSignal = new Signal<this, ICodeSnippet[]>(this);
294294
}
295+
295296
// Request code snippets from server
296297
async fetchData(): Promise<ICodeSnippet[]> {
297298
return await this.codeSnippetManager.findAll();
@@ -447,7 +448,7 @@ export class CodeSnippetWidget extends ReactWidget {
447448
const url = 'elyra/metadata/code-snippets';
448449
const code = Private.findData(event.mimeData);
449450

450-
await inputDialog(url, code);
451+
await inputDialog(this,url, code);
451452
console.log(code);
452453
// await RequestHandler.makePostRequest(
453454
// url,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /