github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/cmd/deck/static/plugins-script.js (about)

     1  "use strict";
     2  
     3  function getParameterByName(name) {  // http://stackoverflow.com/a/5158301/3694
     4      const match = new RegExp('[?&]' + name + '=([^&/]*)').exec(window.location.search);
     5      return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
     6  }
     7  
     8  function redrawOptions() {
     9      const rs = allHelp.AllRepos.sort();
    10      const sel = document.getElementById("repo");
    11      while (sel.length > 1) {
    12          sel.removeChild(sel.lastChild);
    13      }
    14      const param = getParameterByName("repo");
    15      rs.forEach((opt) => {
    16          const o = document.createElement("option");
    17          o.text = opt;
    18          o.selected = (param && opt === param);
    19          sel.appendChild(o);
    20      });
    21  }
    22  
    23  window.onload = function () {
    24      // set dropdown based on options from query string
    25      redrawOptions();
    26      redraw();
    27      // Register dialog
    28      const dialog = document.querySelector('dialog');
    29      dialogPolyfill.registerDialog(dialog);
    30      dialog.querySelector('.close').addEventListener('click', () => {
    31          dialog.close();
    32      });
    33  };
    34  
    35  document.addEventListener("DOMContentLoaded", () => {
    36      configure();
    37  });
    38  
    39  function configure() {
    40      if (!branding) {
    41          return;
    42      }
    43      if (branding.logo) {
    44          document.getElementById('img').src = branding.logo;
    45      }
    46      if (branding.favicon) {
    47          document.getElementById('favicon').href = branding.favicon;
    48      }
    49      if (branding.background_color) {
    50          document.body.style.background = branding.background_color;
    51      }
    52      if (branding.header_color) {
    53          document.getElementsByTagName('header')[0].style.backgroundColor = branding.header_color;
    54      }
    55  }
    56  
    57  function selectionText(sel) {
    58      return sel.selectedIndex === 0 ? "" : sel.options[sel.selectedIndex].text;
    59  }
    60  
    61  /**
    62   * Returns a section to the content of the dialog
    63   * @param title title of the section
    64   * @param body body of the section
    65   * @return {Element}
    66   */
    67  function addDialogSection(title, body) {
    68      const container = document.createElement("DIV");
    69      const sectionTitle = document.createElement("H5");
    70      const sectionBody = document.createElement("DIV");
    71  
    72      sectionBody.classList.add("dialog-section-body");
    73      if (Array.isArray(body)) {
    74          body.forEach(el => {
    75             sectionBody.appendChild(el);
    76          });
    77      } else {
    78          sectionBody.innerHTML = body;
    79      }
    80  
    81      sectionTitle.classList.add("dialog-section-title");
    82      sectionTitle.innerHTML = title;
    83  
    84      container.classList.add("dialog-section");
    85      container.appendChild(sectionTitle);
    86      container.appendChild(sectionBody);
    87  
    88      return container;
    89  }
    90  
    91  /**
    92   * Return a list of link elements that links to commands.
    93   * @param commands list of commands
    94   * @return {Array}
    95   */
    96  function getLinkableCommands(commands) {
    97      const result = [];
    98      commands.forEach(command => {
    99         const commandName = extractCommandName(command.Examples[0]);
   100         const link = document.createElement("A");
   101         link.href = "/command-help#" + commandName;
   102         link.innerHTML = command.Examples[0];
   103         link.classList.add("plugin-help-command-link");
   104         result.push(link);
   105      });
   106      return result;
   107  }
   108  
   109  /**
   110   * Create a card for a plugin.
   111   * @param {string} repo repo name
   112   * @param {string} name name of the plugin
   113   * @param {Object} pluginObj plugin object
   114   * @return {Element} the card element that contains the plugin
   115   */
   116  function createPlugin(repo, name, pluginObj) {
   117      const isExternal = pluginObj.isExternal;
   118      const plugin = pluginObj.plugin;
   119  
   120      const title = document.createElement("H3");
   121      title.innerHTML = name;
   122      title.classList.add("mdl-card__title-text");
   123      const supportTitle = document.createElement("DIV");
   124      supportTitle.innerHTML = isExternal ? " external plugin" : "";
   125      supportTitle.classList.add("mdl-card__subtitle-text");
   126      const cardTitle = document.createElement("DIV");
   127      cardTitle.classList.add("mdl-card__title");
   128      cardTitle.appendChild(title);
   129      cardTitle.appendChild(supportTitle);
   130  
   131      const cardDesc = document.createElement("DIV");
   132      cardDesc.innerHTML = getFirstSentence(plugin.Description);
   133      cardDesc.classList.add("mdl-card__supporting-text");
   134  
   135      const cardAction = document.createElement("DIV");
   136      const actionButton = document.createElement("A");
   137      actionButton.innerHTML = "Details";
   138      actionButton.classList.add(...["mdl-button", "mdl-button--colored", "mdl-js-button", "mdl-js-ripple-effect"]);
   139      actionButton.addEventListener("click", () => {
   140          const dialog = document.querySelector("dialog");
   141          const title = dialog.querySelector(".mdl-dialog__title");
   142          const content = dialog.querySelector(".mdl-dialog__content");
   143  
   144          while (content.firstChild) {
   145              content.removeChild(content.firstChild);
   146          }
   147  
   148          title.innerHTML = name;
   149          if (plugin.Description) {
   150              content.appendChild(addDialogSection("Description", plugin.Description));
   151          }
   152          if (plugin.Events) {
   153              const sectionContent = "[" + plugin.Events.sort().join(", ") + "]";
   154              content.appendChild(addDialogSection("Events handled", sectionContent));
   155          }
   156          if (plugin.Config) {
   157              let sectionContent = plugin.Config ? plugin.Config[repo] : "";
   158              let sectionTitle =
   159                  repo === "" ? "Configuration(global)" : "Configuration(" + repo + ")";
   160              if (sectionContent && sectionContent !== "") {
   161                  content.appendChild(addDialogSection(sectionTitle, sectionContent));
   162              }
   163          }
   164          if (plugin.Commands) {
   165              let sectionContent = getLinkableCommands(plugin.Commands);
   166              content.appendChild(addDialogSection("Commands", sectionContent));
   167          }
   168          dialog.showModal();
   169      });
   170      cardAction.appendChild(actionButton);
   171      cardAction.classList.add(...["mdl-card__actions", "mdl-card--border"]);
   172  
   173      const card = document.createElement("DIV");
   174      card.appendChild(cardTitle);
   175      card.appendChild(cardDesc);
   176      card.appendChild(cardAction);
   177  
   178      card.classList.add(...["plugin-help-card", "mdl-card", "mdl-shadow--2dp"]);
   179      if (isDeprecated(plugin.Description)) {
   180          card.classList.add("deprecated");
   181      }
   182      return card;
   183  }
   184  
   185  /**
   186   * Takes an org/repo string and a repo to plugin map and returns the plugins
   187   * that apply to the repo.
   188   * @param {string} repoSel repo name
   189   * @param {Map<string, PluginHelp>} repoPlugins maps plugin name to plugin
   190   * @return {Array<string>}
   191   */
   192  function applicablePlugins(repoSel, repoPlugins) {
   193      if (repoSel === "") {
   194          const all = repoPlugins[""];
   195          if (all) {
   196              return all.sort();
   197          }
   198          return [];
   199      }
   200      const parts = repoSel.split("/");
   201      const byOrg = repoPlugins[parts[0]];
   202      let plugins = [];
   203      if (byOrg && byOrg !== []) {
   204          plugins = plugins.concat(byOrg);
   205      }
   206      const pluginNames = repoPlugins[repoSel];
   207      if (pluginNames) {
   208          pluginNames.forEach((pluginName) => {
   209              if (!plugins.includes(pluginName)) {
   210                  plugins.push(pluginName);
   211              }
   212          });
   213      }
   214      return plugins.sort();
   215  }
   216  
   217  /**
   218   * Redraw plugin cards.
   219   * @param {string} repo repo name.
   220   * @param {Map<string, Object>} helpMap maps a plugin name to a plugin.
   221   */
   222  function redrawPlugin(repo, helpMap) {
   223      const container = document.querySelector("#plugin-container");
   224      while (container.childElementCount !== 0) {
   225          container.removeChild(container.firstChild);
   226      }
   227      const names = helpMap.keys();
   228      const nameArray = Array.from(names).sort();
   229      nameArray.forEach(name => {
   230          container.appendChild(createPlugin(repo, name, helpMap.get(name)))
   231      });
   232  }
   233  
   234  /**
   235   * Redraws the content of the page.
   236   */
   237  function redraw() {
   238      const repoSel = selectionText(document.getElementById("repo"));
   239      if (window.history && window.history.replaceState !== undefined) {
   240          if (repoSel !== "") {
   241              history.replaceState(null, "", "/plugins?repo="
   242                  + encodeURIComponent(repoSel));
   243          } else {
   244              history.replaceState(null, "", "/plugins")
   245          }
   246      }
   247      redrawOptions();
   248  
   249      const plugins = new Map();
   250      applicablePlugins(repoSel, allHelp.RepoPlugins)
   251          .forEach((name) => {
   252              if (allHelp.PluginHelp[name]) {
   253                  plugins.set(
   254                      name,
   255                      {
   256                          isExternal: false,
   257                          plugin: allHelp.PluginHelp[name]
   258                      });
   259              }
   260          });
   261      applicablePlugins(repoSel, allHelp.RepoExternalPlugins)
   262          .forEach((name) => {
   263              if (allHelp.ExternalPluginHelp[name]) {
   264                  plugins.set(
   265                      name,
   266                      {
   267                          isExternal: true,
   268                          plugin: allHelp.ExternalPluginHelp[name]
   269                      });
   270              }
   271          });
   272      redrawPlugin(repoSel, plugins);
   273  }
   274  
   275  /**
   276   * Returns first sentence from plugin's example.
   277   * @param {string} text
   278   * @return {string}
   279   */
   280  function getFirstSentence(text) {
   281      const fullStop = text.indexOf(".");
   282      return fullStop === -1 ? text : text.slice(0, fullStop + 1);
   283  }
   284  
   285  /**
   286   * Returns true if the plugin is deprecated.
   287   * @param {string} text
   288   * @return {boolean}
   289   */
   290  function isDeprecated(text) {
   291      const dictionary = ["deprecated!"];
   292      text = text.toLowerCase();
   293      for (let i = 0; i < dictionary.length; i++) {
   294          if (text.indexOf(dictionary[i]) !== -1) {
   295              return true;
   296          }
   297      }
   298      return false;
   299  }
   300  
   301  /**
   302   * Extracts a command name from a command example. It takes the first example,
   303   * with out the slash, as the name for the command. Also, any '-' character is
   304   * replaced by '_' to make the name valid in the address.
   305   * @param {string} commandExample
   306   * @return {string}
   307   */
   308  function extractCommandName(commandExample) {
   309      const command = commandExample.split(" ");
   310      if (!command || command.length === 0) {
   311          throw new Error("Cannot extract command name.");
   312      }
   313      return command[0].slice(1).split("-").join("_");
   314  }