diff --git a/Frontend Angular 4/angular.json b/Frontend Angular 4/angular.json
index 105f7599bcc25fc3fc8bbb45c025fab93aaf7dc6..85e0379e6366574be67228952aef0952288a9d7f 100644
--- a/Frontend Angular 4/angular.json	
+++ b/Frontend Angular 4/angular.json	
@@ -90,10 +90,10 @@
               "src/styles/console.css",
               "src/styles/hints.css",
               "node_modules/tippy.js/dist/tippy.css",
-              "node_modules/codemirror/lib/codemirror.css",
-              "node_modules/codemirror/addon/hint/show-hint.css",
-              "node_modules/codemirror/addon/dialog/dialog.css",
-              "node_modules/codemirror/addon/search/matchesonscrollbar.css"
+              "node_modules/lt-codemirror/lib/lt-codemirror.css",
+              "node_modules/lt-codemirror/addon/hint/show-hint.css",
+              "node_modules/lt-codemirror/addon/dialog/dialog.css",
+              "node_modules/lt-codemirror/addon/search/matchesonscrollbar.css"
             ],
             "assets": ["src/assets", "src/favicon.ico", "src/.htaccess"]
           }
diff --git a/Frontend Angular 4/browserslist b/Frontend Angular 4/browserslist
new file mode 100644
index 0000000000000000000000000000000000000000..80848532e47d58cc7a4b618f600b438960f9f045
--- /dev/null
+++ b/Frontend Angular 4/browserslist	
@@ -0,0 +1,12 @@
+# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+
+# You can see what browsers were selected by your queries by running:
+#   npx browserslist
+
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+not IE 9-11 # For IE 9-11 support, remove 'not'.
\ No newline at end of file
diff --git a/Frontend Angular 4/custom codemirror/jump-to-line.js b/Frontend Angular 4/custom codemirror/jump-to-line.js
index 696bbd40a1d6c9c8fa9f5235ed14f27ed590182e..b867b327f3a2eb1d1e119db492c4586cc61bd526 100755
--- a/Frontend Angular 4/custom codemirror/jump-to-line.js	
+++ b/Frontend Angular 4/custom codemirror/jump-to-line.js	
@@ -3,46 +3,55 @@
 
 // Defines jumpToLine command. Uses dialog.js if present.
 
-(function(mod) {
-  if (typeof exports == "object" && typeof module == "object") // CommonJS
+(function (mod) {
+  if (typeof exports == "object" && typeof module == "object")
+    // CommonJS
     mod(require("../../lib/codemirror"), require("../dialog/dialog"));
-  else if (typeof define == "function" && define.amd) // AMD
+  else if (typeof define == "function" && define.amd)
+    // AMD
     define(["../../lib/codemirror", "../dialog/dialog"], mod);
-  else // Plain browser env
-    mod(CodeMirror);
-})(function(CodeMirror) {
+  // Plain browser env
+  else mod(CodeMirror);
+})(function (CodeMirror) {
   "use strict";
 
   function dialog(cm, text, shortText, deflt, f) {
-    if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
+    if (cm.openDialog)
+      cm.openDialog(text, f, { value: deflt, selectValueOnOpen: true });
     else f(prompt(shortText, deflt));
   }
 
   var jumpDialog =
-      'Ir a la línea: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint"></span>';
+    'Ir a la línea: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint"></span>';
 
   function interpretLine(cm, string) {
-    var num = Number(string)
-    if (/^[-+]/.test(string)) return cm.getCursor().line + num
-    else return num - 1
+    var num = Number(string);
+    if (/^[-+]/.test(string)) return cm.getCursor().line + num;
+    else return num - 1;
   }
 
-  CodeMirror.commands.jumpToLine = function(cm) {
+  CodeMirror.commands.jumpToLine = function (cm) {
     var cur = cm.getCursor();
-    dialog(cm, jumpDialog, "Jump to line:", (cur.line + 1) + ":" + cur.ch, function(posStr) {
-      if (!posStr) return;
-
-      var match;
-      if (match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr)) {
-        cm.setCursor(interpretLine(cm, match[1]), Number(match[2]))
-      } else if (match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr)) {
-        var line = Math.round(cm.lineCount() * Number(match[1]) / 100);
-        if (/^[-+]/.test(match[1])) line = cur.line + line + 1;
-        cm.setCursor(line - 1, cur.ch);
-      } else if (match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr)) {
-        cm.setCursor(interpretLine(cm, match[1]), cur.ch);
+    dialog(
+      cm,
+      jumpDialog,
+      "Jump to line:",
+      cur.line + 1 + ":" + cur.ch,
+      function (posStr) {
+        if (!posStr) return;
+
+        var match;
+        if ((match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr))) {
+          cm.setCursor(interpretLine(cm, match[1]), Number(match[2]));
+        } else if ((match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr))) {
+          var line = Math.round((cm.lineCount() * Number(match[1])) / 100);
+          if (/^[-+]/.test(match[1])) line = cur.line + line + 1;
+          cm.setCursor(line - 1, cur.ch);
+        } else if ((match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr))) {
+          cm.setCursor(interpretLine(cm, match[1]), cur.ch);
+        }
       }
-    });
+    );
   };
 
   CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine";
diff --git a/Frontend Angular 4/custom codemirror/search.js b/Frontend Angular 4/custom codemirror/search.js
index 08b24d265f1d2ff73856b40ebe071bc8c4ecf035..82806abe7d34ece1a5c4d0700d8f3d7e4a6cac29 100755
--- a/Frontend Angular 4/custom codemirror/search.js	
+++ b/Frontend Angular 4/custom codemirror/search.js	
@@ -9,34 +9,45 @@
 // replace by making sure the match is no longer selected when hitting
 // Ctrl-G.
 
-(function(mod) {
-  if (typeof exports == "object" && typeof module == "object") // CommonJS
-    mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
-  else if (typeof define == "function" && define.amd) // AMD
+(function (mod) {
+  if (typeof exports == "object" && typeof module == "object")
+    // CommonJS
+    mod(
+      require("../../lib/codemirror"),
+      require("./searchcursor"),
+      require("../dialog/dialog")
+    );
+  else if (typeof define == "function" && define.amd)
+    // AMD
     define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
-  else // Plain browser env
-    mod(CodeMirror);
-})(function(CodeMirror) {
+  // Plain browser env
+  else mod(CodeMirror);
+})(function (CodeMirror) {
   "use strict";
 
   function searchOverlay(query, caseInsensitive) {
     if (typeof query == "string")
-      query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
+      query = new RegExp(
+        query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
+        caseInsensitive ? "gi" : "g"
+      );
     else if (!query.global)
       query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
 
-    return {token: function(stream) {
-      query.lastIndex = stream.pos;
-      var match = query.exec(stream.string);
-      if (match && match.index == stream.pos) {
-        stream.pos += match[0].length || 1;
-        return "searching";
-      } else if (match) {
-        stream.pos = match.index;
-      } else {
-        stream.skipToEnd();
-      }
-    }};
+    return {
+      token: function (stream) {
+        query.lastIndex = stream.pos;
+        var match = query.exec(stream.string);
+        if (match && match.index == stream.pos) {
+          stream.pos += match[0].length || 1;
+          return "searching";
+        } else if (match) {
+          stream.pos = match.index;
+        } else {
+          stream.skipToEnd();
+        }
+      },
+    };
   }
 
   function SearchState() {
@@ -54,7 +65,10 @@
 
   function getSearchCursor(cm, query, pos) {
     // Heuristic: if the query string is all lowercase, do a case insensitive search.
-    return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true});
+    return cm.getSearchCursor(query, pos, {
+      caseFold: queryCaseInsensitive(query),
+      multiline: true,
+    });
   }
 
   function persistentDialog(cm, text, deflt, onEnter, onKeyDown) {
@@ -62,13 +76,16 @@
       value: deflt,
       selectValueOnOpen: true,
       closeOnEnter: false,
-      onClose: function() { clearSearch(cm); },
-      onKeyDown: onKeyDown
+      onClose: function () {
+        clearSearch(cm);
+      },
+      onKeyDown: onKeyDown,
     });
   }
 
   function dialog(cm, text, shortText, deflt, f) {
-    if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
+    if (cm.openDialog)
+      cm.openDialog(text, f, { value: deflt, selectValueOnOpen: true });
     else f(prompt(shortText, deflt));
   }
 
@@ -78,23 +95,23 @@
   }
 
   function parseString(string) {
-    return string.replace(/\\(.)/g, function(_, ch) {
-      if (ch == "n") return "\n"
-      if (ch == "r") return "\r"
-      return ch
-    })
+    return string.replace(/\\(.)/g, function (_, ch) {
+      if (ch == "n") return "\n";
+      if (ch == "r") return "\r";
+      return ch;
+    });
   }
 
   function parseQuery(query) {
     var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
     if (isRE) {
-      try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
-      catch(e) {} // Not a regular expression after all, do a string search
+      try {
+        query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i");
+      } catch (e) {} // Not a regular expression after all, do a string search
     } else {
-      query = parseString(query)
+      query = parseString(query);
     }
-    if (typeof query == "string" ? query == "" : query.test(""))
-      query = /x^/;
+    if (typeof query == "string" ? query == "" : query.test("")) query = /x^/;
     return query;
   }
 
@@ -105,11 +122,20 @@
     state.queryText = query;
     state.query = parseQuery(query);
     cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
-    state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
+    state.overlay = searchOverlay(
+      state.query,
+      queryCaseInsensitive(state.query)
+    );
     cm.addOverlay(state.overlay);
     if (cm.showMatchesOnScrollbar) {
-      if (state.annotate) { state.annotate.clear(); state.annotate = null; }
-      state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
+      if (state.annotate) {
+        state.annotate.clear();
+        state.annotate = null;
+      }
+      state.annotate = cm.showMatchesOnScrollbar(
+        state.query,
+        queryCaseInsensitive(state.query)
+      );
     }
   }
 
