Browse Source

Update: edit frontend replacing selection with seleck and many small visual changes

Sebastian Kreisel 1 year ago
parent
commit
fd9885657c

+ 6 - 10
TODO.org

@@ -3,18 +3,14 @@
 * Urgent
 
 * Big picture, Summer update
-** TODO Fix selection after image upload lock
+** TODO Backend: Make MathJax inclusion stricter
 
 ** TODO General code-review and refactoring, smaller quickfixes from below
-** TODO Find a way to output stdcout from docker
-** TODO Update and adjust edit frontend
-*** TODO Fix bugs below, in particular comments
-*** TODO Adjust for new post-types
-*** TODO Replace select list to seleck
-*** TODO Fix header / footer
-*** TODO Fix messages
-** TODO File permissions on uploaded files
-** TODO Backend: Content type for email transcripts
+** TODO Docker: Find a way to output stdcout from docker
+** TODO Edit: Fix bugs below, in particular comments
+** TODO Edit: Fix messages
+** TODO Files: Permissions on uploaded files
+** TODO Backend: Content type and View for email transcripts
 ** TODO CSS: Improve on h2 fontsize and styling
 
 ** TODO Backend: Rubble: Post title list only

+ 5 - 4
elfcom-backend/src/Endpoint/Edit.hs

@@ -43,7 +43,9 @@ editFetchHandler (EditFetchReq mts mtime mtitle mcat) = do
           mtitle mtime Nothing
   posts <- runSQL $ queryPostList q
   let res = map (\(pid, p) -> (fromIntegral $ fromSqlKey pid,
-                               displayName (postTitle p) (postCrtDate p)))
+                               displayName (postTitle p) (postCrtDate p),
+                               postAccess p,
+                               postPostType p))
             posts
   return $ EditFetchOkay res
 
@@ -150,8 +152,7 @@ isUrlAllowed u = T.isPrefixOf "/" u &&
 
 displayName :: Maybe T.Text -> UTCTime -> T.Text
 displayName (Just tit) _ = tit
-displayName Nothing tm = T.concat ["[Rubble ",  T.pack tstring, " ]"]
-  where tstring = formatTime defaultTimeLocale "%d. %b %y :: %R" tm
+displayName Nothing tm = T.pack $ formatTime defaultTimeLocale "%d.%m.%y" tm
 
 
 -- Data Types
@@ -195,6 +196,6 @@ data EditFetchReq = EditFetchReq { fetTypes :: !(Maybe [Int])
                                  , fetTitle :: !(Maybe T.Text)
                                  , fetCategories :: !(Maybe [T.Text]) }
                   deriving (Show, Eq, Generic, ToJSON, FromJSON)
-data EditFetchRsp = EditFetchOkay { fetContent :: ![(Int, T.Text)] }
+data EditFetchRsp = EditFetchOkay { fetContent :: ![(Int, T.Text, Int, Int)] }
                   | EditFetchFail { fetError :: !T.Text }
                    deriving (Show, Eq, Generic, ToJSON, FromJSON)

+ 1 - 1
elfcom-backend/src/View/Drivel.hs

@@ -78,7 +78,7 @@ drivelRight dst acc = do
         div ! class_ "drivel-cat-cnt" $
           a!href (textValue$makeContHref cp selcats (togglePT 3 ptyps) dacc) !
           class_ (textValue $T.append "drivel-link " (foo (ptyps == [3]))) $
-          "Only Internal"
+          "Only Unlisted"
       _ -> return ()
     div ! class_ "drivel-cat-cnt" $
       a ! href "/rubble?p=0" ! class_ "drivel-link drivel-cat-inactive" $

+ 18 - 22
elfcom-backend/src/View/Edit.hs

@@ -13,17 +13,18 @@ editSite vi = do
   siteHead vi $ do
     makeCss vi "/css/latex.css"
     makeCss vi "/css/input.css"
+    makeCss vi "/css/structure_admin.css"
     makeCss vi "/css/site_edit.css"
     makeMathJax vi
     makeJsM vi "/js/edit/site_edit.js"
-  siteBody $ do
+  div ! class_ "admin-body" $ do
     editHeader
     editMain
     editFooter
 
 editMain :: Html
