Jewell Simon

Add observers to email

Discussion created by Jewell Simon on Dec 10, 2019

Now this is not my idea... I found a git on gitHub that did exactly what I needed it to do the problem was that it was beefy(12k lines)(GitHub - sdjrice/msgobs: A JavaScript modification for the Canvas learning management system which adds the ability to m… ). So I forked it and was going to go to work on it, convert to plain JS modify, when I realized I had no idea WTH is going on. Seriously though, @sdjrice was on another level. So I scraped the project and decided to go in from scratch. I created a baby version of that. So it has a ton of stipulations.

  1. can only be used once per session--- this is a stipulation that I imposed because it is new to our staff only 3 weeks in. you can remove by switching the bool from {once: true} to false 
  2.  This does not work on the grade book. That is hard I am working on it.
  3. If you were to decide to remove one of the students from the email there is no direct line to retract the parents from the email. Again, that is hard I am working on it.
  4. other stuff

I tried to embed the proof of concept no luck so here is the link:

https://www.iorad.com/player/1618642/Add-observers-to-email

  const checkIfNull = async selector => {
    while (document.querySelector(selector) === null) {
      await new Promise(resolve => requestAnimationFrame(resolve));
    }
    return document.querySelector(selector);
  };
  checkIfNull("#compose-btn").then(() => {
    if (
      ENV.current_user_roles.includes("teacher") || ENV.current_user_roles.includes("admin")
    ) {
    const delay = ms => new Promise(res => setTimeout(res, ms));
    let conversationsNav = document.querySelector(
      "div.ui-dialog-buttonpane.ui-widget-content.ui-helper-clearfix"
    );
    let parentButton = document.createElement("div");
    let classesToAdd = [
      "ui-button",
      "ui-widget",
      "ui-state-default",
      "ui-corner-all",
      "ui-button-text-only",
      "includeObserver"
    ];
    parentButton.classList.add(...classesToAdd);
    parentButton.setAttribute(
      "style",
      "margin:0 2px; min-width: 110px; background-color:wheat;"
    );
    parentButton.innerHTML = "Include Observers";
    conversationsNav.insertBefore(parentButton, conversationsNav.childNodes[1]);

    conversationsNav.querySelector(".includeObserver").addEventListener(
      "click",
      () => {
        let course = document.querySelector(
          '.message-header-input > input[type="hidden"]'
        );
        let courseNum = course.value.split("_")[1];
        let parents = {};
        let kiddosArr = [];
        let emailParents = [];

        if (course.value) {
          const fetchObservees = `/api/v1/courses/${courseNum}/enrollments?enrollment_type=ObserverEnrollment&per_page=100`;
          const options = {
            credentials: "same-origin",
            headers: {
              accept: "application/json"
            },
            timeout: 5000
          };
          fetch(fetchObservees, options)
            .then(response =>
              response
                .json()
                .then(data => ({
                  data: data,
                  ok: response.ok
                }))
                .then(res => {
                  if (res.ok) {
                    parents = res;
                  }
                })
            )
            .then(async() => {
              //console.log(parents.data);
              document
                .querySelectorAll(
                  'div.message-header-input input[name="recipients[]"]'
                )
                .forEach(kiddo => {
                  kiddosArr.push(kiddo.value);
                });
              kiddosArr = kiddosArr.map(x => {
                return parseInt(x, 10);
              });
            })
            .then(async() => {
              parents.data.forEach(element => {
                if (kiddosArr.includes(element.associated_user_id)) {
                  emailParents.push([element.user_id, element.user.name]);
                }
              });
            })
            .then(async() => {
              await delay(1000);
              if (emailParents.length > 0){
              emailParents.forEach(parent => {
                //console.table(parent);
                document.querySelectorAll(
                  ".ac-token-list"
                )[1].innerHTML += `<li class="ac-token" style="background-color:wheat;">
  ${parent[1]}

  <a href="#" class="ac-token-remove-btn">
    <i class="icon-x icon-messageRecipient--cancel"></i>
    <span class="screenreader-only">
      Remove recipient ${parent[1]}
    </span>
  </a>


  <input type="hidden" name="recipients[]" value="${parent[0]}">
</li>`;
              });
            }else{
                popUpError(`
( ⊙0⊙) - I am not seeing an observers associated. Sorry. - (⊙▂⊙ )`);
            }});
        } else {
          popUpError(`
(×_×;-In order to add parents you must select a course first. Re-fresh to try again. -(o。o;)`);
        }
      },
      { once: true }
    );
  }});
  const popUpError = (msgTxt) => {
    const msgHolder = document.querySelector("#flash_message_holder");
            const timeout = 9000;
            const daMsg = (msgHolder.innerHTML = `<div role="alert" class="ic-flash-static ic-flash-error popUp">
    <div class="ic-flash__icon" aria-hidden="true">
      <i class="icon-warning"></i>
    </div>
    <h1>${msgTxt}</h1>
  </div>`);
            daMsg;
            setTimeout(() => {
              let popUp = document.querySelector(".popUp");
              popUp.parentNode.removeChild(popUp);
            }, timeout);
  }

 

Edit: 17-12-19: modified script to pull in a 100 parents if there, as well as made a few more async calls for better error handling and lengthy forEach if >50 parents(merged classes & lectures)

Outcomes