@@ -118,29 +144,37 @@
     if (state.query) return findNext(cm, rev);
     var q = cm.getSelection() || state.lastQuery;
     if (persistent && cm.openDialog) {
-      var hiding = null
-      var searchNext = function(query, event) {
+      var hiding = null;
+      var searchNext = function (query, event) {
         CodeMirror.e_stop(event);
         if (!query) return;
         if (query != state.queryText) {
           startSearch(cm, state, query);
           state.posFrom = state.posTo = cm.getCursor();
         }
-        if (hiding) hiding.style.opacity = 1
-        findNext(cm, event.shiftKey, function(_, to) {
-          var dialog
-          if (to.line < 3 && document.querySelector &&
-              (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
-              dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
-            (hiding = dialog).style.opacity = .4
-        })
+        if (hiding) hiding.style.opacity = 1;
+        findNext(cm, event.shiftKey, function (_, to) {
+          var dialog;
+          if (
+            to.line < 3 &&
+            document.querySelector &&
+            (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
+            dialog.getBoundingClientRect().bottom - 4 >
+              cm.cursorCoords(to, "window").top
+          )
+            (hiding = dialog).style.opacity = 0.4;
+        });
       };
-      persistentDialog(cm, queryDialog, q, searchNext, function(event, query) {
-        var keyName = CodeMirror.keyName(event)
-        var cmd = CodeMirror.keyMap[cm.getOption("keyMap")][keyName]
-        if (!cmd) cmd = cm.getOption('extraKeys')[keyName]
-        if (cmd == "findNext" || cmd == "findPrev" ||
-          cmd == "findPersistentNext" || cmd == "findPersistentPrev") {
+      persistentDialog(cm, queryDialog, q, searchNext, function (event, query) {
+        var keyName = CodeMirror.keyName(event);
+        var cmd = CodeMirror.keyMap[cm.getOption("keyMap")][keyName];
+        if (!cmd) cmd = cm.getOption("extraKeys")[keyName];
+        if (
+          cmd == "findNext" ||
+          cmd == "findPrev" ||
+          cmd == "findPersistentNext" ||
+          cmd == "findPersistentPrev"
+        ) {
           CodeMirror.e_stop(event);
           startSearch(cm, getSearchState(cm), query);
           cm.execCommand(cmd);
@@ -154,49 +188,74 @@
         findNext(cm, rev);
       }
     } else {
-      dialog(cm, queryDialog, "Buscar por:", q, function(query) {
-        if (query && !state.query) cm.operation(function() {
-          startSearch(cm, state, query);
-          state.posFrom = state.posTo = cm.getCursor();
-          findNext(cm, rev);
-        });
+      dialog(cm, queryDialog, "Buscar por:", q, function (query) {
+        if (query && !state.query)
+          cm.operation(function () {
+            startSearch(cm, state, query);
+            state.posFrom = state.posTo = cm.getCursor();
+            findNext(cm, rev);
+          });
       });
     }
   }
 
-  function findNext(cm, rev, callback) {cm.operation(function() {
-    var state = getSearchState(cm);
-    var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
-    if (!cursor.find(rev)) {
-      cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
-      if (!cursor.find(rev)) return;
-    }
-    cm.setSelection(cursor.from(), cursor.to());
-    cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
-    state.posFrom = cursor.from(); state.posTo = cursor.to();
-    if (callback) callback(cursor.from(), cursor.to())
-  });}
+  function findNext(cm, rev, callback) {
+    cm.operation(function () {
+      var state = getSearchState(cm);
+      var cursor = getSearchCursor(
+        cm,
+        state.query,
+        rev ? state.posFrom : state.posTo
+      );
+      if (!cursor.find(rev)) {
+        cursor = getSearchCursor(
+          cm,
+          state.query,
+          rev
+            ? CodeMirror.Pos(cm.lastLine())
+            : CodeMirror.Pos(cm.firstLine(), 0)
+        );
+        if (!cursor.find(rev)) return;
+      }
+      cm.setSelection(cursor.from(), cursor.to());
+      cm.scrollIntoView({ from: cursor.from(), to: cursor.to() }, 20);
+      state.posFrom = cursor.from();
+      state.posTo = cursor.to();
+      if (callback) callback(cursor.from(), cursor.to());
+    });
+  }
 
-  function clearSearch(cm) {cm.operation(function() {
-    var state = getSearchState(cm);
-    state.lastQuery = state.query;
-    if (!state.query) return;
-    state.query = state.queryText = null;
-    cm.removeOverlay(state.overlay);
-    if (state.annotate) { state.annotate.clear(); state.annotate = null; }
-  });}
+  function clearSearch(cm) {
+    cm.operation(function () {
+      var state = getSearchState(cm);
+      state.lastQuery = state.query;
+      if (!state.query) return;
+      state.query = state.queryText = null;
+      cm.removeOverlay(state.overlay);
+      if (state.annotate) {
+        state.annotate.clear();
+        state.annotate = null;
+      }
+    });
+  }
 
   var replaceQueryDialog =
     ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint"></span>';
-  var replacementQueryDialog = '<span class="CodeMirror-search-label">Con:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
-  var doReplaceConfirm = '<span class="CodeMirror-search-label">Reemplazar?</span> <button>Si</button> <button>No</button> <button>Todos</button> <button>Cancelar</button>';
+  var replacementQueryDialog =
+    '<span class="CodeMirror-search-label">Con:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
+  var doReplaceConfirm =
+    '<span class="CodeMirror-search-label">Reemplazar?</span> <button>Si</button> <button>No</button> <button>Todos</button> <button>Cancelar</button>';
 
   function replaceAll(cm, query, text) {
-    cm.operation(function() {
-      for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
+    cm.operation(function () {
+      for (var cursor = getSearchCursor(cm, query); cursor.findNext(); ) {
         if (typeof query != "string") {
           var match = cm.getRange(cursor.from(), cursor.to()).match(query);
-          cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
+          cursor.replace(
+            text.replace(/\$(\d)/g, function (_, i) {
+              return match[i];
+            })
+          );
         } else cursor.replace(text);
       }
     });
@@ -205,48 +264,94 @@
   function replace(cm, all) {
     if (cm.getOption("readOnly")) return;
     var query = cm.getSelection() || getSearchState(cm).lastQuery;
-    var dialogText = '<span class="CodeMirror-search-label">' + (all ? 'Reemplazar todo:' : 'Reemplazar:') + '</span>';
-    dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
-      if (!query) return;
-      query = parseQuery(query);
-      dialog(cm, replacementQueryDialog, "Reemplazar con:", "", function(text) {
-        text = parseString(text)
-        if (all) {
-          replaceAll(cm, query, text)
-        } else {
-          clearSearch(cm);
-          var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
-          var advance = function() {
-            var start = cursor.from(), match;
-            if (!(match = cursor.findNext())) {
-              cursor = getSearchCursor(cm, query);
-              if (!(match = cursor.findNext()) ||
-                  (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
+    var dialogText =
+      '<span class="CodeMirror-search-label">' +
+      (all ? "Reemplazar todo:" : "Reemplazar:") +
+      "</span>";
+    dialog(
+      cm,
+      dialogText + replaceQueryDialog,
+      dialogText,
+      query,
+      function (query) {
+        if (!query) return;
+        query = parseQuery(query);
+        dialog(
+          cm,
+          replacementQueryDialog,
+          "Reemplazar con:",
+          "",
+          function (text) {
+            text = parseString(text);
+            if (all) {
+              replaceAll(cm, query, text);
+            } else {
+              clearSearch(cm);
+              var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
+              var advance = function () {
+                var start = cursor.from(),
+                  match;
+                if (!(match = cursor.findNext())) {
+                  cursor = getSearchCursor(cm, query);
+                  if (
+                    !(match = cursor.findNext()) ||
+                    (start &&
+                      cursor.from().line == start.line &&
+                      cursor.from().ch == start.ch)
+                  )
+                    return;
+                }
+                cm.setSelection(cursor.from(), cursor.to());
+                cm.scrollIntoView({ from: cursor.from(), to: cursor.to() });
+                confirmDialog(cm, doReplaceConfirm, "Reemplazar?", [
+                  function () {
+                    doReplace(match);
+                  },
+                  advance,
+                  function () {
+                    replaceAll(cm, query, text);
+                  },
+                ]);
+              };
+              var doReplace = function (match) {
+                cursor.replace(
+                  typeof query == "string"
+                    ? text
+                    : text.replace(/\$(\d)/g, function (_, i) {
+                        return match[i];
+                      })
+                );
+                advance();
+              };
+              advance();
             }
-            cm.setSelection(cursor.from(), cursor.to());
-            cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
-            confirmDialog(cm, doReplaceConfirm, "Reemplazar?",
-                          [function() {doReplace(match);}, advance,
-                           function() {replaceAll(cm, query, text)}]);
-          };
-          var doReplace = function(match) {
-            cursor.replace(typeof query == "string" ? text :
-                           text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
-            advance();
-          };
-          advance();
-        }
-      });
-    });
+          }
+        );
+      }
+    );
   }
 
-  CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
-  CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
-  CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);};
-  CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);};
+  CodeMirror.commands.find = function (cm) {
+    clearSearch(cm);
+    doSearch(cm);
+  };
+  CodeMirror.commands.findPersistent = function (cm) {
+    clearSearch(cm);
+    doSearch(cm, false, true);
+  };
+  CodeMirror.commands.findPersistentNext = function (cm) {
+    doSearch(cm, false, true, true);
+  };
+  CodeMirror.commands.findPersistentPrev = function (cm) {
+    doSearch(cm, true, true, true);
+  };
   CodeMirror.commands.findNext = doSearch;
-  CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
+  CodeMirror.commands.findPrev = function (cm) {
+    doSearch(cm, true);
+  };
   CodeMirror.commands.clearSearch = clearSearch;
   CodeMirror.commands.replace = replace;
-  CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
+  CodeMirror.commands.replaceAll = function (cm) {
+    replace(cm, true);
+  };
 });
diff --git a/Frontend Angular 4/custom codemirror/show-hint.js b/Frontend Angular 4/custom codemirror/show-hint.js
index 2802577553bd4b173af0d9f1f51123cdfcf46a4a..193bb29395d3c9a46df1bcbb5c3da5282065ff55 100755
--- a/Frontend Angular 4/custom codemirror/show-hint.js	
+++ b/Frontend Angular 4/custom codemirror/show-hint.js	
@@ -1,32 +1,34 @@
 // CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: https://codemirror.net/LICENSE
 
-(function(mod) {
-  if (typeof exports == "object" && typeof module == "object") // CommonJS
+(function (mod) {
+  if (typeof exports == "object" && typeof module == "object")
+    // CommonJS
     mod(require("../../lib/codemirror"));
-  else if (typeof define == "function" && define.amd) // AMD
+  else if (typeof define == "function" && define.amd)
+    // AMD
     define(["../../lib/codemirror"], mod);
-  else // Plain browser env
-    mod(CodeMirror);
-})(function(CodeMirror) {
+  // Plain browser env
+  else mod(CodeMirror);
+})(function (CodeMirror) {
   "use strict";
 
-  var HINT_ELEMENT_CLASS        = "CodeMirror-hint";
+  var HINT_ELEMENT_CLASS = "CodeMirror-hint";
   var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
 
   // This is the old interface, kept around for now to stay
   // backwards-compatible.
-  CodeMirror.showHint = function(cm, getHints, options) {
+  CodeMirror.showHint = function (cm, getHints, options) {
     if (!getHints) return cm.showHint(options);
     if (options && options.async) getHints.async = true;
-    var newOpts = {hint: getHints};
+    var newOpts = { hint: getHints };
     if (options) for (var prop in options) newOpts[prop] = options[prop];
     return cm.showHint(newOpts);
   };
 
-  CodeMirror.defineExtension("showHint", function(options) {
+  CodeMirror.defineExtension("showHint", function (options) {
     options = parseOptions(this, this.getCursor("start"), options);
-    var selections = this.listSelections()
+    var selections = this.listSelections();
     if (selections.length > 1) return;
     // By default, don't allow completion when something is selected.
     // A hint function can have a `supportsSelection` property to
@@ -39,7 +41,10 @@
     }
 
     if (this.state.completionActive) this.state.completionActive.close();
-    var completion = this.state.completionActive = new Completion(this, options);
+    var completion = (this.state.completionActive = new Completion(
+      this,
+      options
+    ));
     if (!completion.options.hint) return;
 
     CodeMirror.signal(this, "startCompletion", this);
@@ -53,19 +58,28 @@
     this.debounce = 0;
     this.tick = 0;
     this.startPos = this.cm.getCursor("start");
-    this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
+    this.startLen =
+      this.cm.getLine(this.startPos.line).length -
+      this.cm.getSelection().length;
 
     var self = this;
-    cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
+    cm.on(
+      "cursorActivity",
+      (this.activityFunc = function () {
+        self.cursorActivity();
+      })
+    );
   }
 
-  var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
-    return setTimeout(fn, 1000/60);
-  };
+  var requestAnimationFrame =
+    window.requestAnimationFrame ||
+    function (fn) {
+      return setTimeout(fn, 1000 / 60);
+    };
   var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
 
   Completion.prototype = {
-    close: function() {
+    close: function () {
       if (!this.active()) return;
       this.cm.state.completionActive = null;
       this.tick = null;
@@ -76,49 +90,65 @@
       CodeMirror.signal(this.cm, "endCompletion", this.cm);
     },
 
-    active: function() {
+    active: function () {
       return this.cm.state.completionActive == this;
     },
 
-    pick: function(data, i) {
+    pick: function (data, i) {
       var completion = data.list[i];
       if (completion.hint) completion.hint(this.cm, data, completion);
-      else this.cm.replaceRange(getText(completion), completion.from || data.from,
-                                completion.to || data.to, "complete");
+      else
+        this.cm.replaceRange(
+          getText(completion),
+          completion.from || data.from,
+          completion.to || data.to,
+          "complete"
+        );
       CodeMirror.signal(data, "pick", completion);
       this.close();
     },
 
-    cursorActivity: function() {
+    cursorActivity: function () {
       if (this.debounce) {
         cancelAnimationFrame(this.debounce);
         this.debounce = 0;
       }
 
-      var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
-      if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
-          pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
-          (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
+      var pos = this.cm.getCursor(),
+        line = this.cm.getLine(pos.line);
+      if (
+        pos.line != this.startPos.line ||
+        line.length - pos.ch != this.startLen - this.startPos.ch ||
+        pos.ch < this.startPos.ch ||
+        this.cm.somethingSelected() ||
+        !pos.ch ||
+        this.options.closeCharacters.test(line.charAt(pos.ch - 1))
+      ) {
         this.close();
       } else {
         var self = this;
-        this.debounce = requestAnimationFrame(function() {self.update();});
+        this.debounce = requestAnimationFrame(function () {
+          self.update();
+        });
         if (this.widget) this.widget.disable();
       }
     },
 
-    update: function(first) {
-      if (this.tick == null) return
-      var self = this, myTick = ++this.tick
-      fetchHints(this.options.hint, this.cm, this.options, function(data) {
-        if (self.tick == myTick) self.finishUpdate(data, first)
-      })
+    update: function (first) {
+      if (this.tick == null) return;
+      var self = this,
+        myTick = ++this.tick;
+      fetchHints(this.options.hint, this.cm, this.options, function (data) {
+        if (self.tick == myTick) self.finishUpdate(data, first);
+      });
     },
 
-    finishUpdate: function(data, first) {
+    finishUpdate: function (data, first) {
       if (this.data) CodeMirror.signal(this.data, "update");
 
-      var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
+      var picked =
+        (this.widget && this.widget.picked) ||
+        (first && this.options.completeSingle);
       if (this.widget) this.widget.close();
 
       this.data = data;
@@ -131,18 +161,20 @@
           CodeMirror.signal(data, "shown");
         }
       }
-    }
+    },
   };
 
   function parseOptions(cm, pos, options) {
     var editor = cm.options.hintOptions;
     var out = {};
     for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
-    if (editor) for (var prop in editor)
-      if (editor[prop] !== undefined) out[prop] = editor[prop];
-    if (options) for (var prop in options)
-      if (options[prop] !== undefined) out[prop] = options[prop];
-    if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
+    if (editor)
+      for (var prop in editor)
+        if (editor[prop] !== undefined) out[prop] = editor[prop];
+    if (options)
+      for (var prop in options)
+        if (options[prop] !== undefined) out[prop] = options[prop];
+    if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos);
     return out;
   }
 
@@ -153,42 +185,55 @@
 
   function buildKeyMap(completion, handle) {
     var baseMap = {
-      Up: function() {handle.moveFocus(-1);},
-      Down: function() {handle.moveFocus(1);},
-      PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
-      PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
-      Home: function() {handle.setFocus(0);},
-      End: function() {handle.setFocus(handle.length - 1);},
+      Up: function () {
+        handle.moveFocus(-1);
+      },
+      Down: function () {
+        handle.moveFocus(1);
+      },
+      PageUp: function () {
+        handle.moveFocus(-handle.menuSize() + 1, true);
+      },
+      PageDown: function () {
+        handle.moveFocus(handle.menuSize() - 1, true);
+      },
+      Home: function () {
+        handle.setFocus(0);
+      },
+      End: function () {
+        handle.setFocus(handle.length - 1);
+      },
       Enter: handle.pick,
       Tab: handle.pick,
-      Esc: handle.close
+      Esc: handle.close,
     };
     var custom = completion.options.customKeys;
     var ourMap = custom ? {} : baseMap;
     function addBinding(key, val) {
       var bound;
       if (typeof val != "string")
-        bound = function(cm) { return val(cm, handle); };
+        bound = function (cm) {
+          return val(cm, handle);
+        };
       // This mechanism is deprecated
-      else if (baseMap.hasOwnProperty(val))
-        bound = baseMap[val];
-      else
-        bound = val;
+      else if (baseMap.hasOwnProperty(val)) bound = baseMap[val];
+      else bound = val;
       ourMap[key] = bound;
     }
     if (custom)
-      for (var key in custom) if (custom.hasOwnProperty(key))
-        addBinding(key, custom[key]);
+      for (var key in custom)
+        if (custom.hasOwnProperty(key)) addBinding(key, custom[key]);
     var extra = completion.options.extraKeys;
     if (extra)
-      for (var key in extra) if (extra.hasOwnProperty(key))
-        addBinding(key, extra[key]);
+      for (var key in extra)
+        if (extra.hasOwnProperty(key)) addBinding(key, extra[key]);
     return ourMap;
   }
 
   function getHintElement(hintsElement, el) {
     while (el && el != hintsElement) {
-      if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
+      if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement)
+        return el;
       el = el.parentNode;
     }
   }
@@ -197,45 +242,69 @@
     this.completion = completion;
     this.data = data;
     this.picked = false;
-    var widget = this, cm = completion.cm;
+    var widget = this,
+      cm = completion.cm;
     var ownerDocument = cm.getInputField().ownerDocument;
     var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
 
-    var hints = this.hints = ownerDocument.createElement("ul");
+    var hints = (this.hints = ownerDocument.createElement("ul"));
     var theme = completion.cm.options.theme;
     hints.className = "CodeMirror-hints " + theme;
     this.selectedHint = data.selectedHint || 0;
 
     var completions = data.list;
     for (var i = 0; i < completions.length; ++i) {
-      var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
-      var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
+      var elt = hints.appendChild(ownerDocument.createElement("li")),
+        cur = completions[i];
+      var className =
+        HINT_ELEMENT_CLASS +
+        (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
       if (cur.className != null) className = cur.className + " " + className;
       elt.className = className;
       if (cur.render) cur.render(elt, data, cur);
-      else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
+      else
+        elt.appendChild(
+          ownerDocument.createTextNode(cur.displayText || getText(cur))
+        );
       elt.hintId = i;
     }
 
-    var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
-    var left = pos.left, top = pos.bottom, below = true;
+    var pos = cm.cursorCoords(
+      completion.options.alignWithWord ? data.from : null
+    );
+    var left = pos.left,
+      top = pos.bottom,
+      below = true;
     hints.style.left = left + "px";
     hints.style.top = top + "px";
     // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
-    var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
-    var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
+    var winW =
+      parentWindow.innerWidth ||
+      Math.max(
+        ownerDocument.body.offsetWidth,
+        ownerDocument.documentElement.offsetWidth
+      );
+    var winH =
+      parentWindow.innerHeight ||
+      Math.max(
+        ownerDocument.body.offsetHeight,
+        ownerDocument.documentElement.offsetHeight
+      );
     (completion.options.container || ownerDocument.body).appendChild(hints);
-    var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
-    var scrolls = hints.scrollHeight > hints.clientHeight + 1
+    var box = hints.getBoundingClientRect(),
+      overlapY = box.bottom - winH;
+    var scrolls = hints.scrollHeight > hints.clientHeight + 1;
     var startScroll = cm.getScrollInfo();
 
     if (overlapY > 0) {
-      var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
-      if (curTop - height > 0) { // Fits above cursor
+      var height = box.bottom - box.top,
+        curTop = pos.top - (pos.bottom - box.top);
+      if (curTop - height > 0) {
+        // Fits above cursor
         hints.style.top = (top = pos.top - height) + "px";
         below = false;
       } else if (height > winH) {
-        hints.style.height = (winH - 5) + "px";
+        hints.style.height = winH - 5 + "px";
         hints.style.top = (top = pos.bottom - box.top) + "px";
         var cursor = cm.getCursor();
         if (data.from.ch != cursor.ch) {
@@ -248,46 +317,82 @@
     var overlapX = box.right - winW;
     if (overlapX > 0) {
       if (box.right - box.left > winW) {
-        hints.style.width = (winW - 5) + "px";
-        overlapX -= (box.right - box.left) - winW;
+        hints.style.width = winW - 5 + "px";
+        overlapX -= box.right - box.left - winW;
       }
       hints.style.left = (left = pos.left - overlapX) + "px";
     }
-    if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
-      node.style.paddingRight = cm.display.nativeBarWidth + "px"
-
-    cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
-      moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
-      setFocus: function(n) { widget.changeActive(n); },
-      menuSize: function() { return widget.screenAmount(); },
-      length: completions.length,
-      close: function() { completion.close(); },
-      pick: function() { widget.pick(); },
-      data: data
-    }));
+    if (scrolls)
+      for (var node = hints.firstChild; node; node = node.nextSibling)
+        node.style.paddingRight = cm.display.nativeBarWidth + "px";
+
+    cm.addKeyMap(
+      (this.keyMap = buildKeyMap(completion, {
+        moveFocus: function (n, avoidWrap) {
+          widget.changeActive(widget.selectedHint + n, avoidWrap);
+        },
+        setFocus: function (n) {
+          widget.changeActive(n);
+        },
+        menuSize: function () {
+          return widget.screenAmount();
+        },
+        length: completions.length,
+        close: function () {
+          completion.close();
+        },
+        pick: function () {
+          widget.pick();
+        },
+        data: data,
+      }))
+    );
 
     if (completion.options.closeOnUnfocus) {
       var closingOnBlur;
-      cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
-      cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
+      cm.on(
+        "blur",
+        (this.onBlur = function () {
+          closingOnBlur = setTimeout(function () {
+            completion.close();
+          }, 100);
+        })
+      );
+      cm.on(
+        "focus",
+        (this.onFocus = function () {
+          clearTimeout(closingOnBlur);
+        })
+      );
     }
 
-    cm.on("scroll", this.onScroll = function() {
-      var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
-      var newTop = top + startScroll.top - curScroll.top;
-      var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
-      if (!below) point += hints.offsetHeight;
-      if (point <= editor.top || point >= editor.bottom) return completion.close();
-      hints.style.top = newTop + "px";
-      hints.style.left = (left + startScroll.left - curScroll.left) + "px";
-    });
+    cm.on(
+      "scroll",
+      (this.onScroll = function () {
+        var curScroll = cm.getScrollInfo(),
+          editor = cm.getWrapperElement().getBoundingClientRect();
+        var newTop = top + startScroll.top - curScroll.top;
+        var point =
+          newTop -
+          (parentWindow.pageYOffset ||
+            (ownerDocument.documentElement || ownerDocument.body).scrollTop);
+        if (!below) point += hints.offsetHeight;
+        if (point <= editor.top || point >= editor.bottom)
+          return completion.close();
+        hints.style.top = newTop + "px";
+        hints.style.left = left + startScroll.left - curScroll.left + "px";
+      })
+    );
 
-    CodeMirror.on(hints, "dblclick", function(e) {
+    CodeMirror.on(hints, "dblclick", function (e) {
       var t = getHintElement(hints, e.target || e.srcElement);
-      if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
+      if (t && t.hintId != null) {
+        widget.changeActive(t.hintId);
+        widget.pick();
+      }
     });
 
-    CodeMirror.on(hints, "click", function(e) {
+    CodeMirror.on(hints, "click", function (e) {
       var t = getHintElement(hints, e.target || e.srcElement);
       if (t && t.hintId != null) {
         widget.changeActive(t.hintId);
@@ -295,16 +400,23 @@
       }
     });
 
-    CodeMirror.on(hints, "mousedown", function() {
-      setTimeout(function(){cm.focus();}, 20);
+    CodeMirror.on(hints, "mousedown", function () {
+      setTimeout(function () {
+        cm.focus();
+      }, 20);
     });
 
-    CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
+    CodeMirror.signal(
+      data,
+      "select",
+      completions[this.selectedHint],
+      hints.childNodes[this.selectedHint]
+    );
     return true;
   }
 
   Widget.prototype = {
-    close: function() {
+    close: function () {
       if (this.completion.widget != this) return;
       this.completion.widget = null;
       this.hints.parentNode.removeChild(this.hints);
@@ -318,104 +430,134 @@
       cm.off("scroll", this.onScroll);
     },
 
-    disable: function() {
+    disable: function () {
       this.completion.cm.removeKeyMap(this.keyMap);
       var widget = this;
-      this.keyMap = {Enter: function() { widget.picked = true; }};
+      this.keyMap = {
+        Enter: function () {
+          widget.picked = true;
+        },
+      };
       this.completion.cm.addKeyMap(this.keyMap);
     },
 
-    pick: function() {
+    pick: function () {
       this.completion.pick(this.data, this.selectedHint);
     },
 
-    changeActive: function(i, avoidWrap) {
+    changeActive: function (i, avoidWrap) {
       if (i >= this.data.list.length)
         i = avoidWrap ? this.data.list.length - 1 : 0;
-      else if (i < 0)
-        i = avoidWrap ? 0  : this.data.list.length - 1;
+      else if (i < 0) i = avoidWrap ? 0 : this.data.list.length - 1;
       if (this.selectedHint == i) return;
       var node = this.hints.childNodes[this.selectedHint];
-      if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
-      node = this.hints.childNodes[this.selectedHint = i];
+      if (node)
+        node.className = node.className.replace(
+          " " + ACTIVE_HINT_ELEMENT_CLASS,
+          ""
+        );
+      node = this.hints.childNodes[(this.selectedHint = i)];
       node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
       if (node.offsetTop < this.hints.scrollTop)
         this.hints.scrollTop = node.offsetTop - 3;
-      else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
-        this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
-      CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
+      else if (
+        node.offsetTop + node.offsetHeight >
+        this.hints.scrollTop + this.hints.clientHeight
+      )
+        this.hints.scrollTop =
+          node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
+      CodeMirror.signal(
+        this.data,
+        "select",
+        this.data.list[this.selectedHint],
+        node
+      );
     },
 
-    screenAmount: function() {
-      return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
-    }
+    screenAmount: function () {
+      return (
+        Math.floor(
+          this.hints.clientHeight / this.hints.firstChild.offsetHeight
+        ) || 1
+      );
+    },
   };
 
   function applicableHelpers(cm, helpers) {
-    if (!cm.somethingSelected()) return helpers
-    var result = []
+    if (!cm.somethingSelected()) return helpers;
+    var result = [];
     for (var i = 0; i < helpers.length; i++)
-      if (helpers[i].supportsSelection) result.push(helpers[i])
-    return result
+      if (helpers[i].supportsSelection) result.push(helpers[i]);
+    return result;
   }
 
   function fetchHints(hint, cm, options, callback) {
     if (hint.async) {
-      hint(cm, callback, options)
+      hint(cm, callback, options);
     } else {
-      var result = hint(cm, options)
-      if (result && result.then) result.then(callback)
-      else callback(result)
+      var result = hint(cm, options);
+      if (result && result.then) result.then(callback);
+      else callback(result);
     }
   }
 
   function resolveAutoHints(cm, pos) {
-    var helpers = cm.getHelpers(pos, "hint"), words
+    var helpers = cm.getHelpers(pos, "hint"),
+      words;
     if (helpers.length) {
-      var resolved = function(cm, callback, options) {
+      var resolved = function (cm, callback, options) {
         var app = applicableHelpers(cm, helpers);
         function run(i) {
-          if (i == app.length) return callback(null)
-          fetchHints(app[i], cm, options, function(result) {
-            if (result && result.list.length > 0) callback(result)
-            else run(i + 1)
-          })
+          if (i == app.length) return callback(null);
+          fetchHints(app[i], cm, options, function (result) {
+            if (result && result.list.length > 0) callback(result);
+            else run(i + 1);
+          });
         }
-        run(0)
-      }
-      resolved.async = true
-      resolved.supportsSelection = true
-      return resolved
-    } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
-      return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
+        run(0);
+      };
+      resolved.async = true;
+      resolved.supportsSelection = true;
+      return resolved;
+    } else if ((words = cm.getHelper(cm.getCursor(), "hintWords"))) {
+      return function (cm) {
+        return CodeMirror.hint.fromList(cm, { words: words });
+      };
     } else if (CodeMirror.hint.anyword) {
-      return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
+      return function (cm, options) {
+        return CodeMirror.hint.anyword(cm, options);
+      };
     } else {
-      return function() {}
+      return function () {};
     }
   }
 
   CodeMirror.registerHelper("hint", "auto", {
-    resolve: resolveAutoHints
+    resolve: resolveAutoHints,
   });
 
-  CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
-    var cur = cm.getCursor(), token = cm.getTokenAt(cur)
-    var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
-    if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
-      term = token.string.substr(0, cur.ch - token.start)
+  CodeMirror.registerHelper("hint", "fromList", function (cm, options) {
+    var cur = cm.getCursor(),
+      token = cm.getTokenAt(cur);
+    var term,
+      from = CodeMirror.Pos(cur.line, token.start),
+      to = cur;
+    if (
+      token.start < cur.ch &&
+      /\w/.test(token.string.charAt(cur.ch - token.start - 1))
+    ) {
+      term = token.string.substr(0, cur.ch - token.start);
     } else {
-      term = ""
-      from = cur
+      term = "";
+      from = cur;
     }
     var found = [];
     for (var i = 0; i < options.words.length; i++) {
       var word = options.words[i];
-      if (word.slice(0, term.length) == term)
-        found.push(word);
+      if (word.slice(0, term.length) == term) found.push(word);
     }
 
-    if (found.length) return {list: found, from: from, to: to};
+    if (found.length) return { list: found, from: from, to: to };
   });
 
   CodeMirror.commands.autocomplete = CodeMirror.showHint;
@@ -429,7 +571,7 @@
     completeOnSingleClick: true,
     container: null,
     customKeys: null,
-    extraKeys: null
+    extraKeys: null,
   };
 
   CodeMirror.defineOption("hintOptions", null);
diff --git a/Frontend Angular 4/package-lock.json b/Frontend Angular 4/package-lock.json
index 0578b86d2c39f902b8c86734fc5535ee6935c1cf..f623d9f61342dd7cfa607ad722f14d1901dc18b3 100644
--- a/Frontend Angular 4/package-lock.json	
+++ b/Frontend Angular 4/package-lock.json	
@@ -95,20 +95,6 @@
           "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==",
           "dev": true
         },
-        "glob": {
-          "version": "7.1.4",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
-          "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
         "rxjs": {
           "version": "6.4.0",
           "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@@ -126,12 +112,6 @@
           "requires": {
             "chokidar": ">=2.0.0 <4.0.0"
           }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
         }
       }
     },
@@ -223,6 +203,14 @@
         }
       }
     },
+    "@angular/animations": {
+      "version": "8.2.14",
+      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.2.14.tgz",
+      "integrity": "sha512-3Vc9TnNpKdtvKIXcWDFINSsnwgEMiDmLzjceWg1iYKwpeZGQahUXPoesLwQazBMmxJzQiA4HOMj0TTXKZ+Jzkg==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "@angular/cli": {
       "version": "8.3.29",
       "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.29.tgz",
@@ -257,21 +245,6 @@
           "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
           "dev": true
         },
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
         "rimraf": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz",
@@ -280,12 +253,6 @@
           "requires": {
             "glob": "^7.1.3"
           }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
         }
       }
     },
@@ -711,25 +678,16 @@
         "source-map": "^0.5.0"
       },
       "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
         "json5": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
           "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
           "dev": true
         },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
           "dev": true
         },
         "source-map": {
@@ -795,15 +753,9 @@
           }
         },
         "caniuse-lite": {
-          "version": "1.0.30001414",
-          "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz",
-          "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==",
-          "dev": true
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "version": "1.0.30001416",
+          "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001416.tgz",
+          "integrity": "sha512-06wzzdAkCPZO+Qm4e/eNghZBDfVNDsCgw33T27OwBH9unE9S478OYw//Q2L7Npf/zBzs7rjZOszIFQkwQKAEqA==",
           "dev": true
         }
       }
@@ -1003,14 +955,6 @@
         "@babel/helper-validator-identifier": "^7.18.6",
         "chalk": "^2.0.0",
         "js-tokens": "^4.0.0"
-      },
-      "dependencies": {
-        "js-tokens": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-          "dev": true
-        }
       }
     },
     "@babel/parser": {
@@ -1548,6 +1492,14 @@
         "invariant": "^2.2.2",
         "levenary": "^1.1.1",
         "semver": "^5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "@babel/runtime": {
@@ -1594,23 +1546,6 @@
         "@babel/types": "^7.19.3",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "@babel/types": {
@@ -1772,9 +1707,9 @@
           }
         },
         "semver": {
-          "version": "7.3.7",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
-          "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+          "version": "7.3.8",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+          "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
           "dev": true,
           "requires": {
             "lru-cache": "^6.0.0"
@@ -1849,12 +1784,6 @@
           "requires": {
             "tslib": "^1.9.0"
           }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
         }
       }
     },
@@ -1865,9 +1794,9 @@
       "dev": true
     },
     "@stencil/core": {
-      "version": "2.18.0",
-      "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.18.0.tgz",
-      "integrity": "sha512-NLEY8Jq59smyiivBAxHKipsp9YkkW/K/Vm90zAyXQqukb12i2SFucWHJ1Ik7ropVlhmMVvigyxXgRfQ9quIqtg=="
+      "version": "2.19.2",
+      "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.19.2.tgz",
+      "integrity": "sha512-TK3sHqyQAACwcac4fWntypFtN9c/y+y9ioZojeCnNDY3dxF33Ax70lL9ZLDyQnWWR+aTh1WFoqB5sYOnZIUKMA=="
     },
     "@types/cookie": {
       "version": "0.4.1",
@@ -2355,13 +2284,10 @@
       "integrity": "sha512-shdaI1zT3CVNL2hnx9c0JMc0ZogGaxDs5e85akgHWKYa0yVbIyp06Ind3dVkTj/uuFrzaHBOyqFzo+VV6aXgtA=="
     },
     "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
-      "dev": true,
-      "requires": {
-        "array-uniq": "^1.0.1"
-      }
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true
     },
     "array-uniq": {
       "version": "1.0.3",
@@ -2699,6 +2625,21 @@
           "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
           "dev": true
         },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        },
         "qs": {
           "version": "6.10.3",
           "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
@@ -2943,31 +2884,6 @@
         "ssri": "^6.0.1",
         "unique-filename": "^1.1.1",
         "y18n": "^4.0.0"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "7.2.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-          "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.1.1",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
-        "minimatch": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-          "dev": true,
-          "requires": {
-            "brace-expansion": "^1.1.7"
-          }
-        }
       }
     },
     "cache-base": {
@@ -3054,17 +2970,6 @@
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
         "supports-color": "^5.3.0"
-      },
-      "dependencies": {
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        }
       }
     },
     "chardet": {
@@ -3349,6 +3254,23 @@
         "on-headers": "~1.0.2",
         "safe-buffer": "5.1.2",
         "vary": "~1.1.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        }
       }
     },
     "concat-map": {
@@ -3381,6 +3303,15 @@
         "utils-merge": "1.0.1"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "finalhandler": {
           "version": "1.1.2",
           "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@@ -3396,6 +3327,12 @@
             "unpipe": "~1.0.0"
           }
         },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        },
         "on-finished": {
           "version": "2.3.0",
           "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -3563,20 +3500,6 @@
             "pkg-dir": "^4.1.0"
           }
         },
-        "glob": {
-          "version": "7.2.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-          "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.1.1",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
         "json5": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
@@ -3603,24 +3526,6 @@
             "yallist": "^4.0.0"
           }
         },
-        "make-dir": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-          "dev": true,
-          "requires": {
-            "semver": "^6.0.0"
-          }
-        },
-        "minimatch": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-          "dev": true,
-          "requires": {
-            "brace-expansion": "^1.1.7"
-          }
-        },
         "mkdirp": {
           "version": "1.0.4",
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -3645,12 +3550,6 @@
             "glob": "^7.1.3"
           }
         },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
-        },
         "ssri": {
           "version": "8.0.1",
           "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
@@ -3674,9 +3573,9 @@
       "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
     },
     "core-js-compat": {
-      "version": "3.25.4",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.4.tgz",
-      "integrity": "sha512-gCEcIEEqCR6230WroNunK/653CWKhqyCKJ9b+uESqOt/WFJA8B4lTnnQFdpYY5vmBcwJAA90Bo5vXs+CVsf6iA==",
+      "version": "3.25.5",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.5.tgz",
+      "integrity": "sha512-ovcyhs2DEBUIE0MGEKHP4olCUW/XYte3Vroyxuh38rD1wAO4dHohsovUC4eAOuzFxE6b+RXvBU3UZ9o0YhUTkA==",
       "dev": true,
       "requires": {
         "browserslist": "^4.21.4"
@@ -3695,9 +3594,9 @@
           }
         },
         "caniuse-lite": {
-          "version": "1.0.30001414",
-          "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz",
-          "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==",
+          "version": "1.0.30001416",
+          "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001416.tgz",
+          "integrity": "sha512-06wzzdAkCPZO+Qm4e/eNghZBDfVNDsCgw33T27OwBH9unE9S478OYw//Q2L7Npf/zBzs7rjZOszIFQkwQKAEqA==",
           "dev": true
         }
       }
