Disabling the "unpublish" option

Jump to solution
chriscas
Community Coach
Community Coach

Hi Developers,

The July 17 deploy changed the UI for the publish/unpublish options on a course home page and in course settings to a dropdown box.  I'm looking for a way to disable the "unpublish" option with this new UI.  I had code working for the old UI, but I'm having trouble figuring out how to do this with the new one.  We want teachers to be able to publish (so we can't lock this out with permissions), but we don't want them to be able to unpublish a course that's already been published.  Do any of you experts in here see a way to accomplish this with the new/current UI?  I'd appreciate any assistance I can get!

-Chris

1 Solution
Code-with-Ski
Community Coach
Community Coach

@chriscas 

You can try the following.  It will look for the course status button wrapper.  If it is found, then it will watch for the published icon to show as the selected state.  Once the published icon is found as the selected state, it will replace the button with a modified version of the button content that no longer triggers the menu to change the course state. 

  • If a course is already published, it will be updated as the page loads. 
  • If it is currently, unpublished, it will update it once the course is changed to published.
(function () {
  "use strict";

  if (
    /\/courses\/[0-9]+\/?$/.test(window.location.pathname) ||
    /\/courses\/[0-9]+\/(settings|details)\/?$/.test(window.location.pathname)
  ) {
    watchForCoursePublishButtonWrapper();
  }

  function watchForCoursePublishButtonWrapper() {
    const cssSelector = `#course_publish_button`;
    watchForAddedElement(cssSelector, watchForPublishedState);
  }

  function watchForAddedElement(
    cssSelector,
    handlerFunction,
    elementToObserve = document.body,
    options = { childList: true, subtree: true },
    shouldContinueObservingWhenFound = false
  ) {
    const element = elementToObserve?.querySelector(cssSelector);
    if (element) {
      handlerFunction(element);
      if (!shouldContinueObservingWhenFound) {
        return;
      }
    }

    const observer = new MutationObserver((mutations) => {
      if (
        !mutations.some((mutation) => mutation?.addedNodes?.length ?? 0 > 0)
      ) {
        return;
      }

      const foundElement = elementToObserve?.querySelector(cssSelector);
      if (foundElement) {
        handlerFunction(foundElement);
        if (!shouldContinueObservingWhenFound) {
          observer.disconnect();
        }
      }
    });

    observer.observe(elementToObserve, options);
  }

  function watchForPublishedState(buttonWrapper) {
    const cssSelector = `svg[name=IconPublish]`;
    watchForAddedElement(
      cssSelector,
      () => replacePublishButton(buttonWrapper),
      buttonWrapper
    );
  }

  function replacePublishButton(buttonWrapper) {
    console.log("replace publish");
    const button = buttonWrapper.querySelector("button");
    const buttonContent = buttonWrapper?.querySelector("button > span");
    if (button && buttonContent) {
      // Remove drop-down arrow
      const arrowSvg = buttonContent?.querySelector("svg[name^=IconArrow]");
      arrowSvg?.remove();

      // Cloning to remove event listeners
      const clonedButtonContent = buttonContent.cloneNode(true);

      // Adjusting justify content style to keep left-aligned
      const childrenLayoutWrapper = clonedButtonContent?.querySelector(
        ":scope > span[class$=childrenLayout]"
      );
      if (childrenLayoutWrapper) {
        childrenLayoutWrapper.style.justifyContent = "left";
      }

      // Replace the current button with the cloned and updated button content
      button.replaceWith(clonedButtonContent);
    }
  }
})();

View solution in original post

0 Likes