diff --git a/README.md b/README.md
index 817ba66..c38dbd6 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ Colors course site tabs according to the assignment due date.
Due date within 14 Days
## Notification Badge
-Tells your unchecked latest assignments.
+Tells your **unchecked** latest assignments.
Notification badge will appear in the upper left-hand side of a course site tab.
If you open a course site with the notification badge on, the badge will disappear.
@@ -50,8 +50,8 @@ You can add your custom assignment to miniSakai as `memo` with PLUS button locat
Also check box is available for you to distinguish completed assignments from working assignments.
## Cache
-In order to reduce the network load on Sakai LMS, we have implemented a cache function for getting assignments and quizzes from REST API.
-The default cache interval is as follows
+In order to reduce the network load on Sakai LMS, we have implemented a cache function for fetching assignments and quizzes from REST API.
+The default cache interval is as follows:
- Assignment fetching --- 2 minutes
- Quiz fetching --- 10 minutes
diff --git a/manifest.json b/manifest.json
index ba3e257..0dfcad6 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"name": "Comfortable Sakai",
"description": "__MSG_EXTENSION_DESCRIPTION__",
- "version": "1.2.0",
+ "version": "1.2.1",
"manifest_version": 2,
"default_locale": "en",
"icons": {
@@ -36,7 +36,7 @@
"web_accessible_resources": [
"css/comfortable-sakai.css",
"img/logo.png",
- "img/relaxPanda.png",
+ "img/noAssignment.png",
"img/miniSakaiBtn.png",
"views/minisakai.mustache"
]
diff --git a/package.json b/package.json
index ca76a43..217275b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "comfortable-sakai",
"version": "1.1.0",
- "description": "Comfortable Sakai is a browser extension for managing assignments and quizzes on Sakai LMS.",
+ "description": "Comfortable Sakai is a Web browser extension for managing assignments and quizzes on Sakai LMS.",
"main": "index.ts",
"scripts": {
"test": "jest",
diff --git a/public/img/relaxPanda.png b/public/img/noAssignment.png
similarity index 100%
rename from public/img/relaxPanda.png
rename to public/img/noAssignment.png
diff --git a/public/views/minisakai.mustache b/public/views/minisakai.mustache
index 6315391..cd78b91 100644
--- a/public/views/minisakai.mustache
+++ b/public/views/minisakai.mustache
@@ -14,7 +14,7 @@
{{titles.quizFetchedTime}}
-
{{fetchedTime.assignment}}
+
{{fetchedTime.quiz}}
{{/subset}}
@@ -213,12 +213,12 @@
{{/display.lateSubmit}}
- {{#showRelaxPandA}}
+ {{#noAssignment}}
-
{{titles.relaxPandA}}
+
{{titles.noAssignment}}
- {{/showRelaxPandA}}
+ {{/noAssignment}}
{{^subset}}
diff --git a/src/content_script.ts b/src/content_script.ts
index b625ae4..e817e9b 100644
--- a/src/content_script.ts
+++ b/src/content_script.ts
@@ -1,6 +1,6 @@
import { loadFromLocalStorage, saveToLocalStorage } from "./storage";
import { Assignment, CourseSiteInfo } from "./model";
-import { getCourseIDList, getBaseURL, getAssignmentByCourseID, getQuizFromCourseID } from "./network";
+import { getCourseIDList, getAssignmentByCourseID, getQuizFromCourseID } from "./network";
import { createMiniSakaiBtn, createFavoritesBarNotification, displayMiniSakai } from "./minisakai";
import {
@@ -14,26 +14,20 @@ import {
updateIsReadFlag,
useCache,
} from "./utils";
-import { Settings, loadSettings } from "./settings";
+import { Config, loadConfigs } from "./settings";
-export const baseURL = getBaseURL();
-export const VERSION = chrome.runtime.getManifest().version;
-export let assignmentCacheInterval: number;
-export let quizCacheInterval: number;
-export let assignmentFetchedTime: number | undefined;
-export let quizFetchedTime: number | undefined;
export let courseIDList: Array;
export let mergedAssignmentList: Array;
export let mergedAssignmentListNoMemo: Array;
-export let CPsettings: Settings;
/**
* Load old assignments/quizzes from storage and fetch new assignments/quizzes from Sakai.
+ * @param {Config} config
* @param {CourseSiteInfo[]} courseSiteInfos
* @param {boolean} useAssignmentCache
* @param {boolean} useQuizCache
*/
-export async function loadAndMergeAssignmentList(courseSiteInfos: Array, useAssignmentCache: boolean, useQuizCache: boolean): Promise> {
+export async function loadAndMergeAssignmentList(config: Config ,courseSiteInfos: Array, useAssignmentCache: boolean, useQuizCache: boolean): Promise> {
// Load old assignments and quizzes from local storage
const oldAssignmentList = convertArrayToAssignment(await loadFromLocalStorage("CS_AssignmentList"));
const oldQuizList = convertArrayToAssignment(await loadFromLocalStorage("CS_QuizList"));
@@ -48,7 +42,7 @@ export async function loadAndMergeAssignmentList(courseSiteInfos: Array {
*/
async function updateSettings(event: any, type: string): Promise {
const settingsID = event.target.id;
- let settingsValue = event.currentTarget.value;
+ let settingsValue = event.target.value;
+ const config = await loadConfigs();
+ const CSsettings = config.CSsettings;
// Type of Settings
switch (type) {
case "check":
- settingsValue = event.currentTarget.checked;
+ settingsValue = event.target.checked;
break;
case "number":
- settingsValue = parseInt(event.currentTarget.value);
+ settingsValue = parseInt(event.target.value);
break;
case "string":
break;
@@ -146,7 +148,7 @@ async function updateSettings(event: any, type: string): Promise {
];
for (const k of colorList) {
// @ts-ignore
- CPsettings[k] = DefaultSettings[k];
+ CSsettings[k] = DefaultSettings[k];
const q = document.getElementById(k);
if (q) {
// @ts-ignore
@@ -155,10 +157,10 @@ async function updateSettings(event: any, type: string): Promise {
}
} else {
// @ts-ignore
- CPsettings[settingsID] = settingsValue;
+ CSsettings[settingsID] = settingsValue;
}
- saveToLocalStorage("CS_Settings", CPsettings);
+ await saveToLocalStorage("CS_Settings", CSsettings);
await redrawFavoritesBar(courseIDList, true);
}
@@ -253,8 +255,9 @@ async function editFavoritesMessage(): Promise {
*/
async function redrawFavoritesBar(courseIDList: Array, useCache: boolean): Promise {
deleteFavoritesBarNotification();
- const newAssignmentList = await loadAndMergeAssignmentList(courseIDList, useCache, useCache);
- createFavoritesBarNotification(courseIDList, newAssignmentList);
+ const config = await loadConfigs();
+ const newAssignmentList = await loadAndMergeAssignmentList(config, courseIDList, useCache, useCache);
+ await createFavoritesBarNotification(courseIDList, newAssignmentList);
}
/**
diff --git a/src/minisakai.ts b/src/minisakai.ts
index 2fa94c3..122c2c9 100644
--- a/src/minisakai.ts
+++ b/src/minisakai.ts
@@ -1,7 +1,6 @@
import { Assignment, CourseSiteInfo, DisplayAssignment, DisplayAssignmentEntry } from "./model";
import { createCourseIDMap, getDaysUntil, formatTimestamp, nowTime } from "./utils";
import { appendChildAll, cloneElem, hamburger, miniSakai, SettingsDom } from "./dom";
-import { CPsettings, assignmentFetchedTime, quizFetchedTime, VERSION } from "./content_script";
import {
addMemo,
deleteMemo,
@@ -14,6 +13,7 @@ import {
} from "./eventListener";
// @ts-ignore
import Mustache = require("mustache");
+import { loadConfigs } from "./settings";
/**
* Create a button to open miniSakai
@@ -30,10 +30,10 @@ function createMiniSakaiBtn(): void {
/**
* Using template engine to generate miniSakai list.
*/
-export function createMiniSakaiGeneralized(root: Element, assignmentList: Array, courseSiteInfos: Array, subset: boolean, insertionProcess: (rendered: string) => void): void {
- const assignmentFetchedTimeString = formatTimestamp(assignmentFetchedTime);
- const quizFetchedTimeString = formatTimestamp(quizFetchedTime);
-
+export async function createMiniSakaiGeneralized(root: Element, assignmentList: Array, courseSiteInfos: Array, subset: boolean, insertionProcess: (rendered: string) => void): Promise {
+ const config = await loadConfigs();
+ const assignmentFetchedTimeString = formatTimestamp(config.fetchedTime.assignment);
+ const quizFetchedTimeString = formatTimestamp(config.fetchedTime.quiz);
const courseSiteList: Array = [];
const courseIDMap = createCourseIDMap(courseSiteInfos);
@@ -90,7 +90,7 @@ export function createMiniSakaiGeneralized(root: Element, assignmentList: Array<
appendElement(courseName, otherElements);
break;
case "duePassed":
- const showLateSubmitAssignment = CPsettings ? CPsettings.getDisplayLateSubmitAssignment : false;
+ const showLateSubmitAssignment = config.CSsettings ? config.CSsettings.getDisplayLateSubmitAssignment : false;
if (showLateSubmitAssignment && getDaysUntil(nowTime, assignmentEntry.getCloseDateTimestamp * 1000) !== "duePassed") {
appendElement(courseName, lateSubmitElements);
}
@@ -114,7 +114,7 @@ export function createMiniSakaiGeneralized(root: Element, assignmentList: Array<
return elements;
};
- let relaxPandA = null;
+ let noAssignmentImg = null;
let assignmentCnt = 0;
if (assignmentList.length !== 0) {
for (const assignment of assignmentList) {
@@ -122,20 +122,21 @@ export function createMiniSakaiGeneralized(root: Element, assignmentList: Array<
}
}
if (assignmentList.length === 0 || assignmentCnt === 0) {
- relaxPandA = {
- img: chrome.extension.getURL("img/relaxPanda.png"),
+ noAssignmentImg = {
+ img: chrome.extension.getURL("img/noAssignment.png"),
};
}
+ // Create dict of data for miniSakai
const templateVars = {
fetchedTime: {
assignment: assignmentFetchedTimeString,
quiz: quizFetchedTimeString,
},
miniSakaiLogo: chrome.extension.getURL("img/logo.png"),
- VERSION: VERSION,
+ VERSION: config.version,
subset: subset,
- showRelaxPandA: relaxPandA,
+ noAssignment: noAssignmentImg,
elements: {
danger: sortElements(dangerElements),
warning: sortElements(warningElements),
@@ -160,7 +161,7 @@ export function createMiniSakaiGeneralized(root: Element, assignmentList: Array<
due14d: chrome.i18n.getMessage("due14d"),
dueOver14d: chrome.i18n.getMessage("dueOver14d"),
duePassed: chrome.i18n.getMessage("duePassed"),
- relaxPandA: chrome.i18n.getMessage("no_available_assignments"),
+ noAssignment: chrome.i18n.getMessage("no_available_assignments"),
},
todoBox: {
courseName: chrome.i18n.getMessage("todo_box_course_name"),
@@ -190,8 +191,8 @@ export function createMiniSakaiGeneralized(root: Element, assignmentList: Array<
/**
* Insert miniSakai into Sakai.
*/
-function createMiniSakai(assignmentList: Array, courseSiteInfos: Array): void {
- createMiniSakaiGeneralized(miniSakai, assignmentList, courseSiteInfos, false, (rendered) => {
+async function createMiniSakai(assignmentList: Array, courseSiteInfos: Array): Promise {
+ await createMiniSakaiGeneralized(miniSakai, assignmentList, courseSiteInfos, false, (rendered) => {
miniSakai.innerHTML = rendered;
const parent = document.getElementById("pageBody");
const ref = document.getElementById("toolMenuWrap");
@@ -202,19 +203,20 @@ function createMiniSakai(assignmentList: Array, courseSiteInfos: Arr
/**
* Initialize Settings tab.
*/
-async function createSettingsTab(root: Element): Promise {
- createSettingItem(root, chrome.i18n.getMessage('settings_color_checked_item'), CPsettings.getDisplayCheckedAssignment, "displayCheckedAssignment");
- createSettingItem(root, chrome.i18n.getMessage('settings_display_late_submit_assignment'), CPsettings.getDisplayLateSubmitAssignment, "displayLateSubmitAssignment");
- createSettingItem(root, chrome.i18n.getMessage('settings_assignment_cache'), CPsettings.getAssignmentCacheInterval, "assignmentCacheInterval");
- createSettingItem(root, chrome.i18n.getMessage('settings_quizzes_cache'), CPsettings.getQuizCacheInterval, "quizCacheInterval");
+async function createSettingsTab(root: Element) {
+ const config = await loadConfigs();
+ createSettingItem(root, chrome.i18n.getMessage('settings_color_checked_item'), config.CSsettings.getDisplayCheckedAssignment, "displayCheckedAssignment");
+ createSettingItem(root, chrome.i18n.getMessage('settings_display_late_submit_assignment'), config.CSsettings.getDisplayLateSubmitAssignment, "displayLateSubmitAssignment");
+ createSettingItem(root, chrome.i18n.getMessage('settings_assignment_cache'), config.CSsettings.getAssignmentCacheInterval, "assignmentCacheInterval");
+ createSettingItem(root, chrome.i18n.getMessage('settings_quizzes_cache'), config.CSsettings.getQuizCacheInterval, "quizCacheInterval");
- createSettingItem(root, chrome.i18n.getMessage('settings_colors_hour', ['1', 24]), CPsettings.getTopColorDanger, "topColorDanger");
- createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['1', 5]), CPsettings.getTopColorWarning, "topColorWarning");
- createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['1', 14]), CPsettings.getTopColorSuccess, "topColorSuccess");
+ createSettingItem(root, chrome.i18n.getMessage('settings_colors_hour', ['1', 24]), config.CSsettings.getTopColorDanger, "topColorDanger");
+ createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['1', 5]), config.CSsettings.getTopColorWarning, "topColorWarning");
+ createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['1', 14]), config.CSsettings.getTopColorSuccess, "topColorSuccess");
- createSettingItem(root, chrome.i18n.getMessage('settings_colors_hour', ['2', 24]), CPsettings.getMiniColorDanger, "miniColorDanger");
- createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['2', 5]), CPsettings.getMiniColorWarning, "miniColorWarning");
- createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['2', 14]), CPsettings.getMiniColorSuccess, "miniColorSuccess");
+ createSettingItem(root, chrome.i18n.getMessage('settings_colors_hour', ['2', 24]), config.CSsettings.getMiniColorDanger, "miniColorDanger");
+ createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['2', 5]), config.CSsettings.getMiniColorWarning, "miniColorWarning");
+ createSettingItem(root, chrome.i18n.getMessage('settings_colors_day', ['2', 14]), config.CSsettings.getMiniColorSuccess, "miniColorSuccess");
createSettingItem(root, chrome.i18n.getMessage("settings_reset_colors"), "reset", "reset");
// @ts-ignore
@@ -292,13 +294,14 @@ function initState(root: Element) {
* Display miniSakai
*/
async function displayMiniSakai(mergedAssignmentList: Array, courseSiteInfos: Array): Promise{
- createMiniSakai(mergedAssignmentList, courseSiteInfos);
+ await createMiniSakai(mergedAssignmentList, courseSiteInfos);
}
/**
* Add notification badge for new Assignment/Quiz
*/
-function createFavoritesBarNotification(courseSiteInfos: Array, assignmentList: Array): void {
+async function createFavoritesBarNotification(courseSiteInfos: Array, assignmentList: Array): Promise {
+ const config = await loadConfigs();
const defaultTab = document.querySelectorAll(".Mrphs-sitesNav__menuitem");
const defaultTabCount = Object.keys(defaultTab).length;
@@ -311,7 +314,7 @@ function createFavoritesBarNotification(courseSiteInfos: Array,
return assignment.courseSiteInfo.courseID === courseID;
});
if (q !== -1) {
- const closestTime = (CPsettings.displayCheckedAssignment) ? assignmentList[q].closestDueDateTimestamp : assignmentList[q].closestDueDateTimestampExcludeFinished;
+ const closestTime = (config.CSsettings.displayCheckedAssignment) ? assignmentList[q].closestDueDateTimestamp : assignmentList[q].closestDueDateTimestampExcludeFinished;
if (!assignmentList[q].isRead && closestTime !== -1) {
defaultTab[j].classList.add("cs-notification-badge");
}
@@ -347,7 +350,7 @@ function createFavoritesBarNotification(courseSiteInfos: Array,
}
}
}
- overrideCSSColor();
+ await overrideCSSColor();
}
/**
@@ -368,11 +371,12 @@ function deleteFavoritesBarNotification(): void {
/**
* Override CSS of favorites bar and miniSakai.
*/
-function overrideCSSColor() {
+async function overrideCSSColor() {
+ const config = await loadConfigs();
const overwriteborder = function (className: string, color: string | undefined) {
- const dangerelem = document.getElementsByClassName(className);
- for (let i = 0; i < dangerelem.length; i++) {
- const elem = dangerelem[i] as HTMLElement;
+ const element = document.getElementsByClassName(className);
+ for (let i = 0; i < element.length; i++) {
+ const elem = element[i] as HTMLElement;
const attr = "solid 2px " + color;
(elem.style)["border-top"] = attr;
(elem.style)["border-left"] = attr;
@@ -381,25 +385,26 @@ function overrideCSSColor() {
}
};
const overwritebackground = function (className: string, color: string | undefined) {
- const dangerelem = document.getElementsByClassName(className);
- for (let i = 0; i < dangerelem.length; i++) {
- const elem = dangerelem[i] as HTMLElement;
+ const element = document.getElementsByClassName(className);
+ for (let i = 0; i < element.length; i++) {
+ const elem = element[i] as HTMLElement;
elem.setAttribute("style", "background:" + color + "!important");
}
};
- overwriteborder("cs-assignment-danger", CPsettings.getMiniColorDanger);
- overwriteborder("cs-assignment-success", CPsettings.getMiniColorSuccess);
- overwriteborder("cs-assignment-warning", CPsettings.getMiniColorWarning);
- overwritebackground("cs-course-danger", CPsettings.getMiniColorDanger);
- overwritebackground("cs-course-success", CPsettings.getMiniColorSuccess);
- overwritebackground("cs-course-warning", CPsettings.getMiniColorWarning);
- overwritebackground("cs-tab-danger", CPsettings.getTopColorDanger);
- overwritebackground("cs-tab-success", CPsettings.getTopColorSuccess);
- overwritebackground("cs-tab-warning", CPsettings.getTopColorWarning);
- overwriteborder("cs-tab-danger", CPsettings.getTopColorDanger);
- overwriteborder("cs-tab-success", CPsettings.getTopColorSuccess);
- overwriteborder("cs-tab-warning", CPsettings.getTopColorWarning);
+ // Overwrite colors
+ overwritebackground("cs-course-danger", config.CSsettings.getMiniColorDanger);
+ overwritebackground("cs-course-warning", config.CSsettings.getMiniColorWarning);
+ overwritebackground("cs-course-success", config.CSsettings.getMiniColorSuccess);
+ overwritebackground("cs-tab-danger", config.CSsettings.getTopColorDanger);
+ overwritebackground("cs-tab-warning", config.CSsettings.getTopColorWarning);
+ overwritebackground("cs-tab-success", config.CSsettings.getTopColorSuccess);
+ overwriteborder("cs-assignment-danger", config.CSsettings.getMiniColorDanger);
+ overwriteborder("cs-assignment-warning", config.CSsettings.getMiniColorWarning);
+ overwriteborder("cs-assignment-success", config.CSsettings.getMiniColorSuccess);
+ overwriteborder("cs-tab-danger", config.CSsettings.getTopColorDanger);
+ overwriteborder("cs-tab-warning", config.CSsettings.getTopColorWarning);
+ overwriteborder("cs-tab-success", config.CSsettings.getTopColorSuccess);
}
export {
diff --git a/src/settings.ts b/src/settings.ts
index 3ec9482..c17f1a5 100644
--- a/src/settings.ts
+++ b/src/settings.ts
@@ -1,5 +1,6 @@
import { loadFromLocalStorage } from "./storage";
import { convertArrayToSettings } from "./utils";
+import { getBaseURL } from "./network";
export class Settings {
assignmentCacheInterval?: number;
@@ -67,7 +68,48 @@ export class DefaultSettings extends Settings {
export async function loadSettings(): Promise {
const settingsArr = await loadFromLocalStorage("CS_Settings");
- const CPsettings = convertArrayToSettings(settingsArr);
- CPsettings.displayCheckedAssignment = CPsettings.getDisplayCheckedAssignment;
- return CPsettings;
+ const CSsettings = convertArrayToSettings(settingsArr);
+ CSsettings.displayCheckedAssignment = CSsettings.getDisplayCheckedAssignment;
+ return CSsettings;
+}
+
+export interface Config {
+ baseURL: string;
+ version: string;
+ CSsettings: Settings;
+ fetchedTime: {
+ assignment: number;
+ quiz: number;
+ };
+ cacheInterval: {
+ assignment: number;
+ quiz: number;
+ };
+}
+
+/**
+ * Load configurations from local storage
+ */
+export async function loadConfigs(): Promise {
+ const baseURL = getBaseURL();
+ const VERSION = chrome.runtime.getManifest().version;
+ const CSsettings = await loadSettings();
+ CSsettings.displayCheckedAssignment = CSsettings.getDisplayCheckedAssignment;
+ const assignmentCacheInterval = CSsettings.getAssignmentCacheInterval;
+ const quizCacheInterval = CSsettings.getQuizCacheInterval;
+ const assignmentFetchedTime = await loadFromLocalStorage("CS_AssignmentFetchTime", "undefined");
+ const quizFetchedTime = await loadFromLocalStorage("CS_QuizFetchTime", "undefined");
+ return {
+ baseURL: baseURL,
+ version: VERSION,
+ CSsettings: CSsettings,
+ cacheInterval: {
+ assignment: assignmentCacheInterval,
+ quiz: quizCacheInterval,
+ },
+ fetchedTime: {
+ assignment: assignmentFetchedTime,
+ quiz: quizFetchedTime,
+ },
+ };
}
diff --git a/src/subsakai.ts b/src/subsakai.ts
index b86dbee..58cf4eb 100644
--- a/src/subsakai.ts
+++ b/src/subsakai.ts
@@ -20,7 +20,7 @@ async function updateSubSakai(root: Element) {
mergedAssignmentList = mergeIntoAssignmentList(mergedAssignmentList, assignmentMemoList);
mergedAssignmentList = sortAssignmentList(mergedAssignmentList);
- createMiniSakaiGeneralized(root, mergedAssignmentList, courseIDs, true, (rendered) => {
+ await createMiniSakaiGeneralized(root, mergedAssignmentList, courseIDs, true, (rendered) => {
console.log(rendered);
root.innerHTML = rendered;
});