@@ -3728,18 +3627,6 @@
         "is-directory": "^0.3.1",
         "js-yaml": "^3.13.1",
         "parse-json": "^4.0.0"
-      },
-      "dependencies": {
-        "parse-json": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-          "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
-          "dev": true,
-          "requires": {
-            "error-ex": "^1.3.1",
-            "json-parse-better-errors": "^1.0.1"
-          }
-        }
       }
     },
     "coverage-istanbul-loader": {
@@ -3811,6 +3698,14 @@
         "semver": "^5.5.0",
         "shebang-command": "^1.2.0",
         "which": "^1.2.9"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "crypto-browserify": {
@@ -4152,12 +4047,12 @@
       "dev": true
     },
     "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "requires": {
-        "ms": "2.0.0"
+        "ms": "2.1.2"
       }
     },
     "debuglog": {
@@ -4273,6 +4168,15 @@
         "rimraf": "^2.6.3"
       },
       "dependencies": {
+        "array-union": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+          "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+          "dev": true,
+          "requires": {
+            "array-uniq": "^1.0.1"
+          }
+        },
         "globby": {
           "version": "6.1.0",
           "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
@@ -4294,30 +4198,6 @@
             }
           }
         },
-        "is-path-cwd": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
-          "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
-          "dev": true
-        },
-        "is-path-in-cwd": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
-          "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
-          "dev": true,
-          "requires": {
-            "is-path-inside": "^2.1.0"
-          }
-        },
-        "is-path-inside": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
-          "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
-          "dev": true,
-          "requires": {
-            "path-is-inside": "^1.0.2"
-          }
-        },
         "p-map": {
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
@@ -4493,9 +4373,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.4.270",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz",
-      "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==",
+      "version": "1.4.274",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.274.tgz",
+      "integrity": "sha512-Fgn7JZQzq85I81FpKUNxVLAzoghy8JZJ4NIue+YfUYBbu1AkpgzFvNwzF/ZNZH9ElkmJD0TSWu1F2gTpw/zZlg==",
       "dev": true
     },
     "elliptic": {
@@ -4522,9 +4402,9 @@
       }
     },
     "emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
       "dev": true
     },
     "emojis-list": {
@@ -4587,9 +4467,9 @@
       },
       "dependencies": {
         "@types/node": {
-          "version": "18.8.0",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.0.tgz",
-          "integrity": "sha512-u+h43R6U8xXDt2vzUaVP3VwjjLyOJk6uEciZS8OSyziUQGOwmk+l+4drxcsDboHXwyTaqS1INebghmWMRxq3LA==",
+          "version": "18.8.2",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.2.tgz",
+          "integrity": "sha512-cRMwIgdDN43GO4xMWAfJAecYn8wV4JbsOGHNfNUIDiuYkUYAR5ec4Rj7IO2SAhFPEfpPtLtUTbbny/TCT7aDwA==",
           "dev": true
         },
         "cookie": {
@@ -4598,19 +4478,10 @@
           "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
           "dev": true
         },
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+        "ws": {
+          "version": "8.2.3",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
+          "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
           "dev": true
         }
       }
@@ -4853,6 +4724,15 @@
         "to-regex": "^3.0.1"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -4870,6 +4750,12 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
         }
       }
     },
@@ -4918,6 +4804,21 @@
           "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
           "dev": true
         },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        },
         "qs": {
           "version": "6.10.3",
           "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
@@ -4970,17 +4871,6 @@
         "chardet": "^0.7.0",
         "iconv-lite": "^0.4.24",
         "tmp": "^0.0.33"
-      },
-      "dependencies": {
-        "tmp": {
-          "version": "0.0.33",
-          "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-          "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
-          "dev": true,
-          "requires": {
-            "os-tmpdir": "~1.0.2"
-          }
-        }
       }
     },
     "extglob": {
@@ -5150,8 +5040,25 @@
         "parseurl": "~1.3.3",
         "statuses": "2.0.1",
         "unpipe": "~1.0.0"
-      }
-    },
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        }
+      }
+    },
     "find-cache-dir": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz",
@@ -5161,23 +5068,6 @@
         "commondir": "^1.0.1",
         "make-dir": "^3.0.0",
         "pkg-dir": "^4.1.0"
-      },
-      "dependencies": {
-        "make-dir": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-          "dev": true,
-          "requires": {
-            "semver": "^6.0.0"
-          }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
-        }
       }
     },
     "find-up": {
@@ -5426,9 +5316,9 @@
       }
     },
     "glob": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "version": "7.1.4",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+      "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
@@ -5466,14 +5356,6 @@
         "ignore": "^5.2.0",
         "merge2": "^1.4.1",
         "slash": "^3.0.0"
-      },
-      "dependencies": {
-        "array-union": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-          "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-          "dev": true
-        }
       }
     },
     "graceful-fs": {
@@ -6455,26 +6337,6 @@
       "requires": {
         "ajv": "^6.12.3",
         "har-schema": "^2.0.0"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "6.12.6",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-          "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-          "dev": true,
-          "requires": {
-            "fast-deep-equal": "^3.1.1",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.4.1",
-            "uri-js": "^4.2.2"
-          }
-        },
-        "fast-deep-equal": {
-          "version": "3.1.3",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-          "dev": true
-        }
       }
     },
     "has": {
@@ -6718,6 +6580,12 @@
           "requires": {
             "ms": "2.0.0"
           }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
         }
       }
     },
@@ -6873,12 +6741,6 @@
           "requires": {
             "ms": "^2.1.1"
           }
-        },
-        "ms": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-          "dev": true
         }
       }
     },
@@ -7055,6 +6917,12 @@
           "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
           "dev": true
         },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+          "dev": true
+        },
         "is-fullwidth-code-point": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -7134,9 +7002,9 @@
       }
     },
     "interval-arithmetic": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/interval-arithmetic/-/interval-arithmetic-1.1.0.tgz",
-      "integrity": "sha512-NyKZf/l4wAKB/Z7bURh0TNdiZycKQSEQ1VrPkcaZK8Lrn6X+ZHDqXDTPjYezhYC0Cubrj0qUatomUu4xte26nw==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/interval-arithmetic/-/interval-arithmetic-1.1.2.tgz",
+      "integrity": "sha512-FmonKqVk5HVc4G79d16rQmCb6zOwv0o4LidhJKtdGTwpc3Kk9UZ5t6UE1AQHFF5RdQaSIQs0AYe5rySFT8C1Ww==",
       "requires": {
         "nextafter": "^1.0.0"
       }
@@ -7403,27 +7271,27 @@
       "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA=="
     },
     "is-path-cwd": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
-      "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
+      "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
       "dev": true
     },
     "is-path-in-cwd": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
-      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
+      "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
       "dev": true,
       "requires": {
-        "is-path-inside": "^1.0.0"
+        "is-path-inside": "^2.1.0"
       }
     },
     "is-path-inside": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-      "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
+      "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
       "dev": true,
       "requires": {
-        "path-is-inside": "^1.0.1"
+        "path-is-inside": "^1.0.2"
       }
     },
     "is-plain-obj": {
@@ -7563,14 +7431,6 @@
         "@istanbuljs/schema": "^0.1.2",
         "istanbul-lib-coverage": "^3.0.0",
         "semver": "^6.3.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
-        }
       }
     },
     "istanbul-lib-report": {
@@ -7590,27 +7450,6 @@
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "istanbul-lib-coverage": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
-          "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
-          "dev": true
-        },
-        "make-dir": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-          "dev": true,
-          "requires": {
-            "semver": "^6.0.0"
-          }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
-        },
         "supports-color": {
           "version": "7.2.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -7635,25 +7474,26 @@
         "source-map": "^0.6.1"
       },
       "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
         "istanbul-lib-coverage": {
           "version": "2.0.5",
           "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
           "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
           "dev": true
         },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
           "dev": true
         },
         "source-map": {
@@ -7722,6 +7562,17 @@
       "requires": {
         "merge-stream": "^2.0.0",
         "supports-color": "^6.1.0"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
       }
     },
     "jq-console": {
@@ -7881,47 +7732,6 @@
             "color-convert": "^2.0.1"
           }
         },
-        "anymatch": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
-          "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-          "dev": true,
-          "requires": {
-            "normalize-path": "^3.0.0",
-            "picomatch": "^2.0.4"
-          }
-        },
-        "binary-extensions": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-          "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-          "dev": true
-        },
-        "braces": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-          "dev": true,
-          "requires": {
-            "fill-range": "^7.0.1"
-          }
-        },
-        "chokidar": {
-          "version": "3.5.3",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-          "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-          "dev": true,
-          "requires": {
-            "anymatch": "~3.1.2",
-            "braces": "~3.0.2",
-            "fsevents": "~2.3.2",
-            "glob-parent": "~5.1.2",
-            "is-binary-path": "~2.1.0",
-            "is-glob": "~4.0.1",
-            "normalize-path": "~3.0.0",
-            "readdirp": "~3.6.0"
-          }
-        },
         "cliui": {
           "version": "7.0.4",
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -7948,26 +7758,10 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "fill-range": {
-          "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-          "dev": true,
-          "requires": {
-            "to-regex-range": "^5.0.1"
-          }
-        },
-        "fsevents": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-          "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-          "dev": true,
-          "optional": true
-        },
-        "get-caller-file": {
-          "version": "2.0.5",
-          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
           "dev": true
         },
         "glob": {
@@ -7995,57 +7789,18 @@
             }
           }
         },
-        "glob-parent": {
-          "version": "5.1.2",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-          "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-          "dev": true,
-          "requires": {
-            "is-glob": "^4.0.1"
-          }
-        },
-        "is-binary-path": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-          "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-          "dev": true,
-          "requires": {
-            "binary-extensions": "^2.0.0"
-          }
-        },
         "is-fullwidth-code-point": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
           "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
           "dev": true
         },
-        "is-number": {
-          "version": "7.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-          "dev": true
-        },
         "mime": {
           "version": "2.6.0",
           "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
           "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
           "dev": true
         },
-        "normalize-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-          "dev": true
-        },
-        "readdirp": {
-          "version": "3.6.0",
-          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-          "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-          "dev": true,
-          "requires": {
-            "picomatch": "^2.2.1"
-          }
-        },
         "rimraf": {
           "version": "3.0.2",
           "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -8081,13 +7836,13 @@
             "ansi-regex": "^5.0.1"
           }
         },
-        "to-regex-range": {
-          "version": "5.0.1",
-          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+        "tmp": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+          "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
           "dev": true,
           "requires": {
-            "is-number": "^7.0.0"
+            "rimraf": "^3.0.0"
           }
         },
         "wrap-ansi": {
@@ -8159,14 +7914,6 @@
         "istanbul-lib-source-maps": "^3.0.6",
         "istanbul-reports": "^3.0.2",
         "minimatch": "^3.0.4"
-      },
-      "dependencies": {
-        "istanbul-lib-coverage": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
-          "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
-          "dev": true
-        }
       }
     },
     "karma-jasmine": {
@@ -8358,23 +8105,6 @@
         "flatted": "^3.2.7",
         "rfdc": "^1.3.0",
         "streamroller": "^3.1.3"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "loglevel": {
@@ -8409,6 +8139,35 @@
         "yallist": "^3.0.2"
       }
     },
+    "lt-codemirror": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/lt-codemirror/-/lt-codemirror-5.0.0.tgz",
+      "integrity": "sha512-vJN4pUx3lWfyYpfPx1LAl216EAjiXT1s2mV7qAzn9y+1/gkHF6iOao6dReBd3/SXF8cVTq+YAgbo9sUxhSumWg==",
+      "requires": {
+        "@angular/animations": "~8.2.14",
+        "@angular/common": "~8.2.14",
+        "@angular/compiler": "~8.2.14",
+        "@angular/core": "~8.2.14",
+        "@angular/forms": "~8.2.14",
+        "@angular/platform-browser": "~8.2.14",
+        "@angular/platform-browser-dynamic": "~8.2.14",
+        "@angular/router": "~8.2.14",
+        "codemirror": "^5.56.0",
+        "rxjs": "~6.4.0",
+        "tslib": "^1.10.0",
+        "zone.js": "~0.9.1"
+      },
+      "dependencies": {
+        "rxjs": {
+          "version": "6.4.0",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+          "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+          "requires": {
+            "tslib": "^1.9.0"
+          }
+        }
+      }
+    },
     "magic-string": {
       "version": "0.25.3",
       "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
@@ -8419,13 +8178,12 @@
       }
     },
     "make-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
-      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
       "dev": true,
       "requires": {
-        "pify": "^4.0.1",
-        "semver": "^5.6.0"
+        "semver": "^6.0.0"
       }
     },
     "make-error": {
@@ -8484,9 +8242,9 @@
       }
     },
     "matefun-components": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/matefun-components/-/matefun-components-0.1.0.tgz",
-      "integrity": "sha512-KVrXcO2qWjSkKGbb552THGRBqIHsJ6Ap0MAOFAT/PSxbOTyoyQBqyc1SMG6g5JE0nYiYGBNETYg/KI99SWuzHQ==",
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/matefun-components/-/matefun-components-0.3.0.tgz",
+      "integrity": "sha512-Bs9rbDQLn2woI08tSjGyEDGIQ3clYq0zjXvmlq4W8r0SZaTKQPk7pP88kwc+ud/z7Z2fTfHxkhZLX7OD/7BRuw==",
       "requires": {
         "@stencil/core": "^2.13.0"
       }
@@ -8824,9 +8582,9 @@
       "integrity": "sha512-hug+mpbSSKnH13rFqy3zm+XiG+QTStiDAgMTHK355TIstQE0qBkBtSJsa5YHP94AuarVX9b/4dcebdTRZ9YiEw=="
     },
     "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
       "dev": true
     },
     "multicast-dns": {
@@ -8890,19 +8648,6 @@
         "double-bits": "^1.1.0"
       }
     },
-    "ng2-bootstrap-modal": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/ng2-bootstrap-modal/-/ng2-bootstrap-modal-1.0.1.tgz",
-      "integrity": "sha512-F/NABjMJtmhSfgLIJmGdpgBeU13jPwAw7+mtcKBUFQ38zXY3Ydq/vzjprQ3zJFWIcSwckbEOF4b/7AvSJcRbzA=="
-    },
-    "ng2-codemirror": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/ng2-codemirror/-/ng2-codemirror-1.1.3.tgz",
-      "integrity": "sha512-aqBTOTCo1poOMKxh1hil4ehCN7NgnaxGKG0Hu6Mwe9ya7yN3SQpPUCznw0kWBdN8ir1esbn13vh8y1bSewim4A==",
-      "requires": {
-        "codemirror": "^5.22.2"
-      }
-    },
     "ng2-slideable-directive": {
       "version": "1.0.13",
       "resolved": "https://registry.npmjs.org/ng2-slideable-directive/-/ng2-slideable-directive-1.0.13.tgz",
@@ -9003,6 +8748,14 @@
         "resolve": "^1.10.0",
         "semver": "2 || 3 || 4 || 5",
         "validate-npm-package-license": "^3.0.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "normalize-path": {
@@ -9054,6 +8807,14 @@
         "osenv": "^0.1.5",
         "semver": "^5.5.0",
         "validate-npm-package-name": "^3.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "npm-packlist": {
@@ -9076,6 +8837,14 @@
         "figgy-pudding": "^3.5.1",
         "npm-package-arg": "^6.0.0",
         "semver": "^5.4.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "npm-registry-fetch": {
@@ -9484,6 +9253,12 @@
             "semver": "^5.4.1"
           }
         },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "tar": {
           "version": "4.4.19",
           "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz",
@@ -9540,12 +9315,13 @@
       }
     },
     "parse-json": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-      "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
       "dev": true,
       "requires": {
-        "error-ex": "^1.2.0"
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
       }
     },
     "parse5": {
@@ -9750,12 +9526,6 @@
           "requires": {
             "ms": "^2.1.1"
           }
-        },
-        "ms": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-          "dev": true
         }
       }
     },
@@ -9781,6 +9551,15 @@
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
           "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
           "dev": true
+        },
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
         }
       }
     },
@@ -9935,6 +9714,15 @@
           "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
           "dev": true
         },
+        "array-union": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+          "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+          "dev": true,
+          "requires": {
+            "array-uniq": "^1.0.1"
+          }
+        },
         "chalk": {
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -9977,12 +9765,42 @@
             "pinkie-promise": "^2.0.0"
           }
         },
-        "pify": {
+        "is-path-cwd": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+          "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==",
+          "dev": true
+        },
+        "is-path-in-cwd": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+          "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+          "dev": true,
+          "requires": {
+            "is-path-inside": "^1.0.0"
+          }
+        },
+        "is-path-inside": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+          "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==",
+          "dev": true,
+          "requires": {
+            "path-is-inside": "^1.0.1"
+          }
+        },
+        "pify": {
           "version": "2.3.0",
           "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
           "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
           "dev": true
         },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -10611,113 +10429,6 @@
         "chokidar": ">=3.0.0 <4.0.0",
         "immutable": "^4.0.0",
         "source-map-js": ">=0.6.2 <2.0.0"
-      },
-      "dependencies": {
-        "anymatch": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
-          "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-          "dev": true,
-          "requires": {
-            "normalize-path": "^3.0.0",
-            "picomatch": "^2.0.4"
-          }
-        },
-        "binary-extensions": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-          "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-          "dev": true
-        },
-        "braces": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-          "dev": true,
-          "requires": {
-            "fill-range": "^7.0.1"
-          }
-        },
-        "chokidar": {
-          "version": "3.5.3",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-          "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-          "dev": true,
-          "requires": {
-            "anymatch": "~3.1.2",
-            "braces": "~3.0.2",
-            "fsevents": "~2.3.2",
-            "glob-parent": "~5.1.2",
-            "is-binary-path": "~2.1.0",
-            "is-glob": "~4.0.1",
-            "normalize-path": "~3.0.0",
-            "readdirp": "~3.6.0"
-          }
-        },
-        "fill-range": {
-          "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-          "dev": true,
-          "requires": {
-            "to-regex-range": "^5.0.1"
-          }
-        },
-        "fsevents": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-          "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-          "dev": true,
-          "optional": true
-        },
-        "glob-parent": {
-          "version": "5.1.2",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-          "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-          "dev": true,
-          "requires": {
-            "is-glob": "^4.0.1"
-          }
-        },
-        "is-binary-path": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-          "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-          "dev": true,
-          "requires": {
-            "binary-extensions": "^2.0.0"
-          }
-        },
-        "is-number": {
-          "version": "7.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-          "dev": true
-        },
-        "normalize-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-          "dev": true
-        },
-        "readdirp": {
-          "version": "3.6.0",
-          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-          "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-          "dev": true,
-          "requires": {
-            "picomatch": "^2.2.1"
-          }
-        },
-        "to-regex-range": {
-          "version": "5.0.1",
-          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-          "dev": true,
-          "requires": {
-            "is-number": "^7.0.0"
-          }
-        }
       }
     },
     "sass-loader": {
@@ -10731,6 +10442,14 @@
         "neo-async": "^2.5.0",
         "pify": "^4.0.1",
         "semver": "^5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "saucelabs": {
@@ -10752,6 +10471,15 @@
             "semver": "~5.0.1"
           }
         },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "https-proxy-agent": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
@@ -10763,6 +10491,12 @@
             "extend": "3"
           }
         },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        },
         "semver": {
           "version": "5.0.3",
           "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
@@ -10841,9 +10575,9 @@
       }
     },
     "semver": {
-      "version": "5.6.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
-      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
       "dev": true
     },
     "semver-dsl": {
@@ -10853,6 +10587,14 @@
       "dev": true,
       "requires": {
         "semver": "^5.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "semver-intersect": {
@@ -10862,6 +10604,14 @@
       "dev": true,
       "requires": {
         "semver": "^5.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
       }
     },
     "send": {
@@ -10885,6 +10635,23 @@
         "statuses": "2.0.1"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+              "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+              "dev": true
+            }
+          }
+        },
         "ms": {
           "version": "2.1.3",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -10917,6 +10684,15 @@
         "parseurl": "~1.3.2"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "depd": {
           "version": "1.1.2",
           "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -10941,6 +10717,12 @@
           "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
           "dev": true
         },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        },
         "setprototypeof": {
           "version": "1.1.0",
           "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
@@ -11087,6 +10869,15 @@
         "use": "^3.1.0"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -11105,6 +10896,12 @@
             "is-extendable": "^0.1.0"
           }
         },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -11196,23 +10993,6 @@
         "engine.io": "~6.2.0",
         "socket.io-adapter": "~2.4.0",
         "socket.io-parser": "~4.2.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "socket.io-adapter": {
@@ -11229,23 +11009,6 @@
       "requires": {
         "@socket.io/component-emitter": "~3.1.0",
         "debug": "~4.3.1"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "sockjs": {
@@ -11290,12 +11053,6 @@
           "requires": {
             "websocket-driver": ">=0.5.1"
           }
-        },
-        "ms": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-          "dev": true
         }
       }
     },
@@ -11461,23 +11218,6 @@
         "http-deceiver": "^1.2.7",
         "select-hose": "^2.0.0",
         "spdy-transport": "^3.0.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "spdy-transport": {
@@ -11494,21 +11234,6 @@
         "wbuf": "^1.7.3"
       },
       "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
         "readable-stream": {
           "version": "3.6.0",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@@ -11647,23 +11372,6 @@
         "date-format": "^4.0.14",
         "debug": "^4.3.4",
         "fs-extra": "^8.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "strict-uri-encode": {
@@ -11689,12 +11397,6 @@
           "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
           "dev": true
         },
-        "emoji-regex": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-          "dev": true
-        },
         "strip-ansi": {
           "version": "5.2.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
@@ -11828,9 +11530,9 @@
       }
     },
     "supports-color": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-      "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
       "dev": true,
       "requires": {
         "has-flag": "^3.0.0"
@@ -11967,20 +11669,6 @@
             "pkg-dir": "^4.1.0"
           }
         },
-        "glob": {
-          "version": "7.2.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-          "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.1.1",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -12007,24 +11695,6 @@
             "yallist": "^4.0.0"
           }
         },
-        "make-dir": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-          "dev": true,
-          "requires": {
-            "semver": "^6.0.0"
-          }
-        },
-        "minimatch": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-          "dev": true,
-          "requires": {
-            "brace-expansion": "^1.1.7"
-          }
-        },
         "mkdirp": {
           "version": "1.0.4",
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -12040,12 +11710,6 @@
             "glob": "^7.1.3"
           }
         },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
-        },
         "serialize-javascript": {
           "version": "3.1.0",
           "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
@@ -12138,23 +11802,12 @@
       }
     },
     "tmp": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
-      "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
       "dev": true,
       "requires": {
-        "rimraf": "^3.0.0"
-      },
-      "dependencies": {
-        "rimraf": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        }
+        "os-tmpdir": "~1.0.2"
       }
     },
     "to-arraybuffer": {
@@ -12304,6 +11957,17 @@
         "parse-json": "^2.2.0",
         "strip-bom": "^2.0.0",
         "strip-json-comments": "^2.0.0"
+      },
+      "dependencies": {
+        "parse-json": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+          "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.2.0"
+          }
+        }
       }
     },
     "tslib": {
@@ -12337,6 +12001,12 @@
           "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
           "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
           "dev": true
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
         }
       }
     },
@@ -12489,23 +12159,6 @@
         "debug": "^4.1.1",
         "request": "^2.88.2",
         "uuid": "^3.0.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
       }
     },
     "universalify": {
@@ -12567,9 +12220,9 @@
       "dev": true
     },
     "update-browserslist-db": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz",
-      "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==",
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
+      "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
       "dev": true,
       "requires": {
         "escalade": "^3.1.1",
@@ -13174,6 +12827,16 @@
             }
           }
         },
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
         "micromatch": {
           "version": "3.1.10",
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -13215,6 +12878,12 @@
             "ajv-keywords": "^3.1.0"
           }
         },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -13415,15 +13084,6 @@
             "upath": "^1.1.1"
           }
         },
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
         "fill-range": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -13525,12 +13185,6 @@
             "to-regex": "^3.0.2"
           }
         },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
         "readdirp": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
@@ -13553,11 +13207,14 @@
             "ajv-keywords": "^3.1.0"
           }
         },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
         },
         "to-regex-range": {
           "version": "2.1.1",
@@ -13568,15 +13225,6 @@
             "is-number": "^3.0.0",
             "repeat-string": "^1.6.1"
           }
-        },
-        "ws": {
-          "version": "6.2.2",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
-          "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
-          "dev": true,
-          "requires": {
-            "async-limiter": "~1.0.0"
-          }
         }
       }
     },
@@ -13734,10 +13382,13 @@
       "dev": true
     },
     "ws": {
-      "version": "8.2.3",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
-      "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
-      "dev": true
+      "version": "6.2.2",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
+      "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
+      "dev": true,
+      "requires": {
+        "async-limiter": "~1.0.0"
+      }
     },
     "xml2js": {
       "version": "0.4.23",
diff --git a/Frontend Angular 4/package.json b/Frontend Angular 4/package.json
index 5ee6f950b2870e9cfcc72d2306090e9db147d739..629bb658e8dd669bf923343f9404beb3c789cd1b 100755
--- a/Frontend Angular 4/package.json	
+++ b/Frontend Angular 4/package.json	
@@ -22,6 +22,7 @@
     "@ng-bootstrap/ng-bootstrap": "^5.3.1",
     "@ngx-translate/core": "^12.0.0",
     "@ngx-translate/http-loader": "^4.0.0",
+    "codemirror": "^5.65.9",
     "core-js": "^2.4.1",
     "d3": "^4.12.2",
     "flag-icon-css": "^3.2.1",
@@ -31,10 +32,9 @@
     "ionicons": "^3.0.0",
     "jq-console": "^2.13.2",
     "jquery": "^3.2.1",
-    "matefun-components": "0.1.0",
+    "lt-codemirror": "^5.0.0",
+    "matefun-components": "^0.3.0",
     "mathjs": "1.6.0",
-    "ng2-bootstrap-modal": "^1.0.1",
-    "ng2-codemirror": "^1.1.1",
     "ng2-slider-component": "^1.0.9",
     "rxjs": "6.6.7",
     "tippy.js": "^1.2.0",
diff --git a/Frontend Angular 4/src/app/layout/archivos/archivos.component.html b/Frontend Angular 4/src/app/layout/archivos/archivos.component.html
index 850e4f1a1a54fa5454fe9c24c916e3028b5240aa..81fac87495999caa817b20d7aaf43bfb9e435fcd 100755
--- a/Frontend Angular 4/src/app/layout/archivos/archivos.component.html	
+++ b/Frontend Angular 4/src/app/layout/archivos/archivos.component.html	
@@ -70,11 +70,11 @@
                     <i class="fa fa-plus"></i>
                   </button>
                   <div class="dropdown-menu">
-                    <a class="dropdown-item" (click)="mkFile()">
+                    <a class="dropdown-item" (click)="mkFile(true)">
                       {{ "i18n.object.file" | translate | titleCase }}
                     </a>
                     <div class="dropdown-divider"></div>
-                    <a class="dropdown-item" (click)="mkdir()">
+                    <a class="dropdown-item" (click)="mkFile(false)">
                       {{ "i18n.object.folder" | translate | titleCase }}
                     </a>
                   </div>
@@ -133,22 +133,19 @@
                         | filter: 'nombre':filtroNombre
                     "
                     (click)="seleccionarArchivo(arch)"
-                    class="col-sm-3 col-4"
-                    style="text-align: center"
+                    class="col-sm-3 col-4 matefun-file-wrapper"
                   >
                     <i
                       *ngIf="arch.directorio"
-                      class="fa fa-folder"
-                      style="font-size: 3em; cursor: pointer; color: #f95e5e"
+                      class="fa fa-folder matefun-fa-folder"
                       aria-hidden="true"
                     ></i>
                     <i
                       *ngIf="!arch.directorio"
-                      class="fa fa-file-text"
-                      style="font-size: 3em; cursor: pointer; color: #ff8383"
+                      class="fa fa-file-text matefun-fa-file"
                       aria-hidden="true"
                     ></i>
-                    <p style="cursor: pointer">{{ arch.nombre }}</p>
+                    <p class="matefun-p">{{ arch.nombre }}</p>
                   </div>
                 </div>
               </div>
@@ -215,8 +212,7 @@
                         | filter: 'nombre':filtroNombre
                     "
                     (click)="seleccionarArchivo(arch)"
-                    class="col-sm-3 col-4"
-                    style="text-align: center"
+                    class="col-sm-3 col-4 matefun-file-wrapper"
                   >
                     <i
                       class="fa fa-file-text"
@@ -293,7 +289,7 @@
             "
             (click)="confirmarEntrega()"
           >
-            {{ "i18n.action.send" | translate }}
+            {{ "i18n.action.send" | translate | titleCase }}
           </button>
 
           <div
@@ -366,15 +362,118 @@
             ></i>
           </div>
         </div>
-        <codemirror
+        <lt-codemirror
           class="codemirrorArchivo"
           *ngIf="archivoSeleccionado"
           [(ngModel)]="preview"
           [config]="configCodeMirror"
           [ngStyle]="{ 'font-size': configCodeMirror.fontSize + 'px' }"
         >
-        </codemirror>
+        </lt-codemirror>
       </div>
     </div>
   </div>
 </div>
+<matefun-modal-nuevo-archivo
+  confirmLabel="{{ 'i18n.action.create' | translate | titleCase }}"
+  fileDescriptionLabel="{{ 'i18n.object.descr' | translate | titleCase }}:"
+  fileNameLabel="{{ 'i18n.object.name' | translate | titleCase }}:"
+  header="{{ 'i18n.action.new' | translate | titleCase }} 
+  {{
+    (modalTypeIsFile ? 'i18n.object.file' : 'i18n.object.folder')
+      | translate
+      | titleCase
+  }} "
+  [opened]="modalCreateFileOpened"
+  [typeOfFile]="modalTypeIsFile ? 'file' : 'directory'"
+  (close)="modalCreateFile = false"
+  (confirmFileCreation)="confirmFileCreation($event)"
+  *ngIf="modalCreateFile"
+>
+</matefun-modal-nuevo-archivo>
+
+<matefun-modal-seleccionar-directorio
+  confirmLabel="{{ 'i18n.action.move' | translate | titleCase }} {{
+    'i18n.object.here' | translate
+  }}"
+  [currentDirectory]="currentDirOfFileToMove"
+  [fileIdToMove]="archivoSeleccionado ? archivoSeleccionado.id : -1"
+  fileNameLabel="{{ 'i18n.object.name' | translate | titleCase }}"
+  header="{{ 'i18n.msg.file.move' | translate }}"
+  [initialPath]="currentPath"
+  navigateBackLabel="{{ 'i18n.action.goBack' | translate | titleCase }}"
+  [opened]="modalMoveFileOpened"
+  type-of-modal="move"
+  (close)="modalMoveFile = false"
+  (confirmFileCreation)="confirmFileMove($event)"
+  (navBack)="navigateBackModal($event)"
+  (navTo)="currentDirOfFileToMove = $event.detail"
+  *ngIf="modalMoveFile"
+>
+</matefun-modal-seleccionar-directorio>
+
+<matefun-modal-borrar-archivo
+  bodyDescription="{{ 'i18n.msg.file.delete' | translate: fileNameToRemove }}"
+  cancelLabel="{{ 'i18n.action.cancel' | translate | titleCase }}"
+  confirmLabel="{{ 'i18n.action.delete' | translate | titleCase }}"
+  header="{{ 'i18n.action.delete' | translate | titleCase }} 
+  {{
+    (modalTypeIsFile ? 'i18n.object.file' : 'i18n.object.folder')
+      | translate
+      | titleCase
+  }}"
+  [opened]="modalRemoveFileOpened"
+  [typeOfFile]="modalTypeIsFile ? 'file' : 'directory'"
+  (close)="modalRemoveFile = false"
+  (cancelAction)="modalRemoveFileOpened = false"
+  (removeFile)="confirmFileDeletion()"
+  *ngIf="modalRemoveFile"
+>
+</matefun-modal-borrar-archivo>
+
+<matefun-modal-compartir-archivo
+  confirmLabel="{{ 'i18n.action.share' | translate | titleCase }}"
+  [groups]="groupsToShareFile"
+  header="{{ 'i18n.msg.file.share' | translate: fileNameToShare }}"
+  [opened]="modalShareFileOpened"
+  (close)="modalShareFile = false"
+  (confirmFileShare)="confirmFileShare($event)"
+  *ngIf="modalShareFile"
+>
+</matefun-modal-compartir-archivo>
+
+<matefun-modal-enviar-archivo
+  bodyDescriptionTop="{{
+    'i18n.msg.file.toSend' | translate: { fileName: archivoSeleccionado.nombre }
+  }}"
+  bodyDescriptionBottom="{{ 'i18n.msg.file.toSendInfo' | translate }}"
+  cancelLabel="{{ 'i18n.action.cancel' | translate | titleCase }}"
+  confirmLabel="{{ 'i18n.action.confirm' | translate | titleCase }}"
+  header="{{ 'i18n.action.send' | translate | titleCase }} {{
+    'i18n.object.file' | translate | titleCase
+  }}"
+  [opened]="modalSendFileOpened"
+  (cancelAction)="modalSendFileOpened = false"
+  (close)="modalSendFile = false"
+  (confirmFileSend)="entregarArchivo()"
+  *ngIf="modalSendFile"
+>
+</matefun-modal-enviar-archivo>
+
+<matefun-modal-ver-calificacion
+  detail=" {{ archivoSeleccionado.evaluacion.descripcion }}"
+  detailLabel="{{ 'i18n.object.detail' | translate | titleCase }}: "
+  date=" {{ archivoSeleccionado.evaluacion.fecha | date }}"
+  dateLabel="{{ 'i18n.object.date' | translate | titleCase }}: "
+  confirmLabel="{{ 'i18n.action.close' | translate | titleCase }}"
+  header="{{ 'i18n.object.qualification' | translate | titleCase }} &quot;{{
+    archivoSeleccionado.nombre
+  }}&quot;:"
+  [opened]="modalSeeScoreOpened"
+  score=" {{ archivoSeleccionado.evaluacion.nota }}"
+  scoreLabel="{{ 'i18n.object.score' | translate | titleCase }} (0-100): "
+  (close)="modalSeeScore = false"
+  (confirmClose)="modalSeeScoreOpened = false"
+  *ngIf="modalSeeScore"
+>
+</matefun-modal-ver-calificacion>
diff --git a/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts b/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts
index 186cbbfb7855a824cd71ab59c042a8492d5d621c..94229216a1bb2f3008f7693f92b014ccc1bb5a08 100755
--- a/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts	
+++ b/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts	
@@ -1,22 +1,14 @@
 import { Component, ViewChild } from "@angular/core";
-import { Archivo } from "../../shared/objects/archivo";
+import { Archivo, Grupo } from "../../shared/objects/archivo";
 import { AuthenticationService } from "../../shared/services/authentication.service";
 import { HaskellService } from "../../shared/services/haskell.service";
 import { SessionService } from "../../shared/services/session.service";
 import { NotificacionService } from "../../shared/services/notificacion.service";
 import { Router, ActivatedRoute } from "@angular/router";
-import { NuevoArchivo } from "./nuevoArchivo.component";
-import { VerCalificacionComponent } from "./verCalificacion.component";
-import { CompartirArchivoComponent } from "./compartirArchivo.component";
-import { ConfirmarEliminar } from "./confirmarEliminar.component";
-import { DialogService } from "ng2-bootstrap-modal";
-import { ConfirmComponent } from "../../shared/modal/confirm.component";
-import { SeleccionarDirectorioMove } from "./seleccionarDirectorio.component";
-import { CodemirrorComponent } from "ng2-codemirror";
+import { LtCodemirrorComponent } from "lt-codemirror";
 import { NgbPopoverConfig, NgbPopover } from "@ng-bootstrap/ng-bootstrap";
 import { TranslateService } from "@ngx-translate/core";
 import { TitleCasePipe } from "../../shared/pipes/titlecase.pipe";
-import { map } from "rxjs/operators";
 
 import "codemirror/mode/haskell/haskell";
 import "codemirror/addon/display/panel";
@@ -24,6 +16,10 @@ import "codemirror/addon/hint/show-hint";
 import "codemirror/addon/hint/anyword-hint";
 import "codemirror/mode/markdown/markdown";
 
