From f44f51309fe0f3a00c779111cfbd7cc7685897b6 Mon Sep 17 00:00:00 2001
From: Tim Kreuzer <t.kreuzer@fz-juelich.de>
Date: Thu, 6 Feb 2025 16:09:51 +0100
Subject: [PATCH] listen for server trigger, to update stopped servers
 correctly

---
 templates/footer.html                         |  1 -
 .../macros/table/helpers/systems_js.jinja     |  2 +-
 templates/macros/table/table.jinja            | 13 ++++++
 templates/macros/table/table_js.jinja         | 45 ++++++++++---------
 templates/page.html                           |  2 -
 5 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/templates/footer.html b/templates/footer.html
index a60bb23..e1c9bf0 100644
--- a/templates/footer.html
+++ b/templates/footer.html
@@ -158,7 +158,6 @@ require(["jquery"], function (
       let imgSrc = `${staticUrl}/images/footer/systems/${systemLower}.svg?v=${imgVersion}`;
       checkImageExists(imgSrc, systemLower, function(exists) {
         if (!exists) {
-          console.log(`Use default image for ${systemLower}`);
           let newImgSrc = `${staticUrl}/images/footer/templates/0.svg?v=${imgVersion}`;
           $(`#ampel-${systemLower} .ampel-img`).attr("src", newImgSrc);          
         }
diff --git a/templates/macros/table/helpers/systems_js.jinja b/templates/macros/table/helpers/systems_js.jinja
index c98c5a9..db1adf7 100644
--- a/templates/macros/table/helpers/systems_js.jinja
+++ b/templates/macros/table/helpers/systems_js.jinja
@@ -1,5 +1,5 @@
 {# Kube Systems --> #}
-  const kubeOutpostFlavors = {{ auth_state.outpost_flavors | tojson }};
+  const kubeOutpostFlavors = {{ auth_state.outpost_flavors | default({}, true) | tojson }};
   function _getKubeSystems() {
     return Object.keys(systemConfig).filter(system => {
       const backendService = systemConfig[system].backendService;
diff --git a/templates/macros/table/table.jinja b/templates/macros/table/table.jinja
index 1b9c0cb..1449ec2 100644
--- a/templates/macros/table/table.jinja
+++ b/templates/macros/table/table.jinja
@@ -50,6 +50,7 @@
                 existing-spawner-tr
                 {%- endif %}                
                 "
+                  data-sse-servers
                   data-sse-progress
                   data-service="{{ service_id }}"
                   data-row="{{ row_id }}"
@@ -223,6 +224,18 @@
           
         }
       });
+
+
+      $(`[data-sse-servers][id$='-summary-tr']`).on("sse", function (event, data) {
+        const $this = $(this);
+        const serviceId = $this.attr("data-service");
+        const rowId = $this.attr("data-row");
+        const stopped = data?.stopped ?? [];
+        if ( stopped.includes(rowId) ){
+          progressBarUpdate(serviceId, rowId, "", 0);
+          updateHeaderButtons(serviceId, rowId, "stopped");
+        }
+      });
     });
   </script>
 {%- endmacro %}
diff --git a/templates/macros/table/table_js.jinja b/templates/macros/table/table_js.jinja
index 64c0474..839a8d4 100644
--- a/templates/macros/table/table_js.jinja
+++ b/templates/macros/table/table_js.jinja
@@ -12,11 +12,11 @@
   
 
   // Define the regex pattern with named capture groups
-  const serviceConfig = {{ custom_config.services | tojson }};
-  const userModulesConfig = {{ custom_config.userModules | tojson }};
-  const systemConfig = {{ custom_config.systems | tojson }};
-  const resourcesConfig = {{ custom_config.resources | tojson }};
-  const backendServicesConfig = {{ custom_config.backendServices | tojson }};
+  const serviceConfig = {{ custom_config.services | default({}, true) | tojson }};
+  const userModulesConfig = {{ custom_config.userModules | default({}, true) | tojson }};
+  const systemConfig = {{ custom_config.systems | default({}, true) | tojson }};
+  const resourcesConfig = {{ custom_config.resources | default({}, true) | tojson }};
+  const backendServicesConfig = {{ custom_config.backendServices | default({}, true) | tojson }};
 
   const notAllowedKeys = ["secret_keys", "defaultvalues", "attachvalues"];
   const mappingDict = {};
@@ -26,7 +26,7 @@
   {%- for service_id, service_options in config.frontend_config.get("services", {}).get("options", {}).items() %}
 
     if ( !Object.keys(globalFillingOrder).includes("{{ service_id }}") ) {
-      globalFillingOrder["{{ service_id }}"] = {{ service_options.get("fillingOrder", []) | tojson }};
+      globalFillingOrder["{{ service_id }}"] = {{ service_options.get("fillingOrder", []) | default([], true) | tojson }};
     }
     {%- if pagetype == vars.pagetype_home %}
       {%- for s in spawners %}
@@ -35,12 +35,12 @@
           if ( !Object.keys(globalUserOptions).includes("{{ service_id }}") ) {
             globalUserOptions["{{ service_id }}"] = {};
           }
-          globalUserOptions["{{ service_id }}"]["{{ spawner.name }}"] = {{ decrypted_user_options.get(spawner.name, spawner.user_options) | tojson }};
+          globalUserOptions["{{ service_id }}"]["{{ spawner.name }}"] = {{ decrypted_user_options.get(spawner.name, spawner.user_options) | default({}, true) | tojson }};
         {%- endif %}
       {%- endfor %}
     {%- elif pagetype == vars.pagetype_workshop %}
       globalUserOptions["{{ service_id }}"] = {};
-      globalUserOptions["{{ service_id }}"]["{{ spawner.name }}"] = {{ spawner.user_options | tojson }};
+      globalUserOptions["{{ service_id }}"]["{{ spawner.name }}"] = {{ spawner.user_options | default({}, true) | tojson }};
     {%- endif %}
   {%- endfor %}
 
@@ -127,7 +127,7 @@
       {%- if pagetype == vars.pagetype_workshop %}
         const key = select.attr("name");
         const rowId = select.attr("data-row");
-        const workshopValues = {{ workshop_options | tojson }};
+        const workshopValues = {{ workshop_options | default({}, true) | tojson }};
         if ( Object.keys(workshopValues).includes(key) ) {
           let valueKeys = workshopValues[key];
           if ( !Array.isArray(valueKeys) ){
@@ -204,9 +204,9 @@
         const serviceId = element.attr("data-service");
         const rowId = element.attr("data-row");
         const elementName = element.attr("data-element");
-        const workshop = {{ workshop_options | tojson }};
+        const workshop = {{ workshop_options | default({}, true) | tojson }};
         const workshopId = "{{ spawner.user_options.get("workshop_id", workshop_options.get("workshopid")) }}";
-        const allowedSystems = {{ workshop_options.get("system", false) | tojson }};
+        const allowedSystems = {{ workshop_options.get("system", false) | default({}, true) | tojson }};
         
         const workshopSystems = workshop?.system || [];
         let workshopProject = workshop?.project || [];
@@ -529,7 +529,7 @@
 
       if ( availableDescription ) {
         $(`tr.collapsible-tr[data-server-id='${serviceId}-${rowId}']`).remove();
-        console.log("Header NA");
+        $(`#${serviceId}-${rowId}-summary-tr`).attr("data-spawner-na", "true");
         updateHeaderButtons(serviceId, rowId, "na");
         let description = `
           <div id="${serviceId}-${rowId}-config-td-nadescription-div" class="col text-lg-center col-12 col-lg-12">
@@ -837,7 +837,7 @@
         
         {%- if pagetype == vars.pagetype_workshop %}
           {# Only allow options, which are available for the selected systems #}
-          let allowedSystems = {{ workshop_options.get("system", false) | tojson }};
+          let allowedSystems = {{ workshop_options.get("system", false) | default({}, true) | tojson }};
           if ( allowedSystems ) {
             if ( !Array.isArray(allowedSystems) ){
               allowedSystems = [allowedSystems];
@@ -961,7 +961,7 @@
         let reservations = getReservationOptions(serviceId, rowId);
         
         {%- if pagetype == vars.pagetype_workshop %}          
-          const workshopValues = {{ workshop_options | tojson }};
+          const workshopValues = {{ workshop_options | default({}, true) | tojson }};
           {# Only allow options, which are available for the selected systems #}
           let allowedReservations = workshopValues?.reservation ?? false;
           if ( allowedReservations ) {
@@ -1192,7 +1192,7 @@
             inputElement.attr("data-collect", true);
           }
           {%- if pagetype == vars.pagetype_workshop %}          
-            const workshopValues = {{ workshop_options | tojson }}
+            const workshopValues = {{ workshop_options | default({}, true) | tojson }}
             if ( Object.keys(workshopValues).includes(elementId) ){
               console.log(`Yeah - ${elementId} is defined`);
             } 
@@ -1344,7 +1344,7 @@
 
     {# WorkshopManager.default.repo2docker.repopathtype --> #}
       function R2DgetRepoPathType(serviceId, rowId, tabId, elementId) {
-        return {{ custom_config.get("binderRepos", {}).get("notebookTypes", ["File", "URL"]) | tojson }}.map(item => [item, item]);
+        return {{ custom_config.get("binderRepos", {}).get("notebookTypes", ["File", "URL"]) | default([], true) | tojson }}.map(item => [item, item]);
       }
 
       function homeTriggerRepoPathTypeInit(trigger, serviceId, rowId, tabId, elementId, elementOptions) {
@@ -1390,7 +1390,7 @@
 
     {# WorkshopManager.default.repo2docker.repotype --> #}  
       function R2DgetRepoType() {
-        return {{ custom_config.get("binderRepos", {}).get("repos", ["GitHub"]) | tojson }}.map(item => [item, item]);
+        return {{ custom_config.get("binderRepos", {}).get("repos", ["GitHub"]) | default([], true) | tojson }}.map(item => [item, item]);
       }
 
       function homeTriggerRepoType(trigger, serviceId, rowId, tabId, elementId, elementOptions) {
@@ -1648,6 +1648,10 @@
     {# WorkshopManager.button.stop --> #}
       function updateHeaderButtons(serviceId, rowId, status) {
         // status: ["running", "starting", "na", "stopping", "cancelling", "stopped", "waiting"]
+        const summaryTr = $(`#${serviceId}-${rowId}-summary-tr`);
+        if ( summaryTr.attr("data-spawner-na") == "true" ) {
+          status = "na";
+        }
         let toShow = [];
         let toDisable = [];
         if ( status == "running" ) {
@@ -1674,8 +1678,7 @@
         }
         const baseSelector = `button[id^="${serviceId}-${rowId}"][id$="-btn-header"]`;
 
-        const summaryTr = $(`#${serviceId}-${rowId}-summary-tr`).attr("data-spawner-type");
-        if ( summaryTr == "workshop" ) {
+        if ( summaryTr.attr("data-spawner-type") == "workshop" ) {
           toShow.push("manage");
           toShow.push("del");
         }
@@ -1902,7 +1905,7 @@
         const group = elementOptions.options.group || tabId;
         const name = elementOptions.options.name || elementId;
         {%- if pagetype == vars.pagetype_workshop %}
-          const workshopValues = {{ workshop_options | tojson }}
+          const workshopValues = {{ workshop_options | default({}, true) | tojson }}
           if ( Object.keys(workshopValues).includes(group) && Object.keys(workshopValues[group]).includes(name) ){
             workshopPreset = true;
             const modules = workshopValues[group][name];
@@ -1999,7 +2002,7 @@
       {%- if pagetype == vars.pagetype_workshop %}
         function wTriggerName(trigger, serviceId, rowId, tabId, elementId, elementOptions) {
           const inputName = getInputElement(serviceId, rowId, elementId);
-          const user_options = {{ workshop_options | tojson }} || {};
+          const user_options = {{ workshop_options | default({}, true) | tojson }} || {};
           const displayName = user_options.name || "Workshop {{ workshop_id }}";
           inputName.val(displayName);
         }
diff --git a/templates/page.html b/templates/page.html
index 6a3a412..0c9abbe 100644
--- a/templates/page.html
+++ b/templates/page.html
@@ -51,9 +51,7 @@
       evtSource.onmessage = (e) => {
         try {
             const jsonData = JSON.parse(event.data);
-            console.log(jsonData);
             for (const [key, value] of Object.entries(jsonData)) {
-                console.log(`Trigger ${key}`);
                 $(`[data-sse-${key}]`).trigger("sse", value);
             }
         } catch (error) {
-- 
GitLab