code-editor

added slider and some ui fixes

5/30/2023 5:10:35 PM

Details

diff --git a/codeeditor-app/app.html b/codeeditor-app/app.html
index 2a4fe52..8487de4 100644
--- a/codeeditor-app/app.html
+++ b/codeeditor-app/app.html
@@ -29,6 +29,6 @@
             <output-frame></output-frame>
         </div>
     </div>
-    <div class="flex-shrink section bottom">methods: rect, box, center, width, height, rand</div>
+    <div class="flex-shrink section bottom">methods: rect, box, center, width, height, rand, randomColor</div>
 </div>
 <notification-bubbles></notification-bubbles>
\ No newline at end of file
diff --git a/codeeditor-app/elements/code-editor/code-editor.ts b/codeeditor-app/elements/code-editor/code-editor.ts
index b7390c6..82ae5de 100644
--- a/codeeditor-app/elements/code-editor/code-editor.ts
+++ b/codeeditor-app/elements/code-editor/code-editor.ts
@@ -11,12 +11,15 @@ export class CodeEditor extends BaseElement {
     public input: string = "";
     public language: string = "";
     public editor!: monaco.editor.IStandaloneCodeEditor;
+    public lastInputCache: any;
 
     onInit(): void {
 
         this.initWorkers();
-        this.input = this.setInitInput();
         this.language = this.tagName.substring(0, this.tagName.indexOf("-")).toLocaleLowerCase();
+        this.lastInputCache = localStorage.getItem(this.language + "LastInputCache");
+        this.input = this.setInitInput();
+        
         this.setInitSettings();
 
         const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
@@ -38,6 +41,8 @@ export class CodeEditor extends BaseElement {
         this.editor.onDidChangeModelContent((e) => {
             if (!isSessionPage()) {
                 this.input = this.editor.getValue();
+                this.lastInputCache = this.input;
+                localStorage.setItem(this.language + "LastInputCache", this.input);
                 debounce.ensureDebounce(() => {
                     sessionApi.setSessionData(this.language, this.input);
                     this.outputFrame.setContent(this.language, this.input);
@@ -54,13 +59,21 @@ export class CodeEditor extends BaseElement {
     setInput(input: any) {
         if (this.input !== input) {
             this.input = input;
+            this.lastInputCache = this.input;
+            localStorage.setItem(this.language + "LastInputCache", this.input);
             this.editor.setValue(input);
             this.outputFrame.setContent(this.language, this.input);
         }
     }
 
     setInitInput(): string {
-        return "";
+        if (!isSessionPage() && sessionApi.hasSession()) {
+            return this.lastInputCache;
+        }
+        else {
+            return "";
+        }
+
     }
 
     setInitSettings(): void {
diff --git a/codeeditor-app/elements/code-editor/css-code-editor.ts b/codeeditor-app/elements/code-editor/css-code-editor.ts
index d5eb818..b484361 100644
--- a/codeeditor-app/elements/code-editor/css-code-editor.ts
+++ b/codeeditor-app/elements/code-editor/css-code-editor.ts
@@ -6,7 +6,13 @@ import flexCss from '!!raw-loader!../../../shared/flex.less';
 
 export class CssCodeEditor extends CodeEditor {
     setInitInput(): string {
-        return initCss;
+        var base = super.setInitInput();
+        if (!base) {
+            return initCss;
+        }
+        else {
+            return base;
+        }
     }
 
     setInitSettings(): void {
diff --git a/codeeditor-app/elements/code-editor/html-code-editor.ts b/codeeditor-app/elements/code-editor/html-code-editor.ts
index e083ee3..e325325 100644
--- a/codeeditor-app/elements/code-editor/html-code-editor.ts
+++ b/codeeditor-app/elements/code-editor/html-code-editor.ts
@@ -4,7 +4,13 @@ import initHtml from '!!raw-loader!./injects/editor-init.html';
 
 export class HtmlCodeEditor extends CodeEditor {
     setInitInput(): string {
-        return initHtml;
+        var base = super.setInitInput();
+        if (!base) {
+            return initHtml;
+        }
+        else {
+            return base;
+        }
     }
 
     setInitSettings(): void {
diff --git a/codeeditor-app/elements/code-editor/javascript-code-editor.ts b/codeeditor-app/elements/code-editor/javascript-code-editor.ts
index eef02c2..ec8150c 100644
--- a/codeeditor-app/elements/code-editor/javascript-code-editor.ts
+++ b/codeeditor-app/elements/code-editor/javascript-code-editor.ts
@@ -6,7 +6,13 @@ import declarations from '!!raw-loader!./injects/declarations.d.ts';
 
 export class JavascriptCodeEditor extends CodeEditor {
     setInitInput(): string {
-        return initScript;
+        var base = super.setInitInput();
+        if (!base) {
+            return initScript;
+        }
+        else {
+            return base;
+        }
     }
 
     setInitSettings(): void {
diff --git a/codeeditor-app/elements/session-list/session-list.less b/codeeditor-app/elements/session-list/session-list.less
index e69de29..df5b269 100644
--- a/codeeditor-app/elements/session-list/session-list.less
+++ b/codeeditor-app/elements/session-list/session-list.less
@@ -0,0 +1,15 @@
+@import url('../../../shared/theme.less');
+
+session-list:empty::before {
+    display: block;
+    position: relative;
+    padding: 10px;
+    color: @primary-text-color-dark;
+    content: "There is no sessions within the last 30 days";
+}
+
+@media (prefers-color-scheme: dark) {
+    session-list {
+        color: @primary-text-color-white;
+    }
+}
\ No newline at end of file
diff --git a/codeeditor-app/elements/session-list/session-list.ts b/codeeditor-app/elements/session-list/session-list.ts
index 56899f7..d3b745d 100644
--- a/codeeditor-app/elements/session-list/session-list.ts
+++ b/codeeditor-app/elements/session-list/session-list.ts
@@ -38,9 +38,9 @@ export class SessionList extends BaseElement {
 
                     this.appendChild(ele);
                 }
+                //do this in item instead:
                 else {
-                    exists.setAttribute("numberOfChanges", session.numberOfChanges);
-                    exists.getElementsByClassName("session-list-item-number-of-changes")[0].innerHTML = session.numberOfChanges;
+                    (<any>exists).updateNumberOfChanges(session.numberOfChanges);
                 }
             }
         });
diff --git a/codeeditor-app/elements/session-list-item/session-list-item.less b/codeeditor-app/elements/session-list-item/session-list-item.less
index 7b6fe90..9de62d8 100644
--- a/codeeditor-app/elements/session-list-item/session-list-item.less
+++ b/codeeditor-app/elements/session-list-item/session-list-item.less
@@ -14,8 +14,12 @@ session-list-item.selected {
     background-color: lighten(@primary-interaction-highlight-white, 30%);
 }
 
+session-list-item.selected .slider-wrap {
+    display: block;
+}
+
 .session-list-item-session-id::before {
-    content: "Session: ";
+    content: "";
 }
 
 .session-list-item-timestamp::before {
@@ -25,6 +29,7 @@ session-list-item.selected {
 .session-list-item-timestamp {
     font-size: 12px;
     opacity: 0.9;
+    padding-left: 3px;
 }
 
 .session-list-item-session-id {
@@ -32,11 +37,24 @@ session-list-item.selected {
     white-space: nowrap;
     text-overflow: ellipsis;
     overflow: hidden;
+    margin-bottom: 3px;
+}
+
+.session-list-item-session-id > span {
+    display: inline-block;
+    font-size: 9px;
+    padding: 2px 4px;
+    background-color: @editor-bg-white;
+    border: 1px solid;
+    border-color: darken(@editor-bg-white, 10%);
+    border-radius: 3px;
+    opacity: 0.7;
 }
 
 .session-list-item-number-of-changes {
     font-size: 12px;
     opacity: 0.6;
+    padding-left: 3px;
 }
 
 .session-list-item-number-of-changes::before {
@@ -45,7 +63,54 @@ session-list-item.selected {
     z-index: 0;
 }
 
-@media (prefers-color-scheme: dark) {
+.slider-wrap {
+    display: none;
+    margin-top: 3px;
+}
+
+.slider-wrap input {
+    width: 100%; /* Width of the outside container */
+  }
+  
+  /* The slider itself */
+  .slider-wrap input {
+    -webkit-appearance: none;  /* Override default CSS styles */
+    appearance: none;
+    width: 100%; /* Full-width */
+    height: 25px; /* Specified height */
+    background: @editor-bg-white; /* Grey background */
+    outline: none; /* Remove outline */
+    opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
+    -webkit-transition: .2s; /* 0.2 seconds transition on hover */
+    transition: opacity .2s;
+    border-radius: 3px;
+  }
+  
+  /* Mouse-over effects */
+  .slider-wrap input:hover {
+    opacity: 1; /* Fully shown on mouse-over */
+  }
+  
+  /* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
+  .slider-wrap input::-webkit-slider-thumb {
+    -webkit-appearance: none; /* Override default look */
+    appearance: none;
+    width: 25px; /* Set a specific slider handle width */
+    height: 25px; /* Slider handle height */
+    background: @primary-interaction-highlight-white; /* Green background */
+    cursor: pointer; /* Cursor on hover */
+    border-radius: 3px;
+  }
+  
+  .slider-wrap input::-moz-range-thumb {
+    width: 25px; /* Set a specific slider handle width */
+    height: 25px; /* Slider handle height */
+    background: @primary-interaction-highlight-white; /* Green background */
+    cursor: pointer; /* Cursor on hover */
+    border-radius: 3px;
+  }
+
+  @media (prefers-color-scheme: dark) {
     session-list-item {
         border-color: @primary-bg-color-dark;
         color: @primary-text-color-dark;
@@ -54,4 +119,13 @@ session-list-item.selected {
     session-list-item.selected {
         background-color: @primary-interaction-highlight-dark;
     }
+
+    .slider-wrap input { 
+        background: @editor-bg-dark; /* Grey background */
+    }
+
+    .session-list-item-session-id > span {
+        background-color: @editor-bg-dark;
+        border-color: lighten(@editor-bg-dark, 10%);
+    }
 }
\ No newline at end of file
diff --git a/codeeditor-app/elements/session-list-item/session-list-item.ts b/codeeditor-app/elements/session-list-item/session-list-item.ts
index 67ce5ec..7fa1c61 100644
--- a/codeeditor-app/elements/session-list-item/session-list-item.ts
+++ b/codeeditor-app/elements/session-list-item/session-list-item.ts
@@ -7,11 +7,13 @@ import { navigateTo } from '../../../shared/navigation';
 import { getSessionDetailsId } from '../../../shared/page';
 
 export class SessionListItem extends BaseElement {
+    historyIndex: number | null = null;
+
     onInit(): void {
         if (this.hasAttribute("sessionId")) {
             var sessionIdEle = document.createElement("div");
             sessionIdEle.classList.add("session-list-item-session-id");
-            sessionIdEle.innerHTML = this.getAttribute("sessionId")?.toString() ?? "";
+            sessionIdEle.innerHTML = "<span>" + (this.getAttribute("sessionId")?.toString() ?? "") + "</span>";
             this.appendChild(sessionIdEle);
         }
 
@@ -25,10 +27,12 @@ export class SessionListItem extends BaseElement {
         if (this.hasAttribute("numberOfChanges")) {
             var numberOfChangesEle = document.createElement("div");
             numberOfChangesEle.classList.add("session-list-item-number-of-changes");
-            numberOfChangesEle.innerHTML = this.getAttribute("numberOfChanges")?.toString() ?? "";
+            numberOfChangesEle.innerHTML = this.getNumberOfChanges().toString();
             this.appendChild(numberOfChangesEle);
         }
 
+        this.addSlider(this.getNumberOfChanges());
+
         this.addEventListener("click", (evt) => {
             this.itemClicked();
         });
@@ -38,11 +42,73 @@ export class SessionListItem extends BaseElement {
         }
     }
 
+    getNumberOfChanges() {
+        return parseInt(this.getAttribute("numberOfChanges")?.toString() ?? "0");
+    }
+
+    updateNumberOfChanges(numberOfChanges: number) {
+        this.setAttribute("numberOfChanges", numberOfChanges.toString());
+        this.getElementsByClassName("session-list-item-number-of-changes")[0].innerHTML = (this.historyIndex !== null ? (this.historyIndex + 1) + " / " : "") + numberOfChanges.toString();
+        this.updateSlider(numberOfChanges);
+    }
+
+    private hasSliderChanges: boolean = false;
+
+    private addSlider(numberOfChanges: number) {
+        var sliderEle = document.createElement("div");
+        sliderEle.classList.add("slider-wrap");
+        var sliderInput = document.createElement("input");
+        sliderInput.setAttribute("min", "0");
+        sliderInput.setAttribute("max", (numberOfChanges - 1).toString());
+        sliderInput.setAttribute("type", "range");
+        sliderInput.setAttribute("value", (numberOfChanges - 1).toString());
+        sliderInput.value = (numberOfChanges - 1).toString();
+
+        sliderInput.addEventListener("input", (evt) => {
+            this.hasSliderChanges = true;
+            evt.preventDefault();
+            evt.stopPropagation();
+            evt.stopImmediatePropagation();
+            this.historyIndex = parseInt((<any>evt).target.value);
+
+            if (this.historyIndex != null && this.historyIndex >= this.getNumberOfChanges() - 1) {
+                this.historyIndex = null;
+            }
+
+            this.updateNumberOfChanges(this.getNumberOfChanges());
+            this.updateInputs(true);
+        });
+
+        sliderEle.appendChild(sliderInput);
+        this.appendChild(sliderEle);
+    }
+
+    private updateSlider(numberOfChanges: number) {
+        var sliderInput = <HTMLInputElement>this.querySelector(".slider-wrap input");
+
+        if (sliderInput) {
+
+            sliderInput.setAttribute("max", (numberOfChanges - 1).toString());
+
+            if (this.historyIndex == null) {
+                sliderInput.setAttribute("value", (numberOfChanges - 1).toString());
+                sliderInput.value = (numberOfChanges - 1).toString();
+            }
+        }
+    }
+
     private intervalHandle: number | null = null;
     stopUpdate() {
         this.classList.remove("selected");
-
+        this.historyIndex = null;
         if (this.intervalHandle) {
+
+            this.updateNumberOfChanges(this.getNumberOfChanges());
+            
+            if (this.isUrlSelected()) {
+                navigateTo("/sessions");
+            }
+       
             window.clearInterval(this.intervalHandle);
             this.intervalHandle = null;
         }
@@ -62,7 +128,7 @@ export class SessionListItem extends BaseElement {
         this.intervalHandle = window.setInterval(this.updateInputs.bind(this), 1000);
     }
 
-    updateInputs() {
+    updateInputs(fromCache: boolean = false) {
         var codeEditorHTMLContainer = <CodeEditorContainer>document.querySelector("code-editor-container[language='HTML']");
         var codeEditorCSSContainer = <CodeEditorContainer>document.querySelector("code-editor-container[language='CSS']");
         var codeEditorJavascriptContainer = <CodeEditorContainer>document.querySelector("code-editor-container[language='Javascript']");
@@ -71,59 +137,80 @@ export class SessionListItem extends BaseElement {
             codeEditorJavascriptContainer.setInput(js?.data ?? "");
             codeEditorHTMLContainer.setInput(html?.data ?? "");
             codeEditorCSSContainer.setInput(css?.data ?? "");
-        });
+        }, fromCache);
 
     }
 
-    getSessionData(onGet: (javascript: any, html: any, css: any) => void) {
+    private sessionDataCache: any[] = [];
+    getSessionData(onGet: (javascript: any, html: any, css: any) => void, fromCache: boolean = false) {
+        if (fromCache) {
+            const res = this.findLastContent(this.sessionDataCache);
+            onGet(res.lastJavascript, res.lastHtml, res.lastCSS);
+            this.updateNumberOfChanges(this.sessionDataCache.length);
+        }
+        else {
+            sessionApi.getSessionData(this.getAttribute("sessionId")?.toString()?? "", (data) => {
+                this.sessionDataCache = data;
+                const res = this.findLastContent(data);
+                onGet(res.lastJavascript, res.lastHtml, res.lastCSS);
+                this.updateNumberOfChanges(data.length);
+            });
+        }
+        
+    }
+
+    private findLastContent(data: any[]) {
         var lastJavascript: any | null = null;
         var lastHtml: any | null = null;
         var lastCSS: any | null = null;
 
-        sessionApi.getSessionData(this.getAttribute("sessionId")?.toString()?? "", (data) => {
-            for (var i = data.length - 1; i >= 0; i--) {
-                var dataPoint = data[i];
-                 if (!lastJavascript && dataPoint.type == 0) {
-                    lastJavascript = dataPoint;
-                 }
-                 else if (!lastHtml && dataPoint.type == 1) {
-                    lastHtml = dataPoint;
-                 }
-                 else if (!lastCSS && dataPoint.type == 2) {
-                    lastCSS = dataPoint;
-                 }
-            }
+        for (var i = (this.historyIndex != null ? (this.historyIndex + 1) : data.length) - 1; i >= 0; i--) {
+            var dataPoint = data[i];
+             if (!lastJavascript && dataPoint.type == 0) {
+                lastJavascript = dataPoint;
+             }
+             else if (!lastHtml && dataPoint.type == 1) {
+                lastHtml = dataPoint;
+             }
+             else if (!lastCSS && dataPoint.type == 2) {
+                lastCSS = dataPoint;
+             }
+        }
 
-            onGet(lastJavascript, lastHtml, lastCSS);
-        });
+        return { lastJavascript, lastHtml, lastCSS };
     }
 
     itemClicked() {
-        if (!this.intervalHandle) {
-            var containers = <HTMLElement>document.getElementsByClassName("code-editor-containers")[0];
-            var outputframe = <HTMLElement>document.getElementsByClassName("output-frame-container")[0];
-
-            containers.style.display = "block";
-            outputframe.style.display = "block";
-
-            navigateTo("/sessions/" + this.getAttribute("sessionId")?.toString()?? "");
-
-            var children = this.parentElement?.children;
-
-            if (children) {
-                for (let i = 0; i < children.length; i++) {
-                    const child = <SessionListItem>children[i];
-                    if (child != this) {
-                        child.stopUpdate();
-                    }
-                    else {
-                        child.startUpdate();
+        if (!this.hasSliderChanges) {
+            if (!this.intervalHandle) {
+                var containers = <HTMLElement>document.getElementsByClassName("code-editor-containers")[0];
+                var outputframe = <HTMLElement>document.getElementsByClassName("output-frame-container")[0];
+
+                containers.style.display = "block";
+                outputframe.style.display = "block";
+
+                navigateTo("/sessions/" + this.getAttribute("sessionId")?.toString()?? "");
+
+                var children = this.parentElement?.children;
+
+                if (children) {
+                    for (let i = 0; i < children.length; i++) {
+                        const child = <SessionListItem>children[i];
+                        if (child != this) {
+                            child.stopUpdate();
+                        }
+                        else {
+                            child.startUpdate();
+                        }
                     }
                 }
             }
+            else {
+                this.stopUpdate();
+            }
         }
         else {
-            this.stopUpdate();
+            this.hasSliderChanges = false;
         }
     }
 }
\ No newline at end of file

package.json 1(+0 -1)

diff --git a/package.json b/package.json
index 587a8f9..8effda2 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,6 @@
     "babel-preset-env": "1.7.0",
     "copy-webpack-plugin": "11.0.0",
     "css-loader": "6.8.1",
-    "extract-text-webpack-plugin": "3.0.2",
     "file-loader": "6.2.0",
     "gulp": "4.0.2",
     "html-loader": "4.2.0",

package-lock.json 246(+0 -246)

diff --git a/package-lock.json b/package-lock.json
index ecdde16..f657b0a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,6 @@
         "babel-preset-env": "1.7.0",
         "copy-webpack-plugin": "11.0.0",
         "css-loader": "6.8.1",
-        "extract-text-webpack-plugin": "3.0.2",
         "file-loader": "6.2.0",
         "gulp": "4.0.2",
         "html-loader": "4.2.0",
@@ -1413,15 +1412,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
-      "dev": true,
-      "dependencies": {
-        "lodash": "^4.17.14"
-      }
-    },
     "node_modules/async-done": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz",
@@ -2758,16 +2748,6 @@
         "readable-stream": "^2.3.5"
       }
     },
-    "node_modules/co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
-      "dev": true,
-      "engines": {
-        "iojs": ">= 1.0.0",
-        "node": ">= 0.12.0"
-      }
-    },
     "node_modules/code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -4142,61 +4122,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/extract-text-webpack-plugin": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz",
-      "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==",
-      "deprecated": "Deprecated. Please use https://github.com/webpack-contrib/mini-css-extract-plugin",
-      "dev": true,
-      "dependencies": {
-        "async": "^2.4.1",
-        "loader-utils": "^1.1.0",
-        "schema-utils": "^0.3.0",
-        "webpack-sources": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 4.8 < 5.0.0 || >= 5.10"
-      },
-      "peerDependencies": {
-        "webpack": "^3.1.0"
-      }
-    },
-    "node_modules/extract-text-webpack-plugin/node_modules/ajv": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-      "dev": true,
-      "dependencies": {
-        "co": "^4.6.0",
-        "fast-deep-equal": "^1.0.0",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.3.0"
-      }
-    },
-    "node_modules/extract-text-webpack-plugin/node_modules/fast-deep-equal": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
-      "dev": true
-    },
-    "node_modules/extract-text-webpack-plugin/node_modules/json-schema-traverse": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
-      "dev": true
-    },
-    "node_modules/extract-text-webpack-plugin/node_modules/schema-utils": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
-      "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
-      "dev": true,
-      "dependencies": {
-        "ajv": "^5.0.0"
-      },
-      "engines": {
-        "node": ">= 4.3 < 5.0.0 || >= 5.10"
-      }
-    },
     "node_modules/fancy-log": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
@@ -6073,32 +5998,6 @@
         "node": ">=6.11.5"
       }
     },
-    "node_modules/loader-utils": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
-      "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
-      "dev": true,
-      "dependencies": {
-        "big.js": "^5.2.2",
-        "emojis-list": "^3.0.0",
-        "json5": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/loader-utils/node_modules/json5": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-      "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.0"
-      },
-      "bin": {
-        "json5": "lib/cli.js"
-      }
-    },
     "node_modules/locate-path": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -6490,12 +6389,6 @@
         "node": "*"
       }
     },
-    "node_modules/minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-      "dev": true
-    },
     "node_modules/mixin-deep": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -12048,12 +11941,6 @@
         "websocket-driver": "^0.7.4"
       }
     },
-    "node_modules/source-list-map": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
-      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
-      "dev": true
-    },
     "node_modules/source-map": {
       "version": "0.5.7",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -13472,25 +13359,6 @@
         "node": ">=10.0.0"
       }
     },
-    "node_modules/webpack-sources": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
-      "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
-      "dev": true,
-      "dependencies": {
-        "source-list-map": "^2.0.0",
-        "source-map": "~0.6.1"
-      }
-    },
-    "node_modules/webpack-sources/node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/webpack/node_modules/browserslist": {
       "version": "4.20.2",
       "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
@@ -14800,15 +14668,6 @@
       "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
       "dev": true
     },
-    "async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.17.14"
-      }
-    },
     "async-done": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz",
@@ -15995,12 +15854,6 @@
         "readable-stream": "^2.3.5"
       }
     },