-editMain = div ! class_ "cnt-edit-main font-admin-ui" $ do
-  div ! class_ "cnt-edit-left" $ do
+editMain = div ! class_ "edit-main font-admin-ui" $ do
+  div ! class_ "edit-left" $ do
     input ! id "edit-title"
     input ! id "edit-categories"
     input ! id "edit-url"
@@ -37,38 +38,33 @@ editMain = div ! class_ "cnt-edit-main font-admin-ui" $ do
     input ! id "edit-response" ! class_ "edit-input" ! readonly "readonly"
     input ! id "edit-action" ! class_ "edit-input"
     button ! id "edit-submit-button" $ "Go!"
-  div ! class_ "cnt-edit-right" $ do
+  div ! class_ "edit-right" $ do
     input ! id "edit-id" ! readonly "readonly"
     input ! id "edit-date" ! readonly "readonly"
-    select ! autocomplete "off" ! multiple "multiple" ! id "edit-select" $ ""
+    div ! id "edit-select" $ ""
     input ! id "edit-search"
-  div ! class_ "cnt-edit-info" ! id "edit-info" $ do
+  div ! class_ "edit-info" ! id "edit-info" $ do
     div ! class_ "edit-info-pad" $ ""
     infoCol s1 >> infoCol s2 >> infoCol s3 >> infoCol s4
-  div ! class_ "cnt-edit-bottom font-text latex" $ do
-    div ! class_ "cnt-edit-preview" ! id "edit-preview" $ ""
-    div ! class_ "cnt-edit-buffer" $ ""
+  div ! class_ "edit-bottom font-text latex" $ do
+    div ! class_ "edit-preview" ! id "edit-preview" $ ""
+    div ! class_ "edit-buffer" $ ""
 
 infoCol :: [(String, String)] -> Html
 infoCol xs = do
-  div ! class_ "cnt-edit-info-col" $ toHtml (map toCol xs)
+  div ! class_ "edit-info-col" $ toHtml (map toCol xs)
 
 toCol :: (String, String) -> Html
 toCol (c1, c2) = do div ! class_ "edit-info-1" $ (toHtml c1)
                     div ! class_ "edit-info-2" $ (toHtml c2)
 
+
 editHeader :: Html
-editHeader = div ! class_ "cnt-edit-header" $ ""
+editHeader = div ! class_ "admin-header" $ do
+  a ! href "/admin" ! class_ "admin-header-link" $ "back to admin"
 
-editFooter ::  Html
-editFooter = div ! class_ "cnt-edit-footer" $ do
-  div ! class_ "edit-footer-left" $ do
-    div ! class_ "edit-footer-link-cnt" $
-      a ! href "/admin" ! class_ "edit-footer-link" $ "back to admin"
-    div ! class_ "edit-footer-link-cnt" $
-      a ! href "/rubble" ! class_ "edit-footer-link" $ "back to rubble"
-  div ! class_ "edit-footer-right" $ do
-    div ! id "edit-info-parse" $ ""
+editFooter :: Html
+editFooter = div ! class_ "admin-footer" $ ""
 
 
 -- Shortcuts