+const STARTS_WITH_CAPITAL_LETTER_REGEX = /^[A-Z]/;
+
+const ID_ROOT_DIR = -1;
+
 @Component({
   moduleId: module.id,
   selector: "archivos",
@@ -47,13 +43,127 @@ export class ArchivosComponent {
   sortFunction: any;
   configCodeMirror = JSON.parse(sessionStorage.getItem("codeMirrorConfig"));
 
+  /**
+   * Determina la ruta en donde se encuentra ubicado el archivo/directorio
+   * seleccionado actualmente.
+   */
+  currentPath: string = "/";
+
+  /**
+   * Con `true` se configura el modal para que se muestre la interfaz de
+   * agregar/borrar archivo. De otro modo, se muestra la interfaz de
+   * agregar/borrar directorio
+   */
+  modalTypeIsFile = true;
+
+  // - - - - - - - - - - - - - Modal create file - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de crear un archivo
+   */
+  modalCreateFile = false;
+
+  /**
+   * Con `true` se indica que el modal -de crear un archivo- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM
+   */
+  modalCreateFileOpened = true;
+
+  // - - - - - - - - - - - - -  Modal move file  - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de mover un archivo
+   */
+  modalMoveFile = false;
+
+  /**
+   * Con `true` se indica que el modal -de mover un archivo- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM
+   */
+  modalMoveFileOpened = true;
+
+  /**
+   * Directorio actual sobre el cual será desplegada la lista de directorios
+   * del modal mover archivo.
+   */
+  currentDirOfFileToMove: Archivo;
+
+  // - - - - - - - - - - - - - Modal remove file - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de borrar un archivo
+   */
+  modalRemoveFile = false;
+
+  /**
+   * Con `true` se indica que el modal -de borrar un archivo- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM
+   */
+  modalRemoveFileOpened = true;
+
+  /**
+   * Nombre del archivo que se desea borrar en el modal de borrar
+   * archivos/directorios.
+   */
+  fileNameToRemove: { fileName: string };
+
+  // - - - - - - - - - - - - - Modal share file - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de compartir un archivo
+   */
+  modalShareFile = false;
+
+  /**
+   * Con `true` se indica que el modal -de compartir un archivo- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM
+   */
+  modalShareFileOpened = true;
+
+  /**
+   * Nombre del archivo que se desea compartir en el modal de compartir archivo.
+   */
+  fileNameToShare: { fileName: string };
+
+  /**
+   * Arreglo de grupos sobre los cuales se puede compartir el archivo
+   * seleccionado en el modal de compartir archivo.
+   */
+  groupsToShareFile: Grupo[];
+
+  // - - - - - - - - - - - - - Modal send file - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de enviar un archivo para calificar
+   */
+  modalSendFile = false;
+
+  /**
+   * Con `true` se indica que el modal -de enviar un archivo para calificar-
+   * se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM
+   */
+  modalSendFileOpened = true;
+
+  // - - - - - - - - - - - - - Modal see score - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de ver calificacion
+   */
+  modalSeeScore = false;
+
+  /**
+   * Con `true` se indica que el modal -de ver calificacion- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM
+   */
+  modalSeeScoreOpened = true;
+
   constructor(
     private router: Router,
     private notifService: NotificacionService,
     private authService: AuthenticationService,
     private haskellService: HaskellService,
     private sessionService: SessionService,
-    private dialogService: DialogService,
     public translate: TranslateService,
     private route: ActivatedRoute
   ) {
@@ -66,7 +176,8 @@ export class ArchivosComponent {
     this.directorioActual.archivos = [];
     this.configCodeMirror.readOnly = true;
   }
-  @ViewChild(CodemirrorComponent, { static: false }) codemirror: CodemirrorComponent;
+  @ViewChild(LtCodemirrorComponent, { static: false })
+  codemirror: LtCodemirrorComponent;
 
   ngOnInit() {
     this.sortFunction = "tipo";
@@ -183,73 +294,67 @@ export class ArchivosComponent {
   }
 
   mostrarEliminarDialogo() {
-    if (this.archivoSeleccionado) {
-      //Si el archivo es del alumno lo puedo eliminar.
-      //(No se controla por creador dado que los compartidos mantienen este atributo)
-      if (
-        this.archivos.some((arch) => arch.id == this.archivoSeleccionado.id)
-      ) {
-        var that = this;
-        let disposable = this.dialogService
-          .addDialog(ConfirmarEliminar, {
-            nombreArchivo: { fileName: that.archivoSeleccionado.nombre },
-            esDirectorio: that.archivoSeleccionado.directorio,
-            parentContext: that,
-          })
-          .subscribe((isConfirmed) => {
-            if (isConfirmed) {
-              //codeMirrorRef.options.readOnly = false;
-              //componentRef.editDialogFired = true;
-            }
-          });
-        console.log(disposable);
-      } else {
-        this.notifService.warning(
-          this.translateService.get("i18n.warning.file.noPermissionDelete")
-            .value
-        );
-      }
-    } else {
+    // Chequear si se seleccionó un archivo
+    if (!this.archivoSeleccionado) {
       this.notifService.warning(
         this.translateService.get("i18n.warning.file.noSelected").value
       );
+      return;
+    }
+
+    // Si el archivo es del alumno, se puede eliminar.
+    // No se controla por creador, dado que los compartidos mantienen este atributo
+    if (!this.archivos.some((arch) => arch.id == this.archivoSeleccionado.id)) {
+      this.notifService.warning(
+        this.translateService.get("i18n.warning.file.noPermissionDelete").value
+      );
+      return;
     }
+
+    this.fileNameToRemove = { fileName: this.archivoSeleccionado.nombre };
+
+    // Determina el tipo de modal a renderizar
+    this.modalTypeIsFile = !this.archivoSeleccionado.directorio;
+
+    // Mostrar el modal
+    this.modalRemoveFile = true;
+    this.modalRemoveFileOpened = true;
   }
+
   seleccionarDirectorioAMover() {
-    if (this.archivoSeleccionado) {
-      //Si el archivo es del alumno lo puedo eliminar.
-      //(No se controla por creador dado que los compartidos mantienen este atributo)
-      if (
-        this.archivos.some((arch) => arch.id == this.archivoSeleccionado.id)
-      ) {
-        var that = this;
-        let disposable = this.dialogService
-          .addDialog(SeleccionarDirectorioMove, {
-            archivos: that.tree,
-            directorioActual: that.directorioActual,
-            nombre: that.archivoSeleccionado.nombre,
-            directorio: that.archivoSeleccionado.directorio,
-            parent: that,
-          })
-          .subscribe((isConfirmed) => {
-            if (isConfirmed) {
-            }
-          });
-      } else {
-        this.notifService.warning(
-          this.translateService.get("i18n.warning.file.noPermissionMove").value
-        );
-      }
-    } else {
+    if (!this.archivoSeleccionado) {
       this.notifService.warning(
         this.translateService.get("i18n.warning.file.noSelected").value
       );
+      return;
+    }
+
+    // Si el archivo es del alumno, se puede mover.
+    // No se controla por creador, dado que los compartidos mantienen este atributo
+    if (!this.archivos.some((arch) => arch.id == this.archivoSeleccionado.id)) {
+      this.notifService.warning(
+        this.translateService.get("i18n.warning.file.noPermissionMove").value
+      );
+      return;
     }
+
+    this.navBack(false);
+    this.currentDirOfFileToMove = this.directorioActual;
+
+    // Mostrar el modal
+    this.modalMoveFile = true;
+    this.modalMoveFileOpened = true;
   }
 
+  /**
+   * Dado un ID de directorio, refresca la UI con el contenido del directorio
+   * identificado por `idDirectorioActual`
+   * @param idDirectorioActual ID del directorio sobre el cual se quiere mostrar los archivos
+   */
   recargarArchivos(idDirectorioActual) {
     let cedula = this.authService.getUser().cedula;
     this.loading = true;
+
     this.haskellService.getArchivos(cedula).subscribe(
       (archivos) => {
         this.archivos = archivos;
@@ -260,14 +365,58 @@ export class ArchivosComponent {
     );
   }
 
-  navBack() {
-    var that = this;
-    if (this.directorioActual.padreId !== -1) {
-      var padre = this.archivos.filter(function (a) {
-        return a.id === that.directorioActual.padreId;
-      })[0];
-      this.directorioActual = padre;
+  /**
+   * Navega hacia el directorio padre en la vista principal de directorios.
+   * @param shouldUpdateSelectedFile Determina si se debe actualizar el archivo seleccionado cuando se navega hacia atrás
+   */
+  navBack(shouldUpdateSelectedFile = true) {
+    const { padreId } = this.directorioActual;
+
+    if (padreId === ID_ROOT_DIR) {
+      return;
+    }
+
+    // Actualiza el current path
+    const lastDirectoryIndex = this.currentPath.lastIndexOf(
+      `${this.directorioActual.nombre}`
+    );
+
+    this.currentPath = this.currentPath.substring(0, lastDirectoryIndex);
+
+    const padre = this.archivos.filter((file) => file.id === padreId)[0];
+
+    if (shouldUpdateSelectedFile) {
+      // Cuando se selecciona un directorio cuyo id es el root, significa que ese
+      // es el último archivo de la rama de directorios. En otras palabras, el
+      // root se identifica porque su padreId es ID_ROOT_DIR.
+      const archivoSeleccionado =
+        padre.padreId == ID_ROOT_DIR ? undefined : padre;
+      this.actualizarArchivoSeleccionado(archivoSeleccionado);
+    }
+
+    // Actualiza la vista de directorios y archivos
+    this.directorioActual = padre;
+  }
+
+  /**
+   * Localmente en la vista de directorios del modal, navega hacia el
+   * directorio padre.
+   * @param event Archivo sobre el cual se quiere navegar hacia su directorio padre
+   */
+  navigateBackModal(event: CustomEvent<Archivo>) {
+    const { padreId } = event.detail;
+
+    // No se puede navegar al padre de root
+    if (padreId == ID_ROOT_DIR) {
+      return;
     }
+
+    const archivosList: Archivo[] = this.sessionService.getArchivosList();
+
+    // Se queda con el archivo identificado por padreId
+    this.currentDirOfFileToMove = archivosList.filter(
+      (file) => file.id === padreId
+    )[0];
   }
 
   setSoloLectura = function (arch: Archivo) {
@@ -336,42 +485,9 @@ export class ArchivosComponent {
   }
 
   confirmarEntrega() {
-    var title =
-      this.titlecasePipe.transform(
-        this.translateService.get("i18n.action.send").value
-      ) +
-      " " +
-      this.titlecasePipe.transform(
-        this.translateService.get("i18n.object.file").value
-      );
-    var msg = "";
-    this.translateService
-      .get("i18n.msg.file.toSend", {
-        fileName: this.archivoSeleccionado.nombre,
-      })
-      .subscribe((res: string) => {
-        msg =
-          res +
-          "\n" +
-          this.translateService.get("i18n.msg.file.toSendInfo").value;
-      });
-
-    let disposable = this.dialogService
-      .addDialog(ConfirmComponent, {
-        title: title,
-        message: msg,
-        confirmText: this.titlecasePipe.transform(
-          this.translateService.get("i18n.action.send")
-        ),
-        cancelText: this.titlecasePipe.transform(
-          this.translateService.get("i18n.action.cancel")
-        ),
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          this.entregarArchivo();
-        }
-      });
+    // Mostrar el modal
+    this.modalSendFile = true;
+    this.modalSendFileOpened = true;
   }
 
   entregarArchivo() {
@@ -381,9 +497,15 @@ export class ArchivosComponent {
       .subscribe(
         (archivo) => {
           this.archivoSeleccionado = archivo;
+
+          // Cerrar el modal en caso de éxito
+          this.modalSendFileOpened = false;
         },
         (error) => {
           this.notifService.error(error);
+
+          // Cerrar el modal en caso de falla
+          this.modalSendFileOpened = false;
         }
       );
   }
@@ -476,94 +598,275 @@ export class ArchivosComponent {
     }
   }
 
-  mkdir() {
-    var that = this;
-    let disposable = this.dialogService
-      .addDialog(NuevoArchivo, {
-        nombre: "",
-        descripcion: "",
-        esDirectorio: true,
-        parentContext: that,
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          //codeMirrorRef.options.readOnly = false;
-          //componentRef.editDialogFired = true;
+  /**
+   * Renderiza en pantalla el modal de agregar archivos o directorios,
+   * dependiendo del valor de `modalTypeIsFile`.
+   * @param modalTypeIsFile Con `true` se indica que el modal a renderizar es el de agregar archivo. De otro modo, se renderiza el de agregar directorio.
+   */
+  mkFile(modalTypeIsFile: boolean) {
+    this.modalTypeIsFile = modalTypeIsFile;
+
+    // Mostrar el modal
+    this.modalCreateFile = true;
+    this.modalCreateFileOpened = true;
+  }
+
+  /**
+   * Valida y confirma la creación del archivo.
+   * @param event Evento devuelto por el modal asociado para crear el archivo. En el detalle contiene el `nombre` y `descripcion` del archivo que se desea agregar.
+   */
+  confirmFileCreation(event: CustomEvent) {
+    const { nombre, descripcion } = event.detail;
+
+    // Antes que nada, se chequea que empiece con mayúscula
+    if (!STARTS_WITH_CAPITAL_LETTER_REGEX.test(nombre)) {
+      alert(this.translateService.get("i18n.warning.file.capitalLetter").value);
+      return;
+    }
+
+    const archivo = new Archivo();
+    archivo.cedulaCreador = this.directorioActual.cedulaCreador;
+    archivo.contenido = this.modalTypeIsFile ? "" : descripcion;
+    archivo.directorio = !this.modalTypeIsFile;
+    archivo.editable = true;
+    archivo.fechaCreacion = new Date();
+    archivo.nombre = nombre;
+    archivo.padreId = this.directorioActual.id;
+
+    const that = this;
+    const idDirectorioActual = this.directorioActual.id;
+
+    this.haskellService.crearArchivo(archivo).subscribe(
+      () => {
+        that.recargarArchivos(idDirectorioActual);
+
+        // Cerrar el modal en caso de éxito
+        that.modalCreateFileOpened = false;
+      },
+      (error) => {
+        that.notifService.error(error.text());
+
+        // Cerrar el modal en caso de error
+        that.modalCreateFileOpened = false;
+      }
+    );
+  }
+
+  /**
+   * Valida y confirma la operación de mover el archivo/carpeta.
+   * @param event Evento devuelto por el modal asociado para mover el archivo. El detalle contiene el `idPadre` del archivo que se desea mover.
+   */
+  confirmFileMove(event: CustomEvent) {
+    if (!this.archivoSeleccionado) {
+      this.notifService.warning(
+        this.translateService.get("i18n.warning.file.noSelected").value
+      );
+      return;
+    }
+
+    const nuevoDirectorioPadreId = event.detail.padreId;
+
+    // Se actualiza en el cliente el directorio padre del archivo a mover
+    this.archivoSeleccionado.padreId = nuevoDirectorioPadreId;
+
+    if (this.archivoSeleccionado.directorio) {
+      delete this.archivoSeleccionado["archivos"];
+    }
+
+    this.haskellService
+      .editarArchivo(this.archivoSeleccionado.id, this.archivoSeleccionado)
+      .subscribe(
+        () => {
+          this.recargarArchivos(this.directorioActual.id);
+
+          // Dado que se cambia la ubicación del directorio actual, hay que
+          // rearmar el currentPath
+          if (this.archivoSeleccionado.directorio) {
+            this.inicializarCurrentPath(this.directorioActual);
+          }
+
+          this.archivoSeleccionado = null;
+
+          // Cerrar el modal en caso de éxito
+          this.modalMoveFileOpened = false;
+        },
+        (error) => {
+          this.notifService.error(error.text());
+
+          // Cerrar el modal en caso de error
+          this.modalMoveFileOpened = false;
+        }
+      );
+  }
+
+  /**
+   * Valida y confirma la operación de borrar el archivo/carpeta.
+   */
+  confirmFileDeletion() {
+    const directorio = this.archivoSeleccionado.directorio;
+
+    this.haskellService.eliminarArchivo(this.archivoSeleccionado.id).subscribe(
+      () => {
+        let idDirActual;
+
+        this.archivoSeleccionado.eliminado = true;
+
+        // Si el archivo seleccionado es un directorio, se borran todos los
+        // archivos del directorio
+        if (directorio) {
+          delete this.archivoSeleccionado["archivos"];
+
+          // Actualiza el current path
+          const lastDirectoryIndex = this.currentPath.lastIndexOf(
+            `${this.directorioActual.nombre}`
+          );
+          this.currentPath = this.currentPath.substring(0, lastDirectoryIndex);
+
+          idDirActual = this.directorioActual.padreId;
+
+          // Si se borra el directorio actual, se selecciona el directorio
+          // padre en caso de que este no sea el root
+          this.archivoSeleccionado =
+            idDirActual !== ID_ROOT_DIR ? idDirActual : null;
+        } else {
+          idDirActual = this.directorioActual.id;
+          this.archivoSeleccionado = null;
         }
-      });
-  }
-  mkFile() {
-    var that = this;
-    let disposable = this.dialogService
-      .addDialog(NuevoArchivo, {
-        nombre: "",
-        descripcion: "",
-        esDirectorio: false,
-        parentContext: that,
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          //codeMirrorRef.options.readOnly = false;
-          //componentRef.editDialogFired = true;
+
+        this.recargarArchivos(idDirActual);
+
+        // Cerrar el modal en caso de éxito
+        this.modalRemoveFileOpened = false;
+      },
+      (error) => {
+        this.notifService.error(error);
+
+        // Cerrar el modal en caso de error
+        this.modalRemoveFileOpened = false;
+      }
+    );
+  }
+
+  confirmFileShare(event: CustomEvent<Grupo>) {
+    const selectedGroup = event.detail;
+
+    if (!selectedGroup) {
+      this.notifService.error(
+        this.translateService.get("i18n.warning.group.select").value
+      );
+      return;
+    }
+
+    this.haskellService
+      .compartirArchivoGrupo(selectedGroup, this.archivoSeleccionado.id)
+      .subscribe(
+        () => {
+          this.notifService.success(
+            this.translateService.get("i18n.msg.file.shared").value
+          );
+
+          // Cerrar el modal en caso de éxito
+          this.modalShareFileOpened = false;
+        },
+        (error) => {
+          this.notifService.error(error);
+
+          // Cerrar el modal en caso de error
+          this.modalShareFileOpened = false;
         }
-      });
+      );
   }
 
-  seleccionarArchivo = function (arch: Archivo) {
-    if (arch.directorio) {
-      this.directorioActual = arch;
+  /**
+   * Dado el directorio actual, se contruye el path absoluto (se actualiza
+   * currentPath) que identifica al directorio. Esta función es útil cuando un
+   * directorio es movido de lugar y se desconoce la nueva ubicación del
+   * directorio.
+   * @param lastDirectory Directorio sobre el cual se quiere obtener el path
+   */
+  inicializarCurrentPath(lastDirectory: Archivo) {
+    // Si el directorio está en root, el currentPath es "/"
+    if (lastDirectory.padreId === ID_ROOT_DIR) {
+      this.currentPath = "/";
+      return;
+    }
+
+    let path = "/";
+    let currentDirectory = lastDirectory;
+
+    const archivosList: Archivo[] = this.sessionService.getArchivosList();
+
+    // Se recorren los ancestros de currentDirectory
+    while (currentDirectory.padreId !== ID_ROOT_DIR) {
+      path = "/" + currentDirectory.nombre + path;
+
+      // Se queda con el archivo identificado por padreId
+      currentDirectory = archivosList.filter(
+        (file) => file.id === currentDirectory.padreId
+      )[0];
+    }
+
+    this.currentPath = path;
+  }
+
+  seleccionarArchivo(archivo: Archivo) {
+    if (archivo.directorio) {
+      this.directorioActual = archivo;
+
+      // Actualizar el currentPath para así siempre lo puede recibir el modal de
+      // mover archivo
+      this.currentPath += `${archivo.nombre}/`;
     } else {
       this.sessionService.setDirectorioActual(this.directorioActual);
       this.sessionService.setArchivosCompartidos(this.archivosCompartidos);
-      this.sessionService.cargarDependencias(arch);
+      this.sessionService.cargarDependencias(archivo);
     }
-    this.archivoSeleccionado = arch;
-    this.preview = arch.contenido;
+
+    this.actualizarArchivoSeleccionado(archivo);
+
     //this.ordenarArchivos();
-  };
+  }
+
+  /**
+   * Actualiza el estado del archivo seleccionado, así como la preview del
+   * contenido de dicho archivo.
+   * @param archivo Archivo a seleccionar
+   */
+  actualizarArchivoSeleccionado(archivo: Archivo) {
+    this.archivoSeleccionado = archivo;
+    this.preview = archivo ? archivo.contenido : "";
+  }
 
   compartirArchivo() {
-    if (this.archivoSeleccionado) {
-      var grupos = this.sessionService.getGrupos();
-      if (grupos == undefined) {
-        this.haskellService
-          .getGrupos(this.authService.getUser().cedula)
-          .subscribe(
-            (gruposRest) => {
-              this.sessionService.setGrupos(grupos);
-              this.dialogService
-                .addDialog(CompartirArchivoComponent, {
-                  grupos: gruposRest,
-                  archivo: this.archivoSeleccionado,
-                  nombreArchivo: { fileName: this.archivoSeleccionado.nombre },
-                  parent: this,
-                })
-                .subscribe((isConfirmed) => {
-                  if (isConfirmed) {
-                    this.notifService.success("confirmado?");
-                  }
-                });
-            },
-            (error) => {}
-          );
-      } else {
-        this.dialogService
-          .addDialog(CompartirArchivoComponent, {
-            grupos: grupos,
-            archivo: this.archivoSeleccionado,
-            nombreArchivo: { fileName: this.archivoSeleccionado.nombre },
-            parent: this,
-          })
-          .subscribe((isConfirmed) => {
-            if (isConfirmed) {
-              this.notifService.success("confirmado?");
-            }
-          });
-      }
-    } else {
+    if (!this.archivoSeleccionado) {
       this.notifService.warning(
         this.translateService.get("i18n.warning.file.noSelected").value
       );
+      return;
+    }
+
+    const grupos = this.sessionService.getGrupos();
+    this.fileNameToShare = { fileName: this.archivoSeleccionado.nombre };
+
+    if (grupos == undefined) {
+      this.haskellService
+        .getGrupos(this.authService.getUser().cedula)
+        .subscribe((gruposRest) => {
+          // Se guardan los grupos en la sesión
+          this.sessionService.setGrupos(gruposRest);
+
+          this.groupsToShareFile = gruposRest;
+
+          // Mostrar el modal
+          this.modalShareFile = true;
+          this.modalShareFileOpened = true;
+        });
+    } else {
+      this.groupsToShareFile = grupos;
+
+      // Mostrar el modal
+      this.modalShareFile = true;
+      this.modalShareFileOpened = true;
     }
   }
 
@@ -600,14 +903,12 @@ export class ArchivosComponent {
   }
 
   verCalificacion() {
-    this.dialogService
-      .addDialog(VerCalificacionComponent, {
-        archivo: this.archivoSeleccionado,
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          this.notifService.success("confirmado?");
-        }
-      });
+    if (!this.archivoSeleccionado) {
+      return;
+    }
+
+    // Mostrar el modal
+    this.modalSeeScore = true;
+    this.modalSeeScoreOpened = true;
   }
 }
diff --git a/Frontend Angular 4/src/app/layout/archivos/archivos.module.ts b/Frontend Angular 4/src/app/layout/archivos/archivos.module.ts
index babc52fd90abaab34f3897f499509d7dcaf56187..fba00559caf69ad7b2b345654438af0e726cd2b9 100755
--- a/Frontend Angular 4/src/app/layout/archivos/archivos.module.ts	
+++ b/Frontend Angular 4/src/app/layout/archivos/archivos.module.ts	
@@ -4,16 +4,8 @@ import { ArchivosComponent } from "./archivos.component";
 import { CommonModule } from "@angular/common";
 import { ArchivosRoutingModule } from "./archivos-routing.module";
 import { FilterPipe } from "../../shared/pipes/filter.pipe";
-import { ConfirmComponent } from "../../shared/modal/confirm.component";
-import { NuevoArchivo } from "./nuevoArchivo.component";
-import { VerCalificacionComponent } from "./verCalificacion.component";
-import { CompartirArchivoComponent } from "./compartirArchivo.component";
-import { SeleccionarDirectorioMove } from "./seleccionarDirectorio.component";
-import { ConfirmarEliminar } from "./confirmarEliminar.component";
-import { DialogService } from "ng2-bootstrap-modal";
-import { BootstrapModalModule } from "ng2-bootstrap-modal";
 import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
-import { CodemirrorModule } from "ng2-codemirror";
+import { LtCodemirrorModule } from "lt-codemirror";
 import { NotificacionModule } from "../../notificacion/notificacion.module";
 import { I18nModule } from "../../shared/modules/translate/i18n.module";
 import { TitleCaseModule } from "../../shared/modules/titlecase.module";
@@ -23,31 +15,13 @@ import { TitleCaseModule } from "../../shared/modules/titlecase.module";
     CommonModule,
     ArchivosRoutingModule,
     FormsModule,
-    BootstrapModalModule,
     NgbModule,
-    CodemirrorModule,
+    LtCodemirrorModule,
     NotificacionModule,
     I18nModule,
     TitleCaseModule,
   ],
-  declarations: [
-    ArchivosComponent,
-    FilterPipe,
-    NuevoArchivo,
-    VerCalificacionComponent,
-    ConfirmComponent,
-    CompartirArchivoComponent,
-    ConfirmarEliminar,
-    SeleccionarDirectorioMove,
-  ],
-  entryComponents: [
-    NuevoArchivo,
-    VerCalificacionComponent,
-    ConfirmComponent,
-    CompartirArchivoComponent,
-    ConfirmarEliminar,
-    SeleccionarDirectorioMove,
-  ],
+  declarations: [ArchivosComponent, FilterPipe],
   exports: [ArchivosComponent],
   schemas: [CUSTOM_ELEMENTS_SCHEMA],
 })
diff --git a/Frontend Angular 4/src/app/layout/archivos/compartirArchivo.component.ts b/Frontend Angular 4/src/app/layout/archivos/compartirArchivo.component.ts
deleted file mode 100755
index be9ee07fb1aacb562bbd76b4b53aa8802d66ab05..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/archivos/compartirArchivo.component.ts	
+++ /dev/null
@@ -1,111 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo } from "../../shared/objects/archivo";
-import { Grupo } from "../../shared/objects/grupo";
-import { TranslateService } from "@ngx-translate/core";
-
-export interface ConfirmModel {
-  archivo: Archivo;
-  grupos: any;
-  parent: any;
-  nombreArchivo: { fileName: string };
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h6 class="modal-title pull-lefth">
-          {{ "i18n.msg.file.share" | translate: nombreArchivo }}
-        </h6>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-rigth:8px;"
-        >
-          &times;
-        </button>
-      </div>
-      <div class="modal-body" style="height:350px;overflow-y: scroll;">
-        <div>
-          <div class="list-group">
-            <button
-              *ngFor="let g of grupos"
-              type="button"
-              (click)="seleccionarGrupo(g)"
-              style="cursor:pointer"
-              class="list-group-item list-group-item-action"
-              [ngClass]="{
-                active:
-                  grupo != undefined &&
-                  g.grado == grupo.grado &&
-                  g.grupo == grupo.grupo &&
-                  g.anio == grupo.anio &&
-                  g.liceoId == grupo.liceoId
-              }"
-            >
-              <i
-                class="fa fa-group"
-                style="margin-right:10px; font-size: 3em; cursor: pointer;"
-                aria-hidden="true"
-              ></i>
-              {{ g.grado + "°" + g.grupo + " - " + g.anio }}
-            </button>
-          </div>
-        </div>
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn btn-primary" (click)="compartir()">
-          {{ "i18n.action.share" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class CompartirArchivoComponent
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  archivo: Archivo;
-  grupos: any;
-  grupo: Grupo;
-  parent: any;
-  nombreArchivo: { fileName: string };
-  translateService: any;
-
-  constructor(
-    dialogService: DialogService,
-    public translate: TranslateService
-  ) {
-    super(dialogService);
-    this.translateService = translate;
-  }
-
-  seleccionarGrupo(grupo) {
-    this.grupo = grupo;
-  }
-
-  compartir() {
-    this.nombreArchivo = { fileName: this.archivo.nombre };
-    if (this.grupo) {
-      this.parent.haskellService
-        .compartirArchivoGrupo(this.grupo, this.archivo.id)
-        .subscribe(
-          (success) => {
-            this.parent.notifService.success(
-              this.translateService.get("i18n.msg.file.shared").value
-            );
-            this.close();
-          },
-          (error) => {
-            this.parent.notifService.error(error);
-          }
-        );
-    } else {
-      this.parent.notifService.error(
-        this.translateService.get("i18n.warning.group.select").value
-      );
-    }
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/archivos/confirmarEliminar.component.ts b/Frontend Angular 4/src/app/layout/archivos/confirmarEliminar.component.ts
deleted file mode 100755
index 81834a8169499b48414611bf93de7d3f958b081e..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/archivos/confirmarEliminar.component.ts	
+++ /dev/null
@@ -1,91 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo } from "../../shared/objects/archivo";
-
-export interface ConfirmModel {
-  nombreArchivo: { fileName: string };
-  esDirectorio: boolean;
-  parentContext: any;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h6 class="modal-title" *ngIf="!esDirectorio">
-          {{ "i18n.action.delete" | translate | titleCase }}
-          {{ "i18n.object.file" | translate | titleCase }}
-        </h6>
-        <h6 class="modal-title" *ngIf="esDirectorio">
-          {{ "i18n.action.delete" | translate | titleCase }}
-          {{ "i18n.object.folder" | translate | titleCase }}
-        </h6>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-left:8px;"
-        >
-          &times;
-        </button>
-      </div>
-      <div class="modal-body">
-        <p *ngIf="!esDirectorio">
-          {{ "i18n.msg.file.delete" | translate: nombreArchivo }}
-        </p>
-        <p *ngIf="esDirectorio">
-          {{ "i18n.msg.file.delete" | translate: nombreArchivo }}
-        </p>
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn btn-default" (click)="close()">
-          {{ "i18n.action.cancel" | translate | titleCase }}
-        </button>
-        <button
-          type="button"
-          class="btn btn-success"
-          (click)="confirmarEliminar()"
-        >
-          {{ "i18n.action.delete" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class ConfirmarEliminar
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  nombreArchivo: { fileName: string };
-  esDirectorio: boolean;
-  parentContext: any;
-
-  constructor(dialogService: DialogService) {
-    super(dialogService);
-  }
-  confirmarEliminar() {
-    var that = this.parentContext;
-    var directorio = this.parentContext.archivoSeleccionado.directorio;
-    this.parentContext.archivoSeleccionado.eliminado = true;
-    if (directorio) {
-      delete this.parentContext.archivoSeleccionado["archivos"];
-    }
-    this.parentContext.haskellService
-      .eliminarArchivo(this.parentContext.archivoSeleccionado.id)
-      .subscribe(
-        (archivo) => {
-          if (directorio) {
-            var idDirActual = that.directorioActual.padreId;
-          } else {
-            var idDirActual = that.directorioActual.id;
-          }
-          that.recargarArchivos(idDirActual);
-          that.archivoSeleccionado = null;
-        },
-        (error) => {
-          this.parentContext.notifService.error(error);
-        }
-      );
-    this.close();
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/archivos/nuevoArchivo.component.ts b/Frontend Angular 4/src/app/layout/archivos/nuevoArchivo.component.ts
deleted file mode 100755
index b4f8ebdfe205b118d223f17e92869f56f1f5bdca..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/archivos/nuevoArchivo.component.ts	
+++ /dev/null
@@ -1,126 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo } from "../../shared/objects/archivo";
-import { TranslateService } from "@ngx-translate/core";
-
-export interface ConfirmModel {
-  nombre: string;
-  descripcion: string;
-  parentContext: any;
-  esDirectorio: boolean;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h6 class="modal-title" *ngIf="esDirectorio">
-          {{ "i18n.action.new" | translate | titleCase }}
-          {{ "i18n.object.folder" | translate | titleCase }}
-        </h6>
-        <h6 class="modal-title" *ngIf="!esDirectorio">
-          {{ "i18n.action.new" | translate | titleCase }}
-          {{ "i18n.object.file" | translate | titleCase }}
-        </h6>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-left:8px;"
-        >
-          &times;
-        </button>
-      </div>
-
-      <div class="modal-body">
-        <form>
-          <div class="form-group">
-            <label for="recipient-name" class="form-control-label">
-              {{ "i18n.object.name" | translate | titleCase }}:
-            </label>
-            <input
-              type="text"
-              class="form-control"
-              id="recipient-name"
-              [(ngModel)]="nombre"
-              [ngModelOptions]="{ standalone: true }"
-            />
-          </div>
-          <div class="form-group" *ngIf="esDirectorio">
-            <label for="message-text" class="form-control-label">
-              {{ "i18n.object.descr" | translate | titleCase }}:
-            </label>
-            <textarea
-              class="form-control"
-              id="message-text"
-              [(ngModel)]="descripcion"
-              [ngModelOptions]="{ standalone: true }"
-            ></textarea>
-          </div>
-        </form>
-      </div>
-
-      <div class="modal-footer">
-        <button
-          [disabled]="this.nombre == ''"
-          type="button"
-          class="btn btn-success"
-          (click)="confirm()"
-        >
-          {{ "i18n.action.create" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class NuevoArchivo
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  nombre: string;
-  esDirectorio: boolean;
-  descripcion: string;
-  parentContext: any;
-  translateService: any;
-
-  constructor(
-    dialogService: DialogService,
-    public translate: TranslateService
-  ) {
-    super(dialogService);
-    this.translateService = translate;
-  }
-  confirm() {
-    var nombre = this.nombre;
-    var desc = this.descripcion;
-    var archivo: Archivo;
-    archivo = new Archivo();
-    archivo.cedulaCreador = this.parentContext.directorioActual.cedulaCreador;
-    if (this.esDirectorio) {
-      archivo.contenido = desc;
-    } else {
-      archivo.contenido = "";
-    }
-    archivo.directorio = this.esDirectorio;
-    archivo.editable = true;
-    archivo.fechaCreacion = new Date();
-    archivo.nombre = nombre;
-    archivo.padreId = this.parentContext.directorioActual.id;
-    var that = this.parentContext;
-    var regex = /^[A-Z]/;
-    if (regex.test(nombre)) {
-      this.parentContext.haskellService.crearArchivo(archivo).subscribe(
-        (archivo) => {
-          var id = that.directorioActual.id;
-          that.recargarArchivos(id);
-        },
-        (error) => {
-          this.parentContext.notifService.error(error.text());
-        }
-      );
-      this.close();
-    } else {
-      alert(this.translateService.get("i18n.warning.file.capitalLetter").value);
-    }
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/archivos/seleccionarDirectorio.component.ts b/Frontend Angular 4/src/app/layout/archivos/seleccionarDirectorio.component.ts
deleted file mode 100755
index a49b1a1f40bc28e5ef47929195dabb125b218c94..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/archivos/seleccionarDirectorio.component.ts	
+++ /dev/null
@@ -1,134 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo } from "../../shared/objects/archivo";
-
-export interface ConfirmModel {
-  directorio: boolean;
-  archivos: any;
-  directorioActual: any;
-  parent: any;
-  nombre: string;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h6 class="modal-title pull-lefth">
-          {{ "i18n.msg.file.move" | translate }}
-        </h6>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-rigth:8px;"
-        >
-          &times;
-        </button>
-      </div>
-      <div class="modal-body" style="height:350px;overflow-y: scroll;">
-        <div>
-          <div class="list-group">
-            <button
-              *ngFor="
-                let arch of directorioActual.archivos.filter(esDirectorio)
-              "
-              type="button"
-              (click)="navToDir(arch)"
-              style="cursor:pointer"
-              class="list-group-item list-group-item-action"
-            >
-              <i
-                *ngIf="arch.directorio"
-                class="fa fa-folder"
-                style="margin-right:10px; font-size: 3em; cursor: pointer;"
-                aria-hidden="true"
-              ></i>
-              <i
-                *ngIf="!arch.directorio"
-                class="fa fa-file-text"
-                style="margin-right:10px;font-size: 3em; cursor: pointer;"
-                aria-hidden="true"
-              ></i>
-              {{ arch.nombre }}
-            </button>
-          </div>
-        </div>
-      </div>
-      <div class="modal-footer">
-        <button
-          [disabled]="this.directorioActual.padreId == -1"
-          type="button"
-          class="btn btn-default"
-          (click)="navBack()"
-        >
-          {{ "i18n.action.goBack" | translate | titleCase }}
-        </button>
-        <button type="button" class="btn btn-primary" (click)="move()">
-          {{ "i18n.action.move" | translate | titleCase }}
-          {{ "i18n.object.here" | translate }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class SeleccionarDirectorioMove
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  directorio: boolean;
-  archivos: any;
-  directorioActual: any;
-  parent: any;
-  nombre: string;
-
-  constructor(dialogService: DialogService) {
-    super(dialogService);
-  }
-
-  esDirectorio(archivo) {
-    return archivo.directorio;
-  }
-
-  move() {
-    // we set dialog result as true on click on confirm button,
-    // then we can get dialog result from caller code
-    var that = this;
-    if (this.nombre !== undefined && this.nombre !== "") {
-      this.parent.archivoSeleccionado.padreId = this.directorioActual.id;
-      if (this.parent.archivoSeleccionado.directorio) {
-        delete this.parent.archivoSeleccionado["archivos"];
-      }
-      this.parent.haskellService
-        .editarArchivo(
-          this.parent.archivoSeleccionado.id,
-          this.parent.archivoSeleccionado
-        )
-        .subscribe(
-          (archivo) => {
-            that.parent.recargarArchivos(this.directorioActual.id);
-            that.parent.archivoSeleccionado = null;
-          },
-          (error) => {
-            this.parent.notifService.error(error.text());
-          }
-        );
-    }
-    this.close();
-  }
-
-  navToDir(arch) {
-    if (arch.directorio) {
-      this.directorioActual = arch;
-    }
-  }
-
-  navBack() {
-    var idPadre = this.directorioActual.padreId;
-    var archivosList = this.parent.sessionService.getArchivosList();
-    var nuevoDirectorioActual = archivosList.filter(function (a) {
-      return a.id === idPadre;
-    })[0];
-    this.directorioActual = nuevoDirectorioActual;
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/archivos/verCalificacion.component.ts b/Frontend Angular 4/src/app/layout/archivos/verCalificacion.component.ts
deleted file mode 100755
index 844cc7e5dd854456d4507e2ed72caaa99fe82470..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/archivos/verCalificacion.component.ts	
+++ /dev/null
@@ -1,59 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo, Evaluacion } from "../../shared/objects/archivo";
-
-export interface ConfirmModel {
-  archivo: Archivo;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h6 class="modal-title pull-lefth">
-          {{ "i18n.object.qualification" | translate | titleCase }} &quot;{{
-            archivo.nombre
-          }}&quot;:
-        </h6>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-rigth:8px;"
-        >
-          &times;
-        </button>
-      </div>
-      <div class="modal-body">
-        <div>
-          <label
-            ><b>{{ "i18n.object.date" | translate | titleCase }}: </b></label
-          >&nbsp; {{ archivo.evaluacion.fecha | date }}<br />
-          <label
-            ><b
-              >{{ "i18n.object.score" | translate | titleCase }} (0-100):
-            </b></label
-          >&nbsp; {{ archivo.evaluacion.nota }}<br />
-          <label
-            ><b>{{ "i18n.object.detail" | translate | titleCase }}: </b></label
-          >&nbsp; {{ archivo.evaluacion.descripcion }}
-        </div>
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn btn-primary" (click)="close()">
-          {{ "i18n.action.close" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class VerCalificacionComponent
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  archivo: Archivo;
-
-  constructor(dialogService: DialogService) {
-    super(dialogService);
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/grupos/calificarEntrega.component.ts b/Frontend Angular 4/src/app/layout/grupos/calificarEntrega.component.ts
deleted file mode 100755
index 924070d23f792a635630b70be77ebd3240bb3d9b..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/grupos/calificarEntrega.component.ts	
+++ /dev/null
@@ -1,150 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo, Evaluacion } from "../../shared/objects/archivo";
-import { TranslateService } from "@ngx-translate/core";
-
-export interface ConfirmModel {
-  cedula: string;
-  archivo: Archivo;
-  parentContext: any;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h5 class="modal-title">{{ "i18n.msg.file.qualify" | translate }}</h5>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-left:8px;"
-        >
-          &times;
-        </button>
-      </div>
-
-      <div class="modal-body">
-        <form>
-          <div class="form-group">
-            <label for="message-text" class="form-control-label"
-              >{{ "i18n.object.score" | translate | titleCase }} (0-100):</label
-            >
-            <input
-              type="number"
-              class="form-control"
-              [(ngModel)]="nota"
-              min="1"
-              max="100"
-              [ngModelOptions]="{ standalone: true }"
-            />
-          </div>
-          <div class="form-group">
-            <label for="message-text" class="form-control-label"
-              >{{ "i18n.object.detail" | translate | titleCase }}:</label
-            >
-            <textarea
-              class="form-control"
-              id="message-text"
-              [(ngModel)]="descripcion"
-              [ngModelOptions]="{ standalone: true }"
-            ></textarea>
-          </div>
-          <div class="form-group">
-            <label for="message-text" class="form-control-label"
-              >{{ "i18n.object.state" | translate | titleCase }}:</label
-            >
-            <select
-              name="estado"
-              id="estado"
-              class="form-control"
-              [(ngModel)]="estado"
-            >
-              <option *ngFor="let st of estados" [value]="st.value">
-                {{ st.label }}
-              </option>
-            </select>
-          </div>
-        </form>
-      </div>
-
-      <div class="modal-footer">
-        <button type="button" class="btn btn-secondary" (click)="cancel()">
-          {{ "i18n.action.cancel" | translate | titleCase }}
-        </button>
-        <button type="button" class="btn btn-success" (click)="confirm()">
-          {{ "i18n.action.qualify" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class CalificarEntrega
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  descripcion: string = "";
-  cedula: string;
-  archivo: Archivo;
-  nota: number = 0;
-  estado: string = "Corregido";
-  estados: any;
-  translateService: any;
-  parentContext: any;
-
-  constructor(
-    dialogService: DialogService,
-    public translate: TranslateService
-  ) {
-    super(dialogService);
-    this.translateService = translate;
-    this.estados = [
-      {
-        value: "Corregido",
-        label: this.translateService.get("i18n.msg.file.evaluated").value,
-      },
-      {
-        value: "Devuelto",
-        label: this.translateService.get("i18n.msg.file.returned").value,
-      },
-    ];
-  }
-
-  ngOnInit() {
-    if (this.archivo.evaluacion) {
-      this.descripcion = this.archivo.evaluacion.descripcion;
-      this.nota = this.archivo.evaluacion.nota;
-    }
-  }
-
-  confirm() {
-    var evaluacion = new Evaluacion();
-    evaluacion.cedulaDocente = this.cedula;
-    evaluacion.descripcion = this.descripcion;
-    evaluacion.nota = this.nota;
-    if (this.nota >= 0 && this.nota <= 100) {
-      this.parentContext.haskellService
-        .calificarArchivo(this.archivo.id, this.estado, evaluacion)
-        .subscribe(
-          (evaluacion) => {
-            this.parentContext.notifService.success(
-              this.translateService.get("i18n.msg.file.evaluated").value
-            );
-            this.archivo.evaluacion = evaluacion;
-            this.close();
-          },
-          (error) => {
-            this.parentContext.notifService.error(error);
-          }
-        );
-    } else {
-      this.parentContext.notifService.error(
-        this.translateService.get("i18n.warning.file.qualifyOutRange").value
-      );
-    }
-  }
-
-  cancel() {
-    this.close();
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/grupos/grupos.component.html b/Frontend Angular 4/src/app/layout/grupos/grupos.component.html
index 50d865f72a7d092edd2ebe3a67d14d8fe7cc6403..b12cc21b748e7c08975494d031ce9cef6a5302a8 100755
--- a/Frontend Angular 4/src/app/layout/grupos/grupos.component.html	
+++ b/Frontend Angular 4/src/app/layout/grupos/grupos.component.html	
@@ -30,15 +30,10 @@
             <div
               *ngFor="let grupo of grupos"
               (click)="seleccionarGrupo(grupo)"
-              class="col-sm-3 col-4"
-              style="text-align: center"
+              class="col-sm-3 col-4 matefun-group-wrapper"
             >
-              <i
-                class="fa fa-users"
-                style="font-size: 3em; cursor: pointer; color: #f95e5e"
-                aria-hidden="true"
-              ></i>
-              <p style="cursor: pointer">
+              <i class="fa fa-users matefun-fa-user" aria-hidden="true"></i>
+              <p>
                 {{ grupo.grado + "°" + grupo.grupo + " - " + grupo.anio }}
               </p>
             </div>
@@ -83,15 +78,13 @@
                   <div
                     *ngFor="let alumno of grupoSeleccionado.alumnos"
                     (click)="seleccionarAlumno(alumno)"
-                    class="col-sm-3"
-                    style="text-align: center"
+                    class="col-sm-3 matefun-group-wrapper"
                   >
                     <i
-                      class="fa fa-user"
-                      style="font-size: 3em; cursor: pointer; color: #f95e5e"
+                      class="fa fa-user matefun-fa-user"
                       aria-hidden="true"
                     ></i>
-                    <p style="cursor: pointer">
+                    <p>
                       {{ alumno.apellido + ", " + alumno.nombre }}
                     </p>
                   </div>
@@ -137,15 +130,13 @@
                   <div
                     *ngFor="let archivo of grupoSeleccionado.archivos"
                     (click)="seleccionarArchivo(archivo)"
-                    class="col-sm-3 col-4"
-                    style="text-align: center"
+                    class="col-sm-3 col-4 matefun-group-wrapper"
                   >
                     <i
-                      class="fa fa-file-text"
-                      style="font-size: 3em; cursor: pointer; color: #ff8383"
+                      class="fa fa-file-text matefun-fa-file"
                       aria-hidden="true"
                     ></i>
-                    <p style="cursor: pointer">{{ archivo.nombre }}</p>
+                    <p>{{ archivo.nombre }}</p>
                   </div>
                 </div>
               </div>
@@ -164,16 +155,14 @@
             <div
               *ngFor="let entrega of alumnoSeleccionado.archivos"
               (click)="seleccionarEntrega(entrega)"
-              class="col-sm-3 col-4"
-              style="text-align: center"
+              class="col-sm-3 col-4 matefun-file-wrapper"
             >
               <i
-                [ngStyle]=""
                 class="fa fa-file-text"
-                style="font-size: 3em; cursor: pointer"
+                style="font-size: 3em"
                 aria-hidden="true"
               ></i>
-              <p style="cursor: pointer">{{ entrega.nombre }}</p>
+              <p>{{ entrega.nombre }}</p>
             </div>
             <div
               *ngIf="alumnoSeleccionado.archivos.length == 0"
@@ -227,7 +216,7 @@
           <button
             *ngIf="tipoArchivo == 'entrega'"
             class="btn btn-sm btn-secondary pull-left mr-2"
-            (click)="calificarEntrega()"
+            (click)="mostrarModalCalificarEntrega()"
           >
             Calificar
           </button>
@@ -246,14 +235,32 @@
             {{ archivoSeleccionado?.fechaCreacion | date }}
           </div>
         </div>
-        <codemirror
+        <lt-codemirror
           class="codemirrorGrupos"
           [(ngModel)]="archivoSeleccionado.contenido"
           [config]="configCodeMirror"
           [ngStyle]="{ 'font-size': configCodeMirror.fontSize + 'px' }"
         >
-        </codemirror>
+        </lt-codemirror>
       </div>
     </div>
   </div>
 </div>
+
+<matefun-modal-calificar-entrega
+  cancelLabel="{{ 'i18n.action.cancel' | translate | titleCase }}"
+  confirmLabel="{{ 'i18n.action.qualify' | translate | titleCase }}"
+  [detail]="archivoSeleccionado.evaluacion?.descripcion"
+  detailLabel="{{ 'i18n.object.detail' | translate | titleCase }}:"
+  header="{{ 'i18n.msg.file.qualify' | translate }}"
+  [opened]="modalQualifyDeliveryOpened"
+  [posibleStatuses]="posibleStatusesQualifyDelivery"
+  [score]="archivoSeleccionado.evaluacion?.nota"
+  scoreLabel="{{ 'i18n.object.score' | translate | titleCase }} (0-100):"
+  statusLabel="{{ 'i18n.object.state' | translate | titleCase }}:"
+  (cancelAction)="modalQualifyDeliveryOpened = false"
+  (close)="modalQualifyDelivery = false"
+  (confirmFileQualify)="confirmFileQualify($event)"
+  *ngIf="modalQualifyDelivery"
+>
+</matefun-modal-calificar-entrega>
diff --git a/Frontend Angular 4/src/app/layout/grupos/grupos.component.ts b/Frontend Angular 4/src/app/layout/grupos/grupos.component.ts
index cec5374cbb5ab9ecb2eea45adf317b56f6b235a1..36adbec41c918f5c7172b3c69d38053c7a42f68f 100755
--- a/Frontend Angular 4/src/app/layout/grupos/grupos.component.ts	
+++ b/Frontend Angular 4/src/app/layout/grupos/grupos.component.ts	
@@ -1,14 +1,12 @@
 import { Component } from "@angular/core";
 import { Router } from "@angular/router";
 
-import { Archivo } from "../../shared/objects/archivo";
+import { Archivo, Evaluacion } from "../../shared/objects/archivo";
 import { Grupo } from "../../shared/objects/grupo";
 import { Usuario } from "../../shared/objects/usuario";
 import { AuthenticationService } from "../../shared/services/authentication.service";
 import { HaskellService } from "../../shared/services/haskell.service";
 import { SessionService } from "../../shared/services/session.service";
-import { DialogService } from "ng2-bootstrap-modal";
-import { CalificarEntrega } from "./calificarEntrega.component";
 import { NgbPopoverConfig, NgbPopover } from "@ng-bootstrap/ng-bootstrap";
 import { NotificacionService } from "../../shared/services/notificacion.service";
 import { TranslateService } from "@ngx-translate/core";
@@ -36,19 +34,54 @@ export class GruposComponent {
   configCodeMirror = JSON.parse(sessionStorage.getItem("codeMirrorConfig"));
   translateService: any;
 
+  // - - - - - - - - - - - -  Modal show confirm  - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de calificar entrega.
+   */
+  modalQualifyDelivery = false;
+
+  /**
+   * Con `true` se indica que el modal -de calificar entrega- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM.
+   */
+  modalQualifyDeliveryOpened = true;
+
+  /**
+   * Determina los estados posibles para calificar un archivo
+   */
+  posibleStatusesQualifyDelivery = [
+    {
+      value: "Corregido",
+      label: "",
+    },
+    {
+      value: "Devuelto",
+      label: "",
+    },
+  ];
+
   constructor(
     private router: Router,
     private authService: AuthenticationService,
     private haskellService: HaskellService,
     private notifService: NotificacionService,
     private sessionService: SessionService,
-    private dialogService: DialogService,
     public translate: TranslateService
   ) {
     this.translateService = translate;
     this.directorioActual = {};
     this.directorioActual.archivos = [];
     this.configCodeMirror.readOnly = true;
+
+    // Se obtienen las traducciones de los estados posibles de calificación
+    this.translateService.get("i18n.msg.file.evaluated").subscribe((res) => {
+      this.posibleStatusesQualifyDelivery[0].label = res;
+    });
+
+    this.translateService.get("i18n.msg.file.returned").subscribe((res) => {
+      this.posibleStatusesQualifyDelivery[1].label = res;
+    });
   }
 
   ngOnInit() {
@@ -145,19 +178,49 @@ export class GruposComponent {
     this.tipoArchivo = "entrega";
   }
 
-  calificarEntrega() {
-    let disposable = this.dialogService
-      .addDialog(CalificarEntrega, {
-        cedula: JSON.parse(sessionStorage.currentUser).cedula + "",
-        archivo: this.archivoSeleccionado,
-        parentContext: this,
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          //codeMirrorRef.options.readOnly = false;
-          //componentRef.editDialogFired = true;
+  mostrarModalCalificarEntrega() {
+    // Mostrar el modal
+    this.modalQualifyDelivery = true;
+    this.modalQualifyDeliveryOpened = true;
+  }
+
+  confirmFileQualify(event: CustomEvent<any>) {
+    const { descripcion, estado, nota } = event.detail;
+
+    // Si la nota está fuera de rango, se devuelve un error
+    if (!(nota >= 0 && nota <= 100)) {
+      this.translateService
+        .get("i18n.warning.file.qualifyOutRange")
+        .subscribe((res) => this.notifService.error(res));
+      return;
+    }
+
+    const cedula = JSON.parse(sessionStorage.currentUser).cedula + "";
+
+    const evaluacion = new Evaluacion();
+    evaluacion.cedulaDocente = cedula;
+    evaluacion.descripcion = descripcion;
+    evaluacion.nota = nota;
+
+    this.haskellService
+      .calificarArchivo(this.archivoSeleccionado.id, estado, evaluacion)
+      .subscribe(
+        (evaluacion) => {
+          this.translateService
+            .get("i18n.msg.file.evaluated")
+            .subscribe((res) => this.notifService.success(res));
+          this.archivoSeleccionado.evaluacion = evaluacion;
+
+          // Cerrar el modal en caso de éxito
+          this.modalQualifyDeliveryOpened = false;
+        },
+        (error) => {
+          this.notifService.error(error);
+
+          // Cerrar el modal en caso de falla
+          this.modalQualifyDeliveryOpened = false;
         }
-      });
+      );
   }
 
   esArchivoGrupo() {
diff --git a/Frontend Angular 4/src/app/layout/grupos/grupos.module.ts b/Frontend Angular 4/src/app/layout/grupos/grupos.module.ts
index a06751a548de3bda59b2d6497d93fafb14604907..5816436ca78a2aebe17f5a7632200fdb34a57a7d 100755
--- a/Frontend Angular 4/src/app/layout/grupos/grupos.module.ts	
+++ b/Frontend Angular 4/src/app/layout/grupos/grupos.module.ts	
@@ -1,14 +1,10 @@
-import { NgModule } from "@angular/core";
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
 import { FormsModule } from "@angular/forms";
 import { GruposComponent } from "./grupos.component";
 import { CommonModule } from "@angular/common";
 import { GruposRoutingModule } from "./grupos-routing.module";
-import { DialogService } from "ng2-bootstrap-modal";
-import { NotificacionService } from "../../shared/services/notificacion.service";
-import { BootstrapModalModule } from "ng2-bootstrap-modal";
 import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
-import { CodemirrorModule } from "ng2-codemirror";
-import { CalificarEntrega } from "./calificarEntrega.component";
+import { LtCodemirrorModule } from "lt-codemirror";
 import { NotificacionModule } from "../../notificacion/notificacion.module";
 import { I18nModule } from "../../shared/modules/translate/i18n.module";
 import { TitleCaseModule } from "../../shared/modules/titlecase.module";
@@ -18,15 +14,14 @@ import { TitleCaseModule } from "../../shared/modules/titlecase.module";
     CommonModule,
     GruposRoutingModule,
     FormsModule,
-    BootstrapModalModule,
     NgbModule,
-    CodemirrorModule,
+    LtCodemirrorModule,
     NotificacionModule,
     I18nModule,
     TitleCaseModule,
   ],
-  declarations: [GruposComponent, CalificarEntrega],
+  declarations: [GruposComponent],
   exports: [GruposComponent],
-  entryComponents: [CalificarEntrega],
+  schemas: [CUSTOM_ELEMENTS_SCHEMA],
 })
 export class GruposModule {}
diff --git a/Frontend Angular 4/src/app/layout/layout.module.ts b/Frontend Angular 4/src/app/layout/layout.module.ts
index e787ba3e307240cfe218a695f8c7246b5ab0f5cf..f331ffe058467ef6ff19cb6309b487c00731e4f9 100755
--- a/Frontend Angular 4/src/app/layout/layout.module.ts	
+++ b/Frontend Angular 4/src/app/layout/layout.module.ts	
@@ -8,7 +8,7 @@ import { LayoutComponent } from "./layout.component";
 import { HeaderComponent, SidebarComponent } from "../shared";
 import { AuthenticationService } from "../shared/services/authentication.service";
 import { HaskellService } from "../shared/services/haskell.service";
-import { CodemirrorModule } from "ng2-codemirror";
+import { LtCodemirrorModule } from "lt-codemirror";
 import { NotificacionModule } from "../notificacion/notificacion.module";
 import { I18nModule } from "../shared/modules/translate/i18n.module";
 import { TitleCaseModule } from "../shared/modules/titlecase.module";
@@ -20,7 +20,7 @@ import { TitleCaseModule } from "../shared/modules/titlecase.module";
     // NgbModule.forRoot(),
     NgbModule,
     LayoutRoutingModule,
-    CodemirrorModule,
+    LtCodemirrorModule,
     NotificacionModule,
     I18nModule,
     TitleCaseModule,
diff --git a/Frontend Angular 4/src/app/layout/matefun/confirm.component.ts b/Frontend Angular 4/src/app/layout/matefun/confirm.component.ts
deleted file mode 100755
index 2f893f43bca85f6e34e61521812e9c4619c4fca3..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/matefun/confirm.component.ts	
+++ /dev/null
@@ -1,44 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-export interface ConfirmModel {
-  title: string;
-  message: string;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <button type="button" class="close" (click)="close()">&times;</button>
-        <!-- <h4 class="modal-title">{{title || 'Confirm'}}</h4> -->
-      </div>
-      <div class="modal-body">
-        <p>{{ message || "" }}</p>
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn btn-primary" (click)="confirm()">
-          {{ "i18n.action.edit" | translate }}
-        </button>
-        <button type="button" class="btn btn-default" (click)="close()">
-          {{ "i18n.action.cancel" | translate }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class ConfirmComponent
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  title: string;
-  message: string;
-  constructor(dialogService: DialogService) {
-    super(dialogService);
-  }
-  confirm() {
-    // we set dialog result as true on click on confirm button,
-    // then we can get dialog result from caller code
-    this.result = true;
-    this.close();
-  }
-}
diff --git a/Frontend Angular 4/src/app/layout/matefun/matefun.component.html b/Frontend Angular 4/src/app/layout/matefun/matefun.component.html
index 07e9ba7030fd260c6830306b5cf8ed623e2e7bef..30b5ed3f23dbfd075b0823ccb8e6c2b4c589fe3c 100755
--- a/Frontend Angular 4/src/app/layout/matefun/matefun.component.html	
+++ b/Frontend Angular 4/src/app/layout/matefun/matefun.component.html	
@@ -318,7 +318,7 @@
                   </ng-template>
                 </form>
               </div>
-              <codemirror
+              <lt-codemirror
                 class="codemirrorPrograma"
                 [(ngModel)]="archivo.contenido"
                 (keyup)="archivoModificado($event)"
@@ -326,7 +326,7 @@
                 [config]="configCodeMirror"
                 [ngStyle]="{ 'font-size': configCodeMirror.fontSize + 'px' }"
               >
-              </codemirror>
+              </lt-codemirror>
             </div>
           </ng-template>
         </ngb-tab>
@@ -345,6 +345,7 @@
             ></graph2D-component>
           </ng-template>
         </ngb-tab>
+
         <ngb-tab
           id="FigurasBtn3D"
           title="{{ 'i18n.object.figures' | translate | titleCase }} 3D"
@@ -409,7 +410,7 @@
             </button>
           </form>
         </div>
-        <codemirror
+        <lt-codemirror
           class="codemirrorPrograma"
           [(ngModel)]="archivoDefinicion.contenido"
           [config]="configCodeMirrorDefinicion"
@@ -417,9 +418,56 @@
             'font-size': configCodeMirrorDefinicion.fontSize + 'px'
           }"
         >
-        </codemirror>
+        </lt-codemirror>
       </div>
     </div>
   </div>
   <span class="version">v{{ version }}</span>
 </div>
+
+<matefun-modal-seleccionar-directorio
+  confirmLabel="{{ 'i18n.action.create' | translate | titleCase }}"
+  [currentDirectory]="archivosTree"
+  fileNameLabel="{{ 'i18n.object.name' | translate | titleCase }}:"
+  header="{{ 'i18n.msg.file.create' | translate }}"
+  [import]="importCreateFile"
+  importLabel="{{ 'i18n.object.file' | translate | titleCase }}:"
+  navigateBackLabel="{{ 'i18n.action.goBack' | translate | titleCase }}"
+  [opened]="modalCreateFileOpened"
+  (close)="modalCreateFile = false"
+  (confirmFileCreation)="confirmFileCreation($event)"
+  (navBack)="navigateBack($event)"
+  (navTo)="archivosTree = $event.detail"
+  *ngIf="modalCreateFile"
+>
+</matefun-modal-seleccionar-directorio>
+
+<matefun-modal
+  [opened]="modalShowConfirmOpened"
+  (close)="modalShowConfirm = false"
+  *ngIf="modalShowConfirm"
+>
+  <span slot="header">Está intentando editar un archivo de solo lectura</span>
+
+  <span slot="body">
+    Está editando un archivo de solo lectura, ¿desea continuar?
+  </span>
+
+  <button
+    slot="primary-action"
+    type="button"
+    class="btn btn-primary"
+    (click)="allowFileEdition()"
+  >
+    {{ "i18n.action.edit" | translate | titleCase }}
+  </button>
+
+  <button
+    slot="primary-action"
+    type="button"
+    class="btn btn-default"
+    (click)="modalShowConfirmOpened = false"
+  >
+    {{ "i18n.action.cancel" | translate | titleCase }}
+  </button>
+</matefun-modal>
diff --git a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts
index 1a6073bbd209ef74bd9a6fe9667623a0aac9e7ba..36fdb1b24bc0c1b27adee5b5ad83d5e9ae5aa48b 100755
--- a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts	
+++ b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts	
@@ -1,38 +1,28 @@
 import {
   Component,
-  NgModule,
   ViewChild,
   HostListener,
-  ElementRef,
   ComponentRef,
-  TemplateRef,
   QueryList,
   ViewChildren,
 } from "@angular/core";
-import { CanvasModule } from "../canvas/canvas.module";
-import { CanvasComponent } from "../canvas/canvas.component";
 import { HaskellService } from "../../shared/services/haskell.service";
 import { WebsocketService } from "../../shared/services/websocket.service";
 import { UsuarioService } from "../../shared/services/usuario.service";
 import { SessionService } from "../../shared/services/session.service";
 import { GHCIService } from "../../shared/services/ghci.service";
 import { AuthenticationService } from "../../shared/services/authentication.service";
-import { GHCI_URL } from "../../shared/config";
 import { Archivo } from "../../shared/objects/archivo";
 import { Configuracion } from "../../shared/objects/usuario";
-import { ConfirmComponent } from "./confirm.component";
-import { SeleccionarDirectorioComp } from "./seleccionarDirectorio.component";
-import { DialogService } from "ng2-bootstrap-modal";
-import { CodemirrorComponent } from "ng2-codemirror";
+import { LtCodemirrorComponent } from "lt-codemirror";
 import { NgbPopoverConfig, NgbPopover } from "@ng-bootstrap/ng-bootstrap";
 import { NgbPopoverWindow } from "@ng-bootstrap/ng-bootstrap/popover/popover";
 import { NotificacionService } from "../../shared/services/notificacion.service";
-import { Graph2DModule } from "../plotter/graph2D/graph2D.module";
 import { Graph2DComponent } from "../plotter/graph2D/graph2D.component";
 import { Graph3DComponent } from "../plotter/graph3D/graph3D.component";
 import { TranslateService } from "@ngx-translate/core";
 import { TitleCasePipe } from "../../shared/pipes/titlecase.pipe";
-import { Router, NavigationExtras } from "@angular/router";
+import { Router } from "@angular/router";
 
 // import 'codemirror/mode/haskell/haskell';
 import "codemirror/addon/display/panel";
@@ -55,8 +45,6 @@ import "./codemirror/matefun-mode-EN.js";
 import "./codemirror/addons/functions_definition_EN.js";
 import "./codemirror/addons/functions_definition_ES.js";
 
-import * as npm from "./../../../../package.json";
-
 var codeMirrorRef: any;
 var componentRef: any;
 var focus: any;
@@ -167,14 +155,45 @@ export class MateFunComponent {
   ];
   version: string = "3.1.3"; //npm.version;
 
+  // - - - - - - - - - - - - - Modal create file - - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de crear un archivo en un directorio.
+   */
+  modalCreateFile = false;
+
+  /**
+   * Con `true` se indica que el modal -de crear un archivo- se quiere abrir.
+   * Útil para avisar al modal que anime el dismiss antes de que se elimine del
+   * DOM.
+   */
+  modalCreateFileOpened = true;
+
+  /**
+   * Con `true` se renderiza un input para importar el contenido del archivo a
+   * crear en el modal de crear archivo.
+   */
+  importCreateFile = false;
+
+  // - - - - - - - - - - - -  Modal show confirm  - - - - - - - - - - - -
+  /**
+   * Con `true` se renderiza el modal de preguntar para editar un archivo de
+   * solo lectura.
+   */
+  modalShowConfirm = false;
+
+  /**
+   * Con `true` se indica que el modal -de preguntar para editar un archivo de
+   * solo lectura- se quiere abrir. Útil para avisar al
+   * modal que anime el dismiss antes de que se elimine del DOM.
+   */
+  modalShowConfirmOpened = true;
+
   constructor(
     private haskellService: HaskellService,
     private authService: AuthenticationService,
     private ghciService: GHCIService,
-    private elRef: ElementRef,
     private notifService: NotificacionService,
     private sessionService: SessionService,
-    private dialogService: DialogService,
     private usuarioService: UsuarioService,
     public translate: TranslateService,
     private router: Router
@@ -206,7 +225,6 @@ export class MateFunComponent {
       this.argumentoF = config.argumentoF;
     }
     this.code = "my code";
-    let svg: string = "";
 
     for (var key in this.configCodeMirror) {
       this.configCodeMirrorDefinicion[key] = this.configCodeMirror[key];
@@ -214,7 +232,8 @@ export class MateFunComponent {
     this.configCodeMirrorDefinicion["readOnly"] = true;
   }
 
-  @ViewChildren(CodemirrorComponent) codemirror: QueryList<CodemirrorComponent>;
+  @ViewChildren(LtCodemirrorComponent)
+  codemirror: QueryList<LtCodemirrorComponent>;
   // @ViewChild(NgbPopover) popover: NgbPopover;
   @ViewChild("popover", { static: false }) popover: NgbPopover;
 
@@ -234,17 +253,17 @@ export class MateFunComponent {
   }
 
   showConfirm() {
-    let disposable = this.dialogService
-      .addDialog(ConfirmComponent, {
-        title: "Está intentando editar un archivo de solo lectura",
-        message: "Está editando un archivo de solo lectura, desea continuar?",
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          codeMirrorRef.options.readOnly = false;
-          componentRef.editDialogFired = true;
-        }
-      });
+    // Mostrar el modal
+    this.modalShowConfirm = true;
+    this.modalShowConfirmOpened = true;
+  }
+
+  allowFileEdition() {
+    codeMirrorRef.options.readOnly = false;
+    componentRef.editDialogFired = true;
+
+    // Cerrar el modal
+    this.modalShowConfirmOpened = false;
   }
 
   /* Panel para la posición del cursor */
@@ -281,7 +300,7 @@ export class MateFunComponent {
 
     this.codemirror.first.instance.on("keyHandled", function (cm, name, evt) {
       if (name.code === "Digit1" && name.ctrlKey && name.shiftKey) {
-        that.seleccionarDirectorio(false);
+        that.seleccionarDirectorio();
       } else if (name.code === "Digit2" && name.ctrlKey && name.shiftKey) {
         that.saveConfig();
       }
@@ -773,26 +792,76 @@ export class MateFunComponent {
     this.consolaVisible = !this.consolaVisible;
   }
 
-  seleccionarDirectorio(toImport: boolean) {
+  seleccionarDirectorio(importFileContent = false) {
     this.archivosTree = this.sessionService.getArchivos(undefined);
 
-    var that = this;
-    let disposable = this.dialogService
-      .addDialog(SeleccionarDirectorioComp, {
-        title: "",
-        import: toImport,
-        message: "",
-        archivos: this.archivosTree,
-        directorioActual: this.archivosTree,
-        nombre: "",
-        parent: this,
-      })
-      .subscribe((isConfirmed) => {
-        if (isConfirmed) {
-          //codeMirrorRef.options.readOnly = false;
-          //componentRef.editDialogFired = true;
-        }
-      });
+    this.importCreateFile = importFileContent;
+
+    // Mostrar el modal
+    this.modalCreateFile = true;
+    this.modalCreateFileOpened = true;
+  }
+
+  confirmFileCreation(event: CustomEvent) {
+    const fileContent = event.detail.fileContent;
+    const nombre = event.detail.nombre;
+    const padreId = event.detail.padreId;
+
+    if (nombre == undefined || nombre == "") {
+      this.notifService.error(
+        this.translateService.get("i18n.warning.file.invalidName").value
+      );
+      return;
+    }
+
+    /** Expresión regular para chequear que el nombre esté empiece con mayúscula */
+    var regex = /^[A-Z]/;
+
+    if (!regex.test(nombre)) {
+      this.notifService.error(
+        this.translateService.get("i18n.warning.file.capitalLetter").value
+      );
+      return;
+    }
+
+    var archivo: Archivo = new Archivo();
+    archivo.cedulaCreador = this.authService.getUser().cedula;
+    archivo.contenido = fileContent;
+    archivo.nombre = nombre;
+    archivo.directorio = false;
+    archivo.padreId = padreId;
+    archivo.editable = true;
+
+    this.haskellService.crearArchivo(archivo).subscribe(
+      (archivo) => {
+        this.archivo = archivo;
+        //this.parent.ghciService.loadFile(archivo.id);
+        this.sessionService.setArchivo(archivo);
+
+        // Cerrar el modal en caso de exito
+        this.modalCreateFileOpened = false;
+      },
+      (error) => {
+        this.notifService.error(error.text());
+
+        // Cerrar el modal en caso de falla
+        this.modalCreateFileOpened = false;
+      }
+    );
+  }
+
+  navigateBack(event: CustomEvent<Archivo>) {
+    const { padreId } = event.detail;
+
+    // No se puede navegar al padre de root
+    if (padreId == -1) {
+      return;
+    }
+
+    const archivosList: Archivo[] = this.sessionService.getArchivosList();
+
+    // Se queda con el archivo identificado por padreId
+    this.archivosTree = archivosList.filter((file) => file.id === padreId)[0];
   }
 
   buildTreeFromList(archivos) {
diff --git a/Frontend Angular 4/src/app/layout/matefun/matefun.module.ts b/Frontend Angular 4/src/app/layout/matefun/matefun.module.ts
index bc415fcbac0643417ca69f6787fc3c3dbd06b206..17c3b6d38f4540577edf1021a5acfcf93d282c31 100755
--- a/Frontend Angular 4/src/app/layout/matefun/matefun.module.ts	
+++ b/Frontend Angular 4/src/app/layout/matefun/matefun.module.ts	
@@ -1,13 +1,10 @@
-import { NgModule } from "@angular/core";
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
 import { FormsModule } from "@angular/forms";
 import { CanvasModule } from "../canvas/canvas.module";
 import { MateFunComponent } from "./matefun.component";
-import { BootstrapModalModule } from "ng2-bootstrap-modal";
-import { ConfirmComponent } from "./confirm.component";
-import { SeleccionarDirectorioComp } from "./seleccionarDirectorio.component";
 import { CommonModule } from "@angular/common";
 import { MateFunRoutingModule } from "./matefun-routing.module";
-import { CodemirrorModule } from "ng2-codemirror";
+import { LtCodemirrorModule } from "lt-codemirror";
 import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
 import { NotificacionModule } from "../../notificacion/notificacion.module";
 import { Graph2DModule } from "../plotter/graph2D/graph2D.module";
@@ -24,14 +21,13 @@ import { TitleCaseModule } from "../../shared/modules/titlecase.module";
     Graph3DModule,
     NotificacionModule,
     MateFunRoutingModule,
-    CodemirrorModule,
+    LtCodemirrorModule,
     NgbModule,
-    BootstrapModalModule,
     I18nModule,
     TitleCaseModule,
   ],
-  entryComponents: [ConfirmComponent, SeleccionarDirectorioComp],
-  declarations: [MateFunComponent, ConfirmComponent, SeleccionarDirectorioComp],
+  declarations: [MateFunComponent],
   exports: [MateFunComponent],
+  schemas: [CUSTOM_ELEMENTS_SCHEMA],
 })
 export class MateFunModule {}
diff --git a/Frontend Angular 4/src/app/layout/matefun/seleccionarDirectorio.component.ts b/Frontend Angular 4/src/app/layout/matefun/seleccionarDirectorio.component.ts
deleted file mode 100755
index aa00cb392a99dfb671abd0565462375eac9e7b15..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/layout/matefun/seleccionarDirectorio.component.ts	
+++ /dev/null
@@ -1,199 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-import { Archivo } from "../../shared/objects/archivo";
-import { TranslateService } from "@ngx-translate/core";
-
-export interface ConfirmModel {
-  title: string;
-  message: string;
-  archivos: any;
-  directorioActual: any;
-  import: boolean;
-  parent: any;
-  nombre: string;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h6 class="modal-title pull-lefth">
-          {{ "i18n.msg.file.create" | translate }}
-        </h6>
-        <button
-          type="button"
-          class="close"
-          (click)="close()"
-          style="margin-rigth:8px;"
-        >
-          &times;
-        </button>
-      </div>
-      <div class="modal-body" style="height:350px;overflow-y: scroll;">
-        <div>
-          <div class="form-group">
-            <label for="file-name" class="form-control-label"
-              >{{ "i18n.object.name" | translate | titleCase }}:</label
-            >
-            <input
-              type="text"
-              class="form-control"
-              id="file-name"
-              [(ngModel)]="nombre"
-            />
-          </div>
-          <div class="list-group">
-            <button
-              *ngFor="
-                let arch of directorioActual.archivos.filter(esDirectorio)
-              "
-              type="button"
-              (click)="navToDir(arch)"
-              style="cursor:pointer"
-              class="list-group-item list-group-item-action"
-            >
-              <i
-                *ngIf="arch.directorio"
-                class="fa fa-folder"
-                style="margin-right:10px; font-size: 3em; cursor: pointer;"
-                aria-hidden="true"
-              ></i>
-              <i
-                *ngIf="!arch.directorio"
-                class="fa fa-file-text"
-                style="margin-right:10px;font-size: 3em; cursor: pointer;"
-                aria-hidden="true"
-              ></i>
-              {{ arch.nombre }}
-            </button>
-          </div>
-          <div *ngIf="import" class="form-group">
-            <br />
-            <label for="file-name" class="form-control-label"
-              >{{ "i18n.object.file" | translate | titleCase }}:</label
-            ><br />
-            <input
-              id="fileid"
-              type="file"
-              (change)="changeListener($event)"
-              #input
-            />
-          </div>
-        </div>
-      </div>
-      <div class="modal-footer">
-        <button
-          [disabled]="this.directorioActual.padreId == -1"
-          type="button"
-          class="btn btn-default"
-          (click)="navBack()"
-        >
-          {{ "i18n.action.goBack" | translate | titleCase }}
-        </button>
-        <button
-          [disabled]="this.nombre == '' || (import && filecontent == '')"
-          type="button"
-          class="btn btn-primary"
-          (click)="confirm()"
-        >
-          {{ "i18n.action.create" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class SeleccionarDirectorioComp
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  title: string;
-  message: string;
-  archivos: any;
-  directorioActual: any;
-  parent: any;
-  nombre: string;
-  translateService: any;
-  import: boolean;
-  filecontent: string = "";
-
-  constructor(
-    dialogService: DialogService,
-    public translate: TranslateService
-  ) {
-    super(dialogService);
-    this.translateService = translate;
-  }
-  esDirectorio(archivo) {
-    return archivo.directorio;
-  }
-
-  changeListener($event): void {
-    this.readThis($event.target);
-  }
-
-  readThis(inputValue: any): void {
-    var file: File = inputValue.files[0];
-    var myReader: FileReader = new FileReader();
-    var fileType = inputValue.parentElement.id;
-
-    myReader.onloadend = (e) => {
-      this.filecontent = myReader.result as string;
-    };
-
-    myReader.readAsText(file);
-  }
-
-  confirm() {
-    // we set dialog result as true on click on confirm button,
-    // then we can get dialog result from caller code
-    var regex = /^[A-Z]/;
-    if (this.nombre == undefined || this.nombre == "") {
-      this.parent.notifService.error(
-        this.translateService.get("i18n.warning.file.invalidName").value
-      );
-    } else if (!regex.test(this.nombre)) {
-      this.parent.notifService.error(
-        this.translateService.get("i18n.warning.file.capitalLetter").value
-      );
-    } else {
-      var archivo: Archivo = new Archivo();
-      archivo.cedulaCreador = this.parent.authService.getUser().cedula;
-      archivo.contenido = this.filecontent;
-      archivo.nombre = this.nombre;
-      archivo.directorio = false;
-      archivo.padreId = this.directorioActual.id;
-      archivo.editable = true;
-
-      this.parent.haskellService.crearArchivo(archivo).subscribe(
-        (archivo) => {
-          this.parent.archivo = archivo;
-          //this.parent.ghciService.loadFile(archivo.id);
-          this.parent.sessionService.setArchivo(archivo);
-        },
-        (error) => {
-          this.parent.notifService.error(error.text());
-        }
-      );
-
-      this.result = true;
-      this.close();
-    }
-  }
-
-  navToDir(arch) {
-    if (arch.directorio) {
-      this.directorioActual = arch;
-    }
-  }
-
-  navBack() {
-    if (this.directorioActual.padreId != -1) {
-      var idPadre = this.directorioActual.padreId;
-      var archivosList = this.parent.sessionService.getArchivosList();
-      var nuevoDirectorioActual = archivosList.filter(function (a) {
-        return a.id === idPadre;
-      })[0];
-      this.directorioActual = nuevoDirectorioActual;
-    }
-  }
-}
diff --git a/Frontend Angular 4/src/app/shared/modal/confirm.component.ts b/Frontend Angular 4/src/app/shared/modal/confirm.component.ts
deleted file mode 100755
index 5d8b36c4213819f8d645c40043c20b5fddf6a8e2..0000000000000000000000000000000000000000
--- a/Frontend Angular 4/src/app/shared/modal/confirm.component.ts	
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Component } from "@angular/core";
-import { DialogComponent, DialogService } from "ng2-bootstrap-modal";
-export interface ConfirmModel {
-  title: string;
-  message: string;
-  confirmText: string;
-  cancelText: string;
-}
-@Component({
-  selector: "confirm",
-  template: `<div class="modal-dialog" style="margin-top:100px;">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h4 class="modal-title">{{ title || "Confirm" }}</h4>
-        <button type="button" class="close" (click)="close()">&times;</button>
-      </div>
-      <div class="modal-body">
-        <p style="white-space: pre;">{{ message || "" }}</p>
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn btn-primary" (click)="confirm()">
-          {{ confirmText || "i18n.action.confirm" | translate | titleCase }}
-        </button>
-        <button type="button" class="btn btn-default" (click)="close()">
-          {{ cancelText || "i18n.action.cancel" | translate | titleCase }}
-        </button>
-      </div>
-    </div>
-  </div>`,
-})
-export class ConfirmComponent
-  extends DialogComponent<ConfirmModel, boolean>
-  implements ConfirmModel
-{
-  title: string;
-  message: string;
-  confirmText: string;
-  cancelText: string;
-
-  constructor(dialogService: DialogService) {
-    super(dialogService);
-  }
-  confirm() {
-    // we set dialog result as true on click on confirm button,
-    // then we can get dialog result from caller code
-    this.result = true;
-    this.close();
-  }
-}
diff --git a/Frontend Angular 4/src/app/shared/objects/archivo.ts b/Frontend Angular 4/src/app/shared/objects/archivo.ts
index b47b32d65a66cd698f25433bbb45cc606f3c3672..2821c248704ced49adf3247650304dc5d3435942 100755
--- a/Frontend Angular 4/src/app/shared/objects/archivo.ts	
+++ b/Frontend Angular 4/src/app/shared/objects/archivo.ts	
@@ -23,3 +23,12 @@ export class Archivo {
 
   constructor() {}
 }
+
+export class Grupo {
+  anio: number;
+  grado: number;
+  grupo: string;
+  liceoId: number;
+
+  constructor() {}
+}
diff --git a/Frontend Angular 4/src/assets/i18n/en.json b/Frontend Angular 4/src/assets/i18n/en.json
index 577c1505d43525e4d0ea49b1d9604ba16d152571..56fbc955ae5b8c9062ccc4d63cb5fc5edfd7a9e8 100755
--- a/Frontend Angular 4/src/assets/i18n/en.json	
+++ b/Frontend Angular 4/src/assets/i18n/en.json	
@@ -1,152 +1,150 @@
 {
-    "i18n" : {
-        "code" : "en",
-        "action" : {
-            "login" : "login",
-            "new" : "new",
-            "load" : "load",
-            "reload" : "reload",
-            "restart" : "restart",
-            "save" : "save",
-            "export" : "export",
-	    "import" : "import",
-            "zoom" : "zoom",
-            "center" : "center",
-            "delete" : "delete",
-            "download": "download",
-            "exit" : "exit",
-            "order": "order",
-            "edit" : "edit",
-            "move" : "move",
-            "share" : "share",
-            "shared" : "shared",
-            "created": "created",
-            "send" : "send",
-            "sent" : "sent",
-            "cancel" : "cancel",
-            "create" : "create",
-            "goBack" : "go back",
-            "close" : "close",
-            "qualify" : "qualify",
-            "confirm" : "confirm"
-        },
-        "object" : {
-            "settings" : "settings",
-            "shortcuts" : "shortcuts",
-            "theme" : "theme",
-            "name" : "name",
-            "descr" : "description",
-            "user" : "user",
-            "password" : "password",
-            "guest" : "guest",
-            "program" : "program",
-            "figure" : "figure",
-            "figures" : "figures",
-            "file" : "file",
-            "files" : "files",
-            "group" : "group",
-            "groups" : "groups",
-            "interpreter" : "interpreter",
-            "axis" : "axis",
-            "axes" : "axes",
-            "grid" : "grid",
-            "tip" : "tip",
-            "normal" : "normal",
-            "quality" : "quality",
-            "folder" : "folder",
-            "here" : "here",
-            "qualification" : "qualification",
-            "date" : "date",
-            "detail" : "detail",
-            "score" : "score",
-            "state" : "state"
-        },
-        "codemirror" : {
-            "command" : {
-                "inLine" : "in line",
-                "column" : "column",
-                "inColumn" : "In column",
-                "line" : "line",
-                "outWarning" : "OUTWarning",
-                "outError" : "OUTError"
-            }
-        },
-        "msg" : {
-            "404" : {
-                "title": "Page Not Found",
-                "descrp": "Sorry, this page does not exist.",
-                "return": "Return"
-            },
-            "codemirror" : {
-                "fontSize" : "Font Size",
-                "functionWarnings": "Show warnings of use of functions",
-                "infixOperatorsWarnings" : "Show warnings of use of infix operators",
-                "cursorPosition" : "Cursor position",
-                "showHints" : "Show autocomplete hints",
-                "functionTyping" : "Show functions typing",
-                "consoleWarnings": "Program contains warnings"
-            },
-            "figure" : {
-                "multiPlot" : "Multi graph",
-                "animationSpeed" : "Animation speed"
-            },
-            "file" : {
-                "fileName" : "File name",
-                "preview" : "Select a file to preview",
-                "myFiles" : "My files",
-                "readOnly": "Read Only",
-                "viewCalification": "View Calification",
-                "modified": "Modified file",
-                "toSend" : "Do you want to send the file {{fileName}}?",
-                "toSendInfo" : "The file can't be edited after being sent.",
-                "delete" : "Are you want to delete the {{fileName}} file?",
-                "seeOriginal" : "See original",
-                "seeMine" : "See mine",
-                "share" : "Share &quot;{{fileName}}&quot; with:",
-                "shared" : "Shared file",
-                "move" : "Where do you want to move the file?",
-                "create" : "Where do you want to create the file?",
-                "qualify" : "Qualify the delivered file",
-                "evaluated" : "Evaluated file",
-                "returned" : "Evaluated file (re-send)"
-
-            },
-            "folder" : {
-                "delete" : "Are you want to delete the {{fileName}} folder?"
-            },
-            "order" : {
-                "kind" : "Kind",
-                "date" : "Date"
-            }
-        },
-        "warning" : {
-            "file" : {
-                "noSelected" : "File not selected",
-                "noPermissionDelete" : "No permissions to delete the file",
-                "noPermissionMove" : "No permissions to move the file",
-                "capitalLetter" : "File name must start with upper case.",
-                "qualifyOutRange" : "Qualification out of range",
-                "invalidName" : "Invalid file name."
-            },
-            "group" : {
-                "select" : "Select a group"
-            }
-        },
-        "shortcuts" : {
-            "runCode" : "Execute the code",
-            "newFile" : "New file",
-            "openMenu" : "Open options menu",
-            "exportFile" : "Export file",
-            "importFile" : "Import file",
-            "restartInterpreter" : "Restart interpreter",
-            "saveFile" : "Save File",
-            "autocomplete" : "Autocomplete",
-            "space" : "Space",
-            "comment" : "Comment/Uncomment",
-            "functionNavigation" : "Jump to the definition",
-    	    "focusProgram" : "Focus on Program",
-	    "focusInterpreter" : "Focus on Interpreter"
-
-        }
+  "i18n": {
+    "code": "en",
+    "action": {
+      "login": "login",
+      "new": "new",
+      "load": "load",
+      "reload": "reload",
+      "restart": "restart",
+      "save": "save",
+      "export": "export",
+      "import": "import",
+      "zoom": "zoom",
+      "center": "center",
+      "delete": "delete",
+      "download": "download",
+      "exit": "exit",
+      "order": "order",
+      "edit": "edit",
+      "move": "move",
+      "share": "share",
+      "shared": "shared",
+      "created": "created",
+      "send": "send",
+      "sent": "sent",
+      "cancel": "cancel",
+      "create": "create",
+      "goBack": "go back",
+      "close": "close",
+      "qualify": "qualify",
+      "confirm": "confirm"
+    },
+    "object": {
+      "settings": "settings",
+      "shortcuts": "shortcuts",
+      "theme": "theme",
+      "name": "name",
+      "descr": "description",
+      "user": "user",
+      "password": "password",
+      "guest": "guest",
+      "program": "program",
+      "figure": "figure",
+      "figures": "figures",
+      "file": "file",
+      "files": "files",
+      "group": "group",
+      "groups": "groups",
+      "interpreter": "interpreter",
+      "axis": "axis",
+      "axes": "axes",
+      "grid": "grid",
+      "tip": "tip",
+      "normal": "normal",
+      "quality": "quality",
+      "folder": "folder",
+      "here": "here",
+      "qualification": "qualification",
+      "date": "date",
+      "detail": "detail",
+      "score": "score",
+      "state": "state"
+    },
+    "codemirror": {
+      "command": {
+        "inLine": "in line",
+        "column": "column",
+        "inColumn": "In column",
+        "line": "line",
+        "outWarning": "OUTWarning",
+        "outError": "OUTError"
+      }
+    },
+    "msg": {
+      "404": {
+        "title": "Page Not Found",
+        "descrp": "Sorry, this page does not exist.",
+        "return": "Return"
+      },
+      "codemirror": {
+        "fontSize": "Font Size",
+        "functionWarnings": "Show warnings of use of functions",
+        "infixOperatorsWarnings": "Show warnings of use of infix operators",
+        "cursorPosition": "Cursor position",
+        "showHints": "Show autocomplete hints",
+        "functionTyping": "Show functions typing",
+        "consoleWarnings": "Program contains warnings"
+      },
+      "figure": {
+        "multiPlot": "Multi graph",
+        "animationSpeed": "Animation speed"
+      },
+      "file": {
+        "fileName": "File name",
+        "preview": "Select a file to preview",
+        "myFiles": "My files",
+        "readOnly": "Read Only",
+        "viewCalification": "View Calification",
+        "modified": "Modified file",
+        "toSend": "Do you want to send the file {{fileName}}?",
+        "toSendInfo": "The file can't be edited after being sent.",
+        "delete": "Are you want to delete the {{fileName}} file?",
+        "seeOriginal": "See original",
+        "seeMine": "See mine",
+        "share": "Share \"{{fileName}}\" with:",
+        "shared": "Shared file",
+        "move": "Where do you want to move the file?",
+        "create": "Where do you want to create the file?",
+        "qualify": "Qualify the delivered file",
+        "evaluated": "Evaluated file",
+        "returned": "Evaluated file (re-send)"
+      },
+      "folder": {
+        "delete": "Are you want to delete the {{fileName}} folder?"
+      },
+      "order": {
+        "kind": "Kind",
+        "date": "Date"
+      }
+    },
+    "warning": {
+      "file": {
+        "noSelected": "File not selected",
+        "noPermissionDelete": "No permissions to delete the file",
+        "noPermissionMove": "No permissions to move the file",
+        "capitalLetter": "File name must start with upper case.",
+        "qualifyOutRange": "Qualification out of range",
+        "invalidName": "Invalid file name."
+      },
+      "group": {
+        "select": "Select a group"
+      }
+    },
+    "shortcuts": {
+      "runCode": "Execute the code",
+      "newFile": "New file",
+      "openMenu": "Open options menu",
+      "exportFile": "Export file",
+      "importFile": "Import file",
+      "restartInterpreter": "Restart interpreter",
+      "saveFile": "Save File",
+      "autocomplete": "Autocomplete",
+      "space": "Space",
+      "comment": "Comment/Uncomment",
+      "functionNavigation": "Jump to the definition",
+      "focusProgram": "Focus on Program",
+      "focusInterpreter": "Focus on Interpreter"
     }
+  }
 }
diff --git a/Frontend Angular 4/src/assets/i18n/es.json b/Frontend Angular 4/src/assets/i18n/es.json
index 8d1fa3f59ba092f71ff3e5e426513997b5c2e6a1..13ab990f919deb017d0fd2e1fe241a1a5ac78531 100755
--- a/Frontend Angular 4/src/assets/i18n/es.json	
+++ b/Frontend Angular 4/src/assets/i18n/es.json	
@@ -1,150 +1,150 @@
 {
-    "i18n" : {
-        "code" : "es",
-        "action" : {
-            "login" : "iniciar sesión",
-            "new" : "nuevo",
-            "load" : "cargar",
-            "reload" : "recargar",
-            "restart" : "reiniciar",
-            "save" : "guardar",
-            "export" : "exportar",
-	    "import" : "importar",
-            "zoom" : "zoom",
-            "center" : "centrar",
-            "delete" : "borrar",
-            "download": "descargar",
-            "exit" : "salir",
-            "order": "ordenar",
-            "edit": "editar",
-            "move": "mover",
-            "share": "compartir",
-            "shared" : "compartidos",
-            "created": "creado",
-            "send" : "enviar",
-            "sent" : "enviado",
-            "cancel" : "cancelar",
-            "create" : "crear",
-            "goBack" : "atrás",
-            "close" : "cerrar",
-            "qualify" : "calificar",
-            "confirm" : "confirmar"
-        },
-        "object" : {
-            "settings" : "configuración",
-            "shortcuts" : "atajos",
-            "name" : "nombre",
-            "descr" : "descripción",
-            "user" : "usuario",
-            "theme" : "tema",
-            "password" : "contraseña",
-            "guest" : "invitado",
-            "program" : "programa",
-            "figure" : "figura",
-            "figures" : "figuras",
-            "file" : "archivo",
-            "files" : "archivos",
-            "group" : "grupo",
-            "groups" : "grupos",
-            "interpreter" : "intérprete",
-            "axis" : "eje",
-            "axes" : "ejes",
-            "grid" : "grilla",
-            "tip" : "tip",
-            "normal" : "normal",
-            "quality" : "calidad",
-            "folder" : "carpeta",
-            "here" : "aquí",
-            "qualification" : "calificación",
-            "date" : "fecha",
-            "detail" : "detalle",
-            "score" : "puntaje",
-            "state" : "estado"
-        },
-        "codemirror" : {
-            "command" : {
-                "inLine" : "en linea",
-                "column" : "columna",
-                "inColumn" : "En columna",
-                "line" : "linea",
-                "outWarning" : "OUTAdvertencia",
-                "outError" : "OUTError"
-            }
-        },
-        "msg" : {
-            "404" : {
-                "title": "Página no encontrada",
-                "descrp": "Lo sentimos, esta página no existe.",
-                "return": "Volver"
-            },
-            "codemirror" : {
-                "fontSize" : "Tamaño de fuente",
-                "functionWarnings": "Mostrar advertencias de uso de funciones",
-                "infixOperatorsWarnings" : "Mostrar advertencias de uso de operadores infijos",
-                "cursorPosition" : "Posición del cursor",
-                "showHints" : "Mostrar sugerencias de autocompletar",
-                "functionTyping" : "Mostrar tipado de funciones",
-                "consoleWarnings": "El programa contiene advertencias"
-            },
-            "figure" : {
-                "multiPlot" : "Multi gráfica",
-                "animationSpeed" : "Velocidad de animación"
-            },
-            "file" : {
-                "fileName" : "Nombre de archivo",
-                "preview" : "Seleccione un archivo para previsualizarlo",
-                "myFiles" : "Mis archivos",
-                "readOnly": "Sólo lectura",
-                "viewCalification": "Ver Calificación",
-                "modified": "Archivo modificado",
-                "toSend" : "¿Desea enviar el archivo {{fileName}}?",
-                "toSendInfo" : "No se podrá editar luego de enviado.",
-                "delete" : "¿Está seguro que desea eliminar el archivo {{fileName}}?",
-                "seeOriginal" : "Ver original",
-                "seeMine" : "Ver mio",
-                "share" : "Compartir &quot;{{fileName}}&quot; con:",
-                "shared" : "Archivo compartido",
-                "move" : "¿Dónde quieres mover el archivo?",
-                "create" : "¿Dónde quieres crear el archivo?",
-                "qualify" : "Calificar entrega",
-                "evaluated" : "Archivo evaluado",
-                "returned" : "Archivo evaluado (re-entrega)"
-            },
-            "folder" : {
-                "delete" : "¿Está seguro que desea eliminar la carpeta {{fileName}}?"
-            },
-            "order" : {
-                "kind" : "Tipo",
-                "date" : "Fecha"
-            }
-        },
-        "warning" : {
-            "file" : {
-                "noSelected" : "Archivo no seleccionado",
-                "noPermissionDelete" : "Sin permisos para eliminar el archivo",
-                "noPermissionMove" : "Sin permisos para mover el archivo",
-                "capitalLetter" : "Nombre de archivo debe iniciar con mayúscula.",
-                "qualifyOutRange" : "Calificación fuera de rango",
-                "invalidName" : "Nombre de archivo inválido."
-            },
-            "group" : {
-                "select" : "Seleccione un grupo"
-            }
-        },
-        "shortcuts" : {
-            "runCode" : "Ejecutar el código",
-            "newFile" : "Nuevo archivo",
-            "openMenu" : "Abrir menú de opciones",
-            "exportFile" : "Exportar archivo",
-            "importFile" : "Importar archivo",
-            "restartInterpreter" : "Reiniciar intérprete",
-            "saveFile" : "Guardar archivo",
-            "autocomplete" : "Autocompletar",
-            "space" : "Espacio",
-            "comment" : "Comentar/Descomentar",
-            "functionNavigation" : "Saltar a la definición",
-	    "focusProgram" : "Foco en Programa",
-	    "focusInterpreter" : "Foco en Interprete"
-        }
+  "i18n": {
+    "code": "es",
+    "action": {
+      "login": "iniciar sesión",
+      "new": "nuevo",
+      "load": "cargar",
+      "reload": "recargar",
+      "restart": "reiniciar",
+      "save": "guardar",
+      "export": "exportar",
+      "import": "importar",
+      "zoom": "zoom",
+      "center": "centrar",
+      "delete": "borrar",
+      "download": "descargar",
+      "exit": "salir",
+      "order": "ordenar",
+      "edit": "editar",
+      "move": "mover",
+      "share": "compartir",
+      "shared": "compartidos",
+      "created": "creado",
+      "send": "enviar",
+      "sent": "enviado",
+      "cancel": "cancelar",
+      "create": "crear",
+      "goBack": "atrás",
+      "close": "cerrar",
+      "qualify": "calificar",
+      "confirm": "confirmar"
+    },
+    "object": {
+      "settings": "configuración",
+      "shortcuts": "atajos",
+      "name": "nombre",
+      "descr": "descripción",
+      "user": "usuario",
+      "theme": "tema",
+      "password": "contraseña",
+      "guest": "invitado",
+      "program": "programa",
+      "figure": "figura",
+      "figures": "figuras",
+      "file": "archivo",
+      "files": "archivos",
+      "group": "grupo",
+      "groups": "grupos",
+      "interpreter": "intérprete",
+      "axis": "eje",
+      "axes": "ejes",
+      "grid": "grilla",
+      "tip": "tip",
+      "normal": "normal",
+      "quality": "calidad",
+      "folder": "carpeta",
+      "here": "aquí",
+      "qualification": "calificación",
+      "date": "fecha",
+      "detail": "detalle",
+      "score": "puntaje",
+      "state": "estado"
+    },
+    "codemirror": {
+      "command": {
+        "inLine": "en linea",
+        "column": "columna",
+        "inColumn": "En columna",
+        "line": "linea",
+        "outWarning": "OUTAdvertencia",
+        "outError": "OUTError"
+      }
+    },
+    "msg": {
+      "404": {
+        "title": "Página no encontrada",
+        "descrp": "Lo sentimos, esta página no existe.",
+        "return": "Volver"
+      },
+      "codemirror": {
+        "fontSize": "Tamaño de fuente",
+        "functionWarnings": "Mostrar advertencias de uso de funciones",
+        "infixOperatorsWarnings": "Mostrar advertencias de uso de operadores infijos",
+        "cursorPosition": "Posición del cursor",
+        "showHints": "Mostrar sugerencias de autocompletar",
+        "functionTyping": "Mostrar tipado de funciones",
+        "consoleWarnings": "El programa contiene advertencias"
+      },
+      "figure": {
+        "multiPlot": "Multi gráfica",
+        "animationSpeed": "Velocidad de animación"
+      },
+      "file": {
+        "fileName": "Nombre de archivo",
+        "preview": "Seleccione un archivo para previsualizarlo",
+        "myFiles": "Mis archivos",
+        "readOnly": "Sólo lectura",
+        "viewCalification": "Ver Calificación",
+        "modified": "Archivo modificado",
+        "toSend": "¿Desea enviar el archivo {{fileName}}?",
+        "toSendInfo": "No se podrá editar luego de enviado.",
+        "delete": "¿Está seguro que desea eliminar el archivo {{fileName}}?",
+        "seeOriginal": "Ver original",
+        "seeMine": "Ver mio",
+        "share": "Compartir \"{{fileName}}\" con:",
+        "shared": "Archivo compartido",
+        "move": "¿Dónde quieres mover el archivo?",
+        "create": "¿Dónde quieres crear el archivo?",
+        "qualify": "Calificar entrega",
+        "evaluated": "Archivo evaluado",
+        "returned": "Archivo evaluado (re-entrega)"
+      },
+      "folder": {
+        "delete": "¿Está seguro que desea eliminar la carpeta {{fileName}}?"
+      },
+      "order": {
+        "kind": "Tipo",
+        "date": "Fecha"
+      }
+    },
+    "warning": {
+      "file": {
+        "noSelected": "Archivo no seleccionado",
+        "noPermissionDelete": "Sin permisos para eliminar el archivo",
+        "noPermissionMove": "Sin permisos para mover el archivo",
+        "capitalLetter": "Nombre de archivo debe iniciar con mayúscula.",
+        "qualifyOutRange": "Calificación fuera de rango",
+        "invalidName": "Nombre de archivo inválido."
+      },
+      "group": {
+        "select": "Seleccione un grupo"
+      }
+    },
+    "shortcuts": {
+      "runCode": "Ejecutar el código",
+      "newFile": "Nuevo archivo",
+      "openMenu": "Abrir menú de opciones",
+      "exportFile": "Exportar archivo",
+      "importFile": "Importar archivo",
+      "restartInterpreter": "Reiniciar intérprete",
+      "saveFile": "Guardar archivo",
+      "autocomplete": "Autocompletar",
+      "space": "Espacio",
+      "comment": "Comentar/Descomentar",
+      "functionNavigation": "Saltar a la definición",
+      "focusProgram": "Foco en Programa",
+      "focusInterpreter": "Foco en Interprete"
     }
+  }
 }
diff --git a/Frontend Angular 4/src/styles/_responsive.scss b/Frontend Angular 4/src/styles/_responsive.scss
index 89aacd9b51ee0f41fcf9d5b263700bf43a601c20..4b6157840f563524df3754cbd6a2f6c07d5b68da 100755
--- a/Frontend Angular 4/src/styles/_responsive.scss	
+++ b/Frontend Angular 4/src/styles/_responsive.scss	
@@ -1,82 +1,127 @@
 // @media screen and (max-width: 992px) {
-	.push-right {
-		.sidebar {
-			left: 235px !important;
-		}
-	}
+.push-right {
+  .sidebar {
+    left: 235px !important;
+  }
+}
 // }
 
-
 .CodeMirror {
-	height: 400px !important;
+  height: 400px !important;
 }
 
 #console {
-	height: 400px !important;
+  height: 400px !important;
 }
 
-.contenedor-canvas{
-	height: 400px !important;
+.contenedor-canvas {
+  height: 400px !important;
 }
 
-.listado-archivos{
-	height: 400px !important;
+.listado-archivos {
+  height: 400px !important;
 }
 
-.previewArchivoNoSeleccionado{
-	height: 400px !important;
+.previewArchivoNoSeleccionado {
+  height: 400px !important;
 }
 
 .listado-grupos {
-	height: 400px !important;
+  height: 400px !important;
 }
 
-.previewArchivoNoSeleccionado{
-	height: 400px !important;
+.previewArchivoNoSeleccionado {
+  height: 400px !important;
 }
 
-.listadoEntregasAlumnoGrupos{
-	height: 400px !important;
+.listadoEntregasAlumnoGrupos {
+  height: 400px !important;
 }
 
 @media screen and (min-width: 992px) {
-	.codemirrorArchivo .CodeMirror {
-		height: calc(100vh - 235px) !important;	
-	}
-
-	.codemirrorPrograma .CodeMirror {
-	 	height: calc(100vh - 197px) !important;
-	}
-
-	.codemirrorGrupos .CodeMirror {
-	 	height: calc(100vh - 232px) !important;
-	}
-
-	#console {
-		height: calc(100vh - 79px) !important;
-	}
-
-	.contenedor-canvas{
-		height: calc(100vh - 121px) !important;
-	}
-
-	.listado-archivos{
-		height: calc(100vh - 265px) !important;
-	}
-
-	.previewArchivoNoSeleccionado{
-		height: calc(100vh - 275px) !important;
-	}
-
-	.previewArchivoNoSeleccionadoGrupos{
-		height: calc(100vh - 225px) !important;
-	}
-
-	.listadoEntregasAlumnoGrupos{
-		height: calc(100vh - 225px) !important;
-	}
-
-	.listado-grupos {
-		height: calc(100vh - 270px) !important;
-	}
-}
\ No newline at end of file
+  .codemirrorArchivo .CodeMirror {
+    height: calc(100vh - 235px) !important;
+  }
+
+  .codemirrorPrograma .CodeMirror {
+    height: calc(100vh - 197px) !important;
+  }
+
+  .codemirrorGrupos .CodeMirror {
+    height: calc(100vh - 232px) !important;
+  }
+
+  #console {
+    height: calc(100vh - 79px) !important;
+  }
+
+  .contenedor-canvas {
+    height: calc(100vh - 121px) !important;
+  }
+
+  .listado-archivos {
+    height: calc(100vh - 265px) !important;
+  }
+
+  .previewArchivoNoSeleccionado {
+    height: calc(100vh - 275px) !important;
+  }
+
+  .previewArchivoNoSeleccionadoGrupos {
+    height: calc(100vh - 225px) !important;
+  }
+
+  .listadoEntregasAlumnoGrupos {
+    height: calc(100vh - 225px) !important;
+  }
+
+  .listado-grupos {
+    height: calc(100vh - 270px) !important;
+  }
+}
+
+// - - - - - - - - - - - - - - - -
+//        Archivos y grupos
+// - - - - - - - - - - - - - - - -
+.listado-archivos,
+.listado-grupos,
+.listadoEntregasAlumnoGrupos {
+  align-content: flex-start;
+  text-align: center;
+}
+
+.matefun-file-wrapper,
+.matefun-group-wrapper {
+  cursor: pointer;
+  padding-top: 1rem; // El mismo margin-bottom que pone el p al final del contenedor
+  margin-bottom: 8px;
+  transition-property: background-color, opacity;
+  transition-duration: 0.2s;
+  transition-timing-function: ease-in-out;
+}
+
+.matefun-file-wrapper,
+.matefun-group-wrapper {
+  &:hover {
+    background-color: #eee;
+  }
+}
+
+.matefun-fa-folder,
+.matefun-fa-file,
+.matefun-fa-user {
+  font-size: 3em;
+}
+
+.matefun-fa-folder,
+.matefun-fa-user {
+  color: #f95e5e;
+}
+
+.matefun-fa-file {
+  color: #ff8383;
+}
+
+button {
+  cursor: pointer;
+}