-    "co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
-      "dev": true
-    },
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -17070,53 +16923,6 @@
         }
       }
     },
-    "extract-text-webpack-plugin": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz",
-      "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==",
-      "dev": true,
-      "requires": {
-        "async": "^2.4.1",
-        "loader-utils": "^1.1.0",
-        "schema-utils": "^0.3.0",
-        "webpack-sources": "^1.0.1"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "5.5.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-          "dev": true,
-          "requires": {
-            "co": "^4.6.0",
-            "fast-deep-equal": "^1.0.0",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.3.0"
-          }
-        },
-        "fast-deep-equal": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-          "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
-          "dev": true
-        },
-        "json-schema-traverse": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-          "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
-          "dev": true
-        },
-        "schema-utils": {
-          "version": "0.3.0",
-          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
-          "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
-          "dev": true,
-          "requires": {
-            "ajv": "^5.0.0"
-          }
-        }
-      }
-    },
     "fancy-log": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
@@ -18535,28 +18341,6 @@
       "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==",
       "dev": true
     },
-    "loader-utils": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
-      "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
-      "dev": true,
-      "requires": {
-        "big.js": "^5.2.2",
-        "emojis-list": "^3.0.0",
-        "json5": "^1.0.1"
-      },
-      "dependencies": {
-        "json5": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.0"
-          }
-        }
-      }
-    },
     "locate-path": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -18871,12 +18655,6 @@
         "brace-expansion": "^1.1.7"
       }
     },
-    "minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-      "dev": true
-    },
     "mixin-deep": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -22899,12 +22677,6 @@
         "websocket-driver": "^0.7.4"
       }
     },
-    "source-list-map": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
-      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
-      "dev": true
-    },
     "source-map": {
       "version": "0.5.7",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -23996,24 +23768,6 @@
         "wildcard": "^2.0.0"
       }
     },
-    "webpack-sources": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
-      "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
-      "dev": true,
-      "requires": {
-        "source-list-map": "^2.0.0",
-        "source-map": "~0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
     "websocket-driver": {
       "version": "0.7.4",
       "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
diff --git a/shared/session-api.ts b/shared/session-api.ts
index 580e158..d04ab51 100644
--- a/shared/session-api.ts
+++ b/shared/session-api.ts
@@ -1,4 +1,22 @@
 var apiUrl = "https://codeeditor-api.davidssoft.com/";
+//var apiUrl = "https://codeeditor-api.azurewebsites.net/";
+
+export function hasSession() {
+    var localstorageSessionId = localStorage.getItem("sessionId");
+
+    if (!localstorageSessionId) {
+        return false;
+    }
+    else {
+        var expiration = localStorage.getItem("sessionIdExpiration");
+        if (expiration) {
+            return !sessionIsExpired(expiration);
+        }
+        else {
+            return false;
+        }
+    }
+}
 
 function getSessionId() {
     var localstorageSessionId = localStorage.getItem("sessionId");
@@ -10,9 +28,7 @@ function getSessionId() {
         var expiration = localStorage.getItem("sessionIdExpiration");
 
         if (expiration) {
-            var expirationDate = new Date(expiration);
-
-            if (dateDiff(expirationDate, new Date()) > 120) {
+            if (sessionIsExpired(expiration)) {
                 return setNewSession();
             }
             else {
@@ -27,6 +43,10 @@ function getSessionId() {
     }
 }
 
+function sessionIsExpired(expiration: string) {
+    return dateDiff(new Date(expiration), new Date()) > 120;
+}
+
 function setNewSession() {
     var newSessionId = uuidv4();
     localStorage.setItem("sessionIdExpiration", (new Date()).toString());
@@ -76,6 +96,9 @@ export function setSessionData(language: string, input: any, onSet?: () => void)
     else if (language.toLowerCase() == "css") {
         type = 2;
     }
+    else {
+        type = 3;
+    }
 
     fetch(apiUrl + "session/set", { 
         method: "POST", 
diff --git a/shared/url-helpers.ts b/shared/url-helpers.ts
index 8c37fdf..9ab43cc 100644
--- a/shared/url-helpers.ts
+++ b/shared/url-helpers.ts
@@ -12,5 +12,6 @@ export function GetOutputFrameUrl(): string {
     }
     else {
         return "https://outputframe.davidmeincke.dk/";
+        //return "https://codeeditoroutput.z16.web.core.windows.net/";
     }
 }
\ No newline at end of file