@@ -81,9 +77,9 @@ s1 = [ ("c = 1", "norm")
      , ("p = 0", "site")
      , ("p = 1", "post")
      , ("p = 2", "rubble")
-     , ("p = 3", "dlog")
+     , ("p = 3", "unlisted")
      , ("p = 4", "email")
-     , ("p = 5", "chat")
+     , ("p = 5", "archive")
      , ("", "")
      , ("width", "758")
      , ("mini-2", "374 :: 10")

+ 10 - 1
elfcom-backend/static/css/latex.css

@@ -34,15 +34,17 @@ h3.txt-headline {
 }
 
 div.txt-par {
+    display: block;
     font-size: 15px;
     line-height: 160%;
 }
 
 div.txt-math {
-
+    display: block;
 }
 
 div.txt-center {
+    display: block;
     text-align: center;
 }
 
@@ -72,6 +74,7 @@ div.txt-v-space {
 }
 
 div.txt-line {
+    display: block;
     --overflow: auto;
     border: 0px solid black;
     margin: 0px;
@@ -123,26 +126,32 @@ a.txt-link {
 /* Spaces */
 
 div.txt-space-par {
+    display: block;
     height: 14px;
 }
 
 div.txt-space-item {
+    display: block;
     height: 5px;
 }
 
 div.txt-space-h1 {
+    display: block;
     height: 22px;
 }
 
 div.txt-space-h2 {
+    display: block;
     height: 18px;
 }
 
 div.txt-space-h3 {
+    display: block;
     height: 16px;
 }
 
 div.txt-space-h4 {
+    display: block;
     height: 14px;
 }
 

+ 109 - 68
elfcom-backend/static/css/site_edit.css

@@ -1,31 +1,27 @@
-/*
- * CONTAINERS
- */
+/* Overall Structure ------------------------------------------------------ */
 
-div.cnt-edit-header {
-    height: 5px;
-    border-bottom: 1px grey solid;
-}
-
-div.cnt-edit-footer {
-    border-top: 1px grey solid;
-}
-
-div.cnt-edit-left {
-    display: inline-block;
+div.edit-left {
     width: 580px;
     height: 270px;
-    vertical-align: top;
 }
 
-div.cnt-edit-right {
-    display: inline-block;
+div.edit-right {
     margin-left: 8px;
     width: 212px;
-    vertical-align: top;
 }
 
-div.cnt-edit-info {
+div.edit-bottom {
+    width: 794px;
+    padding: 2px;
+    height: 320px;
+    margin-top: 0px;
+    border: 1px solid #888888;
+    overflow-y: scroll;
+}
+
+/* Info Panel ------------------------------------------------------------- */
+
+div.edit-info {
     display: none;
     width: 798px;
     border: 1px solid #888888;
@@ -33,70 +29,44 @@ div.cnt-edit-info {
 }
 
 div.edit-info-show {
-    display: inline-block;
+    display: flex;
 }
 
-div.cnt-edit-info-col {
-    display: inline-block;
-    border: 1px dotted #888888;
+div.edit-info-col {
+    font-size: 11px;
+    border: 1px dotted grey;
+    --border-width: 0px 1px 0px 1px;
     padding: 5px;
     margin: 10px;
     margin-left: 0px;
     width: 174px;
-    font-size: 11px;
-    vertical-align: top;
 }
 
 div.edit-info-1 {
-    display: inline-block;
     width: 110px;
 }
 
 div.edit-info-2 {
-    display: inline-block;
     witdth: 70px;
 }
 
 div.edit-info-pad {
-    display: inline-block;
     width: 11px;
 }
 
-div.cnt-edit-bottom {
-    display: inline-block;
-    width: 794px;
-    padding: 2px;
-    height: 310px;
-    margin-top: 0px;
-    border: 1px solid #888888;
-    overflow-y: scroll;
-}
+/* Bottom Panel (Preview) ------------------------------------------------- */
 
-div.cnt-edit-buffer {
+div.edit-buffer {
     height: 100px;
 }
 
-div.cnt-edit-preview {
+div.edit-preview {
     margin-left: 12px;
     margin-right: 14px;
     width: 758px;
 }
 
-
-/*
- * IDS
- */
-textarea#edit-text {
-    width: 580px;
-    height: 210px;
-    margin: auto;
-    font-size: 11px;
-}
-
-select#edit-select {
-    width: 212px;
-    height: 210px;
-}
+/* Upper Input Panel --------- -------------------------------------------- */
 
 input#edit-title {
     width: 234px;
@@ -130,6 +100,15 @@ input#edit-paccess {
     text-align: center;
 }
 
+textarea#edit-text {
+    width: 580px;
+    height: 210px;
+    margin: auto;
+    font-size: 11px;
+}
+
+/* Lower Input Panel ------------------------------------------------------ */
+
 input#edit-response {
     width: 355px;
     margin-right: 5px;
@@ -181,24 +160,86 @@ input#edit-search {
     font-size: 9px;
 }
 
-div.edit-footer-left {
-    display: inline-block;
-    width: 401px;
-    font-size: 13px;
-    margin-right: 20px;
+/* Select Panel ----------------------------------------------------------- */
+
+div#edit-select {
+    width: 210px;
+    height: 208px;
+    overflow-y: scroll;
+    border: 1px solid grey;
+    font-size: 11px;
+}
+
+div.edit-select-top {
+    display: block;
+    border-bottom: 1px dotted grey;
+    padding: 1px 0px 1px 3px;
+    cursor: pointer;
+}
+
+div.edit-select-top:not(.edit-select-top-selected):hover {
+    background-color: #e8e8e8;
+}
+
+div.edit-select-top-selected {
+    background-color: #e0e0e0;
+}
+
+div.edit-select-name {
+    width: 153px;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+}
+
+div.edit-select-acc {
+    width: 13px;
+    border-width: 1px;
+    border-style: solid;
+    border-radius: 2px;
+    text-align: center;
+    margin-left: 5px;
+}
+
+div.edit-select-ptype {
+    width: 13px;
+    border: 1px solid black;
+    border-radius: 2px;
+    text-align: center;
+    margin-left: 3px;
+}
+
+/* Colored ptype Tags ----------------------------------------------------- */
+/* https://htmlcolorcodes.com/color-picker/ :: Analgous
+   HSV=0,20,90 and HSV=0,50,90 in GIMP
+*/
+
+div.edit-ptype-0 {
+    background-color: #E6B8B8;
+    border-color: #E67373;
+}
+
+div.edit-ptype-1 {
+    background-color: #E6CFB8;
+    border-color: #E6AD73;
+}
+
+div.edit-ptype-2 {
+    background-color: #E6E6B8;
+    border-color: #E6E673;
 }
 
-div.edit-footer-right {
-    display: inline-block;
-    text-align: right;
-    width: 379px;
-    font-size: 13px;
+div.edit-ptype-3 {
+    background-color: #CFE6B8;
+    border-color: #ADE673;
 }
 
-a.edit-footer-link {
+div.edit-ptype-4 {
+    background-color: #B8E6B8;
+    border-color: #73E673;
 }
 
-div.edit-footer-link-cnt {
-    display: inline-block;
-    margin-right: 10px;
+div.edit-ptype-4 {
+    background-color: #B8E6CF;
+    border-color: #73E6AD;
 }

+ 0 - 45
elfcom-backend/static/css/site_files.css

@@ -292,48 +292,3 @@ div.files-select-acc {
     border-radius: 2px;
     margin: 0px 1px;
 }
-
-div.files-select-acc-0 {
-    border-color: #bfbfbf;
-    background-color: #f2f2f2;
-}
-div.files-select-acc-0-sel {
-    background-color: #bfbfbf;
-    border-color: #bfbfbf;
-}
-div.files-select-acc-0:hover {
-    border-color: #666666;
-}
-div.files-select-acc-1 {
-    border-color: #8080ff;
-    background-color: #e6e6ff;
-}
-div.files-select-acc-1-sel {
-    background-color: #8080ff;
-    border-color: #8080ff;
-}
-div.files-select-acc-1:hover {
-    border-color: #0000cc;
-}
-div.files-select-acc-2 {
-    border-color: #00cc00;
-    background-color: #e6ffe6;
-}
-div.files-select-acc-2-sel {
-    background-color: #00aa00;
-    border-color: #00aa00;
-}
-div.files-select-acc-2:hover {
-    border-color: #00aa00;
-}
-div.files-select-acc-5 {
-    border-color: #ff8080;
-    background-color: #ffe6e6;
-}
-div.files-select-acc-5-sel {
-    background-color: #ff8080;
-    border-color: #ff8080;
-}
-div.files-select-acc-5:hover {
-    border-color: #cc0000;
-}

+ 50 - 0
elfcom-backend/static/css/structure_admin.css

@@ -49,3 +49,53 @@ div.admin-main {
     margin: 10px 0px 0px 0px;
     font-size: 12px;
 }
+
+/* Colored Acc Tags ------------------------------------------------------- */
+
+div.admin-acc-0-unsel {
+    border-color: #bfbfbf;
+    background-color: #f2f2f2;
+}
+div.admin-acc-0-sel {
+    background-color: #bfbfbf;
+    border-color: #bfbfbf;
+}
+div.admin-acc-0-unsel:hover {
+    border-color: #666666;
+}
+
+div.admin-acc-1-unsel {
+    border-color: #8080ff;
+    background-color: #e6e6ff;
+}
+div.admin-acc-1-sel {
+    background-color: #8080ff;
+    border-color: #8080ff;
+}
+div.admin-acc-1-unsel:hover {
+    border-color: #0000cc;
+}
+
+div.admin-acc-2-unsel {
+    border-color: #00cc00;
+    background-color: #e6ffe6;
+}
+div.admin-acc-2-sel {
+    background-color: #00aa00;
+    border-color: #00aa00;
+}
+div.admin-acc-2-unsel:hover {
+    border-color: #00aa00;
+}
+
+div.admin-acc-5-unsel {
+    border-color: #ff8080;
+    background-color: #ffe6e6;
+}
+div.admin-acc-5-unsel:hover {
+    border-color: #cc0000;
+}
+div.admin-acc-5-sel {
+    background-color: #ff8080;
+    border-color: #ff8080;
+}

+ 1 - 1
elfcom-frontend/admin/site_admin.js

@@ -23,5 +23,5 @@ function registerEventHandlers(sobjs) {
     if(e.keyCode === 13) {
       Log.doFetch(sobjs);
     }
-  }
+  };
 }

+ 56 - 22
elfcom-frontend/edit/fetch.js

@@ -1,6 +1,9 @@
 "use strict";
 
 import Common from "../common.js";
+import SelTree from "../seleck.js";
+import Load from "./load.js";
+import Preview from "./preview.js";
 
 
 var Fetch = {
@@ -9,9 +12,8 @@ var Fetch = {
 };
 export default Fetch;
 
-
 function init(sobjs) {
-  var start = new Date(); start.setDate(-2000);
+  var start = new Date(); start.setDate(-90);
   var end = new Date();
   var dateString = "(" +
       Common.monthString(start) + "/" +
@@ -19,7 +21,7 @@ function init(sobjs) {
       Common.monthString(end) + "/" +
       Common.yearString(end) + ")";
 
-  sobjs.seaEl.value = "p=0,1;" + "date=" + dateString + ";";
+  sobjs.seaEl.value = "p=0,1,2,3;" + "date=" + dateString + ";";
   return doFetch(sobjs);
 }
 
@@ -32,7 +34,7 @@ function doFetch(sobjs) {
   var cats = null;
   if(dateToken !== null) {
     dates = [ new Date("20" + dateToken.slice(4, 6), dateToken.slice(1, 3)),
-              new Date("20" + dateToken.slice(10, 12), dateToken.slice(7, 9))];
+              new Date("20" + dateToken.slice(10, 12),dateToken.slice(7, 9))];
   }
   var titleToken = Common.filterTokens(tokens, "title");
   var catToken = Common.filterTokens(tokens, "cats");
@@ -42,7 +44,7 @@ function doFetch(sobjs) {
   }
   if(typeToken !== null) {
     types = typeToken.split(",").map(a => a.trim()).filter(c => c.length > 0);
-    types = types.map(s => prsPostType(s)).filter(t => t >= 0);
+    types = types.map(s => parseInt(s)).filter(t => t >= 0);
   }
   var jsonObj = {
     "fetTypes": types.length === 0 ? [0, 1, 3] : types,
@@ -67,25 +69,57 @@ function doFetch(sobjs) {
 }
 
 function updateSelect(sobjs, items) {
-  for(var i = sobjs.selEl.length - 1; i >= 0; i--) {
-    sobjs.selEl.remove(i);
-  }
+  sobjs.selTree.removeChildren();
+  var newPostNode = createSelNode(sobjs, [-1, "New Post", 5, 1]);
+  sobjs.selTree.insertChild(newPostNode, -1, true);
   for(var item of items) {
-    var opt = document.createElement("option");
-    opt.id = item[0]; opt.innerHTML = item[1];
-    sobjs.selEl.add(opt);
+    var selNode = createSelNode(sobjs, item);
+    sobjs.selTree.insertChild(selNode, -1, true);
   }
-  // New Post Option
-  var nopt = document.createElement("option");
-  nopt.id = "-1"; nopt.innerHTML = "New Post";
-  sobjs.selEl.add(nopt, 0);
+  selectNode(sobjs, newPostNode);
 }
 
-function prsPostType(s) {
-  if(s === "0") { return 0; }
-  if(s === "1") { return 1; }
-  if(s === "2") { return 2; }
-  if(s === "3") { return 3; }
-  if(s === "4") { return 4; }
-  if(s === "5") { return 5; }
+function createSelNode(sobjs, item) {
+  var acc = item[2];
+  var ptype = item[3];
+  var topDiv = Common.createDomWith("div", "admin-noselect edit-select-top" +
+                                    " edit-select-top-unselected");
+  var nameDiv = Common.createDomWith("div", "edit-select-name");
+  if(item[3] === 2) {
+    nameDiv.innerHTML = "R :: " + item[1];
+  } else {
+    nameDiv.innerHTML = item[1];
+  }
+  topDiv.appendChild(nameDiv);
+  if(item[1] !== "New Post") {
+    var accDiv = Common.createDomWith("div", "edit-select-acc " +
+                                      "admin-acc-" + acc + "-unsel");
+    accDiv.innerHTML = "" + acc;
+    var ptypeDiv = Common.createDomWith("div", "edit-select-ptype " +
+                                        "edit-ptype-" + ptype);
+    ptypeDiv.innerHTML = "" + ptype;
+
+    topDiv.appendChild(accDiv);
+    topDiv.appendChild(ptypeDiv);
+  }
+  var selNode = new SelTree(topDiv, null, null, item[0]);
+  topDiv.onclick = function() {
+    selectNode(sobjs, selNode);
+  };
+  return selNode;
+}
+
+function selectNode(sobjs, node) {
+  var selectedNode = sobjs.selTree.findFirstSelectedChild();
+  if(selectedNode !== null) {
+    selectedNode.setSelected(false);
+    Common.toggleClass(selectedNode.domContentContainer,
+                       "edit-select-top-selected",
+                       "edit-select-top-unselected");
+  }
+  node.setSelected(true);
+  Common.toggleClass(node.domContentContainer,
+                     "edit-select-top-selected",
+                     "edit-select-top-unselected");
+  Load.doLoad(sobjs).then(() => Preview.doPreview(sobjs, true));
 }

+ 17 - 20
elfcom-frontend/edit/load.js

@@ -18,33 +18,30 @@ function init(sobjs) {
 }
 
 function doLoad(sobjs) {
-  var sid = sobjs.selEl.selectedIndex;
-  if(sid < 0) {
+  var selectedNode = sobjs.selTree.findFirstSelectedChild();
+  if(selectedNode === null) {
     return Promise.reject("Nothing selected on doLoad");
   }
-  var sel = sobjs.selEl[sid];
-  if(sel.id < 0) {
+  var sid = selectedNode.content;
+  if(sid < 0) {
     sobjs.titEl.value = ""; sobjs.catEl.value = ""; sobjs.urlEl.value = "";
     sobjs.pidEl.value = "-1"; sobjs.typEl.value = "1"; sobjs.ctyEl.value = "1";
     sobjs.txtEl.value = ""; sobjs.datEl.value = ""; sobjs.accEl.value = "5";
     return Promise.resolve();
   }
-  if(sel === null) { return Promise.resolve(); }
-  else {
-    return new Promise(function(resolve, reject) {
-      Common.sendJson("/api/admin/edit/load", parseInt(sel.id))
-        .then(res => res.json(),
-              () => { Common.fetchError("Load"); reject("ajax failed"); })
-        .then(function(json) {
-          if(json.tag === "EditLoadOkay") {
-            loadPost(sobjs, json);
-            Common.success("Load"); resolve();
-          } else {
-            Common.serverError("Load"); reject("server failed");
-          }
-        }, () => { Common.jsonError("Load"); reject("json failed"); });
-    });
-  }
+  return new Promise(function(resolve, reject) {
+    Common.sendJson("/api/admin/edit/load", sid)
+      .then(res => res.json(),
+            () => { Common.fetchError("Load"); reject("ajax failed"); })
+      .then(function(json) {
+        if(json.tag === "EditLoadOkay") {
+          loadPost(sobjs, json);
+          Common.success("Load"); resolve();
+        } else {
+          Common.serverError("Load"); reject("server failed");
+        }
+      }, () => { Common.jsonError("Load"); reject("json failed"); });
+  });
 }
 
 function loadPost(sobjs, post) {

+ 4 - 4
elfcom-frontend/edit/preview.js

@@ -53,10 +53,10 @@ function doPreview(sobjs, fullRewrite) {
   }
   var prefHtml = performance.now();
   // --- Info
-  sobjs.prsEl.innerHTML = "parse " +
-    ((prefParse - prefStart) + "").substring(0,5) + "ms :: render " +
-    ((prefHtml - prefParse) + "").substring(0,5) + "ms :: " + scons + " | " +
-    icons;
+  //sobjs.prsEl.innerHTML = "parse " +
+  //  ((prefParse - prefStart) + "").substring(0,5) + "ms :: render " +
+  //  ((prefHtml - prefParse) + "").substring(0,5) + "ms :: " + scons + " | " +
+  //  icons;
 
   prevString = string;
   prevS = sobjs.txtEl.selectionStart;

+ 5 - 5
elfcom-frontend/edit/site_edit.js

@@ -1,6 +1,7 @@
 "use strict";
 
 import Common from "../common.js";
+import SelTree from "../seleck.js";
 import Fetch from "./fetch.js";
 import Load from "./load.js";
 import Submit from "./submit.js";
@@ -33,6 +34,9 @@ document.addEventListener("DOMContentLoaded", function() {
     "pbtEl": document.getElementById("edit-reparse-button"),
   };
 
+  var selTree = new SelTree(sobjs.selEl, sobjs.selEl);
+  sobjs.selTree = selTree;
+
   registerEventHandlers(sobjs);
   Common.init(sobjs);
   Fetch.init(sobjs)
@@ -56,15 +60,11 @@ function registerEventHandlers(sobjs) {
     if(cn.indexOf("edit-info-show") < 0) {
       sobjs.infEl.className += " edit-info-show";
     } else {
-      sobjs.infEl.className = "cnt-edit-info";
+      sobjs.infEl.className = "edit-info";
     }
   };
   sobjs.pbtEl.onclick = function() {
     Preview.doPreview(sobjs, true);
-  }
-  sobjs.selEl.onchange = function() {
-    Load.doLoad(sobjs)
-      .then(() => Preview.doPreview(sobjs, true));
   };
   sobjs.seaEl.onkeyup = function(e) {
     if(e.keyCode === 13) {

+ 5 - 5
elfcom-frontend/files/fetch.js

@@ -94,7 +94,7 @@ function createNode(sobjs, path, accs, isFile) {
   var accDivs = [];
   for(var a of accs.reverse()) {
     var accDiv = Common.createDomWith("div", "files-select-acc " +
-                                      "files-select-acc-" + a +
+                                      "admin-acc-" + a + "-unsel" +
                                       " files-select-acc-unsel");
     accDivs.push(accDiv);
     accDiv.innerHTML = a;
@@ -149,8 +149,8 @@ function setSelect(sobjs, selNode, accDiv) {
   if(selectedDiv !== null) {
     acc = selectedDiv.innerHTML;
     Common.toggleClass(selectedDiv,
-                       "files-select-acc-" + acc + "-sel",
-                       "files-select-acc-" + acc);
+                       "admin-acc-" + acc + "-sel",
+                       "admin-acc-" + acc + "-unsel");
   }
   if(selectedNode !== null) {
     Common.toggleClass(selectedNode.domContentContainer.children[0],
@@ -174,8 +174,8 @@ function setSelect(sobjs, selNode, accDiv) {
     Common.toggleClass(selectedNode.domContentContainer.children[0],
                        "files-select-head-sel", "files-select-head-uns");
     Common.toggleClass(selectedDiv,
-                       "files-select-acc-" + acc + "-sel",
-                       "files-select-acc-" + acc);
+                       "admin-acc-" + acc + "-sel",
+                       "admin-acc-" + acc + "-unsel");
     Load.doLoad(sobjs, completePath);
   } else {
     selectedNode = null;

+ 10 - 0
elfcom-frontend/seleck.js

@@ -113,6 +113,16 @@ export default class SelTree {
     return null;
   }
 
+  // not recursive!
+  findFirstSelectedChild() {
+    for(var c of this.children) {
+      if(c.isSelected) {
+        return c;
+      }
+    }
+    return null;
+  }
+
   hasChildRec(child) {
     if(this.children.indexOf(child) >= 0) {
       return true;