Skip to content

Commit f62a84f

Browse files
committed
Add overwrite confirmation modal
1 parent d52fc9c commit f62a84f

File tree

2 files changed

+96
-23
lines changed

2 files changed

+96
-23
lines changed

assets/css/ide.css

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ body { justify-content: stretch; }
8989
/****************************************************************************\
9090
* Notices
9191
\****************************************************************************/
92-
.main-pane { display: flex; flex-direction: column; justify-content: stretch; overflow-y: hidden; }
92+
.main-pane { display: flex; flex-direction: column; justify-content: stretch; overflow-y: hidden; position: relative; }
9393
.main-pane .notices { display: flex; flex: 0 0 auto; flex-direction: column; border-right: 1px solid #ddd; border-bottom: 1px solid #ddd; }
9494

9595
.main-pane .notices > .notice { padding: 5px 60px; background: #f5f5f5; flex: 0 0 auto; }
@@ -103,6 +103,21 @@ body { justify-content: stretch; }
103103
.main-pane .notices > .notice.error { background: rgb(255, 216, 222); }
104104
.main-pane .notices > .notice.warning { background: rgb(255, 247, 217); }
105105

106+
/****************************************************************************\
107+
* Modals
108+
\****************************************************************************/
109+
.main-pane > .modal-overlay {display: flex;justify-content: center;align-items: center;position: absolute;top: 0;left: 0;bottom: 0;right: 0;z-index: 5;background: rgba(0, 0, 0, 0.1);}
110+
.main-pane > .modal-overlay .modal-window { display: flex; flex-direction: column; width: 320; padding: 20; background: #FFF; border-radius: 4px; z-index: 10; box-shadow: 0 4px 5px rgba(0, 0, 0, 0.25); }
111+
.main-pane > .modal-overlay .modal-window h3 { align-self: center; margin-top: 0; }
112+
.main-pane > .modal-overlay .modal-window .controls { flex: 0 0 auto; }
113+
.main-pane > .modal-overlay .modal-window .btn { flex: 1; text-align: center; padding: 5 10; border: 1px solid #DDD; border-radius: 4px; -webkit-user-select: none; -moz-webkit-user-select: none; }
114+
.main-pane > .modal-overlay .modal-window .btn + .btn { margin-left: 10; }
115+
.main-pane > .modal-overlay .modal-window .btn:hover { background: #EEE; }
116+
.main-pane > .modal-overlay .modal-window .btn:active {background: #DDD; }
117+
.main-pane > .modal-overlay .modal-window .btn.danger { background: #EE5555; color: white; border: #CC3333; }
118+
.main-pane > .modal-overlay .modal-window .btn.danger:hover { background: #DD4444; }
119+
.main-pane > .modal-overlay .modal-window .btn.danger:active { background: #CC3333; }
120+
106121
/****************************************************************************\
107122
* Editor
108123
\****************************************************************************/

src/ide.ts

Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,10 @@ export class IDE {
20282028
loaded = false;
20292029
/** Whether the IDE is currently loading a new document. */
20302030
loading = false;
2031+
2032+
/** When attempting to overwrite an existing document with a new one, the ID of the document to overwrite. */
2033+
overwriteId:string;
2034+
20312035
/** The current editor generation. Used for imposing a relative ordering on parses. */
20322036
generation = 0;
20332037
/** Whether the currently open document is a modified version of an example. */
@@ -2064,6 +2068,7 @@ export class IDE {
20642068
{c: "main-pane", children: [
20652069
this.noticesElem(),
20662070
this.editor.render(),
2071+
this.overwriteId ? this.overwritePrompt() : undefined,
20672072
]},
20682073
this.comments.render()
20692074
]};
@@ -2087,6 +2092,37 @@ export class IDE {
20872092
}
20882093
}
20892094

2095+
overwritePrompt():Elem {
2096+
return {c: "modal-overlay", children: [
2097+
{c: "modal-window", children: [
2098+
{t: "h3", text: "Overwrite existing copy?"},
2099+
{c: "flex-row controls", children: [
2100+
{c: "btn load-btn", text: "load existing", click: this.loadExisting},
2101+
{c: "btn danger overwrite-btn", text: "overwrite", click: this.overwriteDocument},
2102+
]}
2103+
]}
2104+
]};
2105+
}
2106+
2107+
loadExisting = () => {
2108+
let id = this.overwriteId;
2109+
this.overwriteId = undefined;
2110+
this.loadFile(id);
2111+
this.render();
2112+
}
2113+
2114+
overwriteDocument = () => {
2115+
let id = this.overwriteId;
2116+
this.overwriteId = undefined;
2117+
this.cloneDocument(id);
2118+
this.render();
2119+
}
2120+
2121+
promptOverwrite(neueId:string) {
2122+
this.overwriteId = neueId;
2123+
this.render();
2124+
}
2125+
20902126
render() {
20912127
// Update child states as necessary
20922128
this.renderer.render([this.elem()]);
@@ -2143,13 +2179,16 @@ export class IDE {
21432179
return false;
21442180
}
21452181

2146-
// Otherwise we load the file from either localstorage or from the supplied
2147-
// examples object
2148-
let saves = JSON.parse(localStorage.getItem("eve-saves") || "{}");
2149-
let code = saves[docId];
2150-
if(code) {
2151-
this.modified = true;
2152-
} else {
2182+
// Otherwise find the content locally.
2183+
let code;
2184+
if(this.local) {
2185+
let saves = JSON.parse(localStorage.getItem("eve-saves") || "{}");
2186+
code = saves[docId];
2187+
if(code) {
2188+
this.modified = true;
2189+
}
2190+
}
2191+
if(!code) {
21532192
code = this._fileCache[docId];
21542193
this.modified = false;
21552194
}
@@ -2205,9 +2244,6 @@ export class IDE {
22052244
saveDocument() {
22062245
if(!this.documentId || !this.loaded) return;
22072246

2208-
let md = this.editor.toMarkdown();
2209-
let isDirty = md !== this._fileCache[this.documentId];
2210-
22112247
// When we try to edit a gist-backed file we need to fork it and save the new file to disk.
22122248
// @FIXME: This is all terribly hacky, and needs to be cleaned up as part of the FileStore rework.
22132249
if(this.documentId.indexOf("gist:") === 0) {
@@ -2216,22 +2252,17 @@ export class IDE {
22162252
let neueId = oldId.slice(5);
22172253
neueId = neueId.slice(0, 7) + neueId.slice(32);
22182254
neueId = `/root/${neueId}`;
2219-
this.documentId = neueId;
2220-
2221-
let navNode = this.navigator.nodes[oldId];
2222-
if(navNode) navNode.id = neueId;
2223-
this.navigator.nodes[oldId] = undefined;
2224-
this.navigator.nodes[neueId] = navNode;
2225-
if(this.navigator.currentId === oldId) this.navigator.currentId = neueId;
22262255

2227-
let currentHashChunks = location.hash.split("#").slice(1);
2228-
let modified = neueId;
2229-
if(currentHashChunks[1]) {
2230-
modified += `/#` + currentHashChunks[1];
2256+
if(this._fileCache[neueId]) {
2257+
return this.promptOverwrite(neueId);
2258+
} else {
2259+
return this.cloneDocument(neueId);
22312260
}
2232-
location.hash = modified;
22332261
}
22342262

2263+
let md = this.editor.toMarkdown();
2264+
let isDirty = md !== this._fileCache[this.documentId];
2265+
22352266
// @NOTE: We sync this here to prevent a terrible reload bug that occurs when saving to the file system.
22362267
// This isn't really the right fix, but it's a quick one that helps prevent lost work in trivial cases
22372268
// like navigating the workspace.
@@ -2268,6 +2299,33 @@ export class IDE {
22682299
this.loadFile(docId);
22692300
}
22702301

2302+
cloneDocument(neueId:string) {
2303+
let oldId = this.documentId;
2304+
this.documentId = neueId;
2305+
2306+
let navNode = this.navigator.nodes[oldId];
2307+
if(navNode) {
2308+
let neueNode:TreeNode = {} as any;
2309+
for(let attr in navNode) {
2310+
neueNode[attr] = navNode[attr];
2311+
}
2312+
neueNode.id = neueId;
2313+
neueNode.children = [];
2314+
this.navigator.nodes[neueId] = neueNode;
2315+
}
2316+
2317+
if(this.navigator.currentId === oldId) this.navigator.currentId = neueId;
2318+
2319+
let currentHashChunks = location.hash.split("#").slice(1);
2320+
let modified = neueId;
2321+
if(currentHashChunks[1]) {
2322+
modified += `/#` + currentHashChunks[1];
2323+
}
2324+
location.hash = modified;
2325+
2326+
this.saveDocument();
2327+
}
2328+
22712329
saveToGist() {
22722330
// @FIXME: We really need a display name setup for documents.
22732331
let savingNotice = this.injectNotice("info", "Saving...");

0 commit comments

Comments
 (0)