MDL-66845 mod_forum: Convert user picker to class
authorAndrew Nicols <andrew@nicols.co.uk>
Sat, 5 Oct 2019 08:07:43 +0000 (16:07 +0800)
committerMathew May <mathewm@hotmail.co.nz>
Wed, 30 Oct 2019 02:23:41 +0000 (10:23 +0800)
Part of MDL-66074

mod/forum/amd/build/local/grades/grader.min.js
mod/forum/amd/build/local/grades/grader.min.js.map
mod/forum/amd/build/local/grades/local/grader/user_picker.min.js
mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map
mod/forum/amd/src/local/grades/grader.js
mod/forum/amd/src/local/grades/local/grader/user_picker.js

index 5ee007b..8db2e6c 100644 (file)
Binary files a/mod/forum/amd/build/local/grades/grader.min.js and b/mod/forum/amd/build/local/grades/grader.min.js differ
index ce4ed19..6940597 100644 (file)
Binary files a/mod/forum/amd/build/local/grades/grader.min.js.map and b/mod/forum/amd/build/local/grades/grader.min.js.map differ
index 93e3993..9cb271e 100644 (file)
Binary files a/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js and b/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js differ
index ecf5061..67fb8a6 100644 (file)
Binary files a/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map and b/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map differ
index 2697509..0a842c4 100644 (file)
@@ -24,7 +24,7 @@
 import Templates from 'core/templates';
 // TODO import Notification from 'core/notification';
 import Selectors from './local/grader/selectors';
-import * as UserPicker from './local/grader/user_picker';
+import getUserPicker from './local/grader/user_picker';
 import {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';
 import getGradingPanelFunctions from './local/grader/gradingpanel';
 import {add as addToast} from 'core/toast';
@@ -116,18 +116,22 @@ export const launch = async(getListOfUsers, getContentForUser, getGradeForUser,
     ]);
     const graderContainer = graderLayout.getContainer();
 
+    const saveGradeFunction = getSaveUserGradeFunction(graderContainer, setGradeForUser);
+
     Templates.replaceNodeContents(graderContainer, graderHTML, '');
     registerEventListeners(graderLayout);
     const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser);
 
-    const pickerHTML = await UserPicker.buildPicker(
+    // Fetch the userpicker for display.
+    const userPicker = await getUserPicker(
         userList,
         initialUserId,
         updateUserContent,
-        getSaveUserGradeFunction(graderContainer, setGradeForUser)
+        saveGradeFunction
     );
 
-    displayUserPicker(graderContainer, pickerHTML);
+    // Display the newly created user picker.
+    displayUserPicker(graderContainer, userPicker.rootNode);
 };
 
 export {getGradingPanelFunctions};
index 51f3818..252ecfa 100644 (file)
 import Templates from 'core/templates';
 import Selectors from './user_picker/selectors';
 
-const renderNavigator = () => {
-    return Templates.render('mod_forum/local/grades/local/grader/user_picker', {});
-};
+const templatePath = 'mod_forum/local/grades/local/grader';
 
-const renderUserChange = (context) => {
-    return Templates.render('mod_forum/local/grades/local/grader/user_picker/user', context);
-};
+class UserPicker {
 
-const showUser = async(root, users, currentUserIndex, showUserCallback) => {
-    const user = {
-        ...users[currentUserIndex],
-        total: users.length,
-        displayIndex: currentUserIndex + 1,
-    };
-    const [html] = await Promise.all([renderUserChange(user), showUserCallback(user)]);
-    const userRegion = root.querySelector(Selectors.regions.userRegion);
-    Templates.replaceNodeContents(userRegion, html, '');
-};
+    /**
+     * Constructor for the User Picker.
+     *
+     * @param {Array} userList List of users
+     * @param {Number} initialUserId The ID of the initial user to display
+     * @param {Function} showUserCallback The callback used to display the user
+     * @param {Function} preChangeUserCallback The callback to use before changing user
+     * @param {Bool} render Whether to render on instantiation
+     */
+    constructor(userList, initialUserId, showUserCallback, preChangeUserCallback, render = true) {
+        this.userList = userList;
+        this.showUserCallback = showUserCallback;
+        this.preChangeUserCallback = preChangeUserCallback;
+
+        // Determine the current index.
+        this.currentUserIndex = userList.findIndex(user => {
+            return user.id === parseInt(initialUserId);
+        });
+
+        // Ensure that render is bound correctly.
+        this.render = this.render.bind(this);
 
-const bindEvents = (root, users, currentUserIndex, showUserCallback, saveUserCallback) => {
-    root.addEventListener('click', (e) => {
-        const button = e.target.closest(Selectors.actions.changeUser);
-        if (button) {
-            saveUserCallback(users[currentUserIndex]);
-            currentUserIndex += parseInt(button.dataset.direction);
-            showUser(root, users, currentUserIndex, showUserCallback);
+        if (render) {
+            this.render();
         }
-    });
-};
+    }
+
+    /**
+     * Render the user picker.
+     */
+    async render() {
+        // Create the root node.
+        this.root = document.createElement('div');
+
+        const {html, js} = await this.renderNavigator();
+        Templates.replaceNodeContents(this.root, html, js);
+
+        // Call the showUser function to show the first user immediately.
+        await this.showUser(this.currentUser);
+
+        // Ensure that the event listeners are all bound.
+        this.registerEventListeners();
+    }
 
-export const buildPicker = async(users, currentUserID, showUserCallback, saveUserCallback) => {
-    let root = document.createElement('div');
+    /**
+     * Render the navigator itself.
+     *
+     * @returns {Promise}
+     */
+    renderNavigator() {
+        return Templates.renderForPromise(`${templatePath}/user_picker`, {});
+    }
 
-    const [html] = await Promise.all([renderNavigator()]);
-    Templates.replaceNodeContents(root, html, '');
+    /**
+     * Render the current user details for the picker.
+     *
+     * @param {Object} context The data used to render the user picker.
+     * @returns {Promise}
+     */
+    renderUserChange(context) {
+        return Templates.renderForPromise(`${templatePath}/user_picker/user`, context);
+    }
 
-    const currentUserIndex = users.findIndex((user) => {
-        return user.id === parseInt(currentUserID);
-    });
+    /**
+     * Show the specified user in the picker.
+     *
+     * @param {Object} user
+     */
+    async showUser(user) {
+        const [{html, js}] = await Promise.all([this.renderUserChange(user), this.showUserCallback(user)]);
+        const userRegion = this.root.querySelector(Selectors.regions.userRegion);
+        Templates.replaceNodeContents(userRegion, html, js);
+    }
 
-    await showUser(root, users, currentUserIndex, showUserCallback);
+    /**
+     * Register the event listeners for the user picker.
+     */
+    registerEventListeners() {
+        this.root.addEventListener('click', (e) => {
+            const button = e.target.closest(Selectors.actions.changeUser);
+            if (button) {
+                this.preChangeUserCallback(this.currentUser);
+                this.updateIndex(parseInt(button.dataset.direction));
+                this.showUser(this.currentUser);
+            }
+        });
+    }
 
-    bindEvents(root, users, currentUserIndex, showUserCallback, saveUserCallback);
+    /**
+     * Update the current user index.
+     *
+     * @param {Number} direction
+     * @returns {Number}}
+     */
+    updateIndex(direction) {
+        this.currentUserIndex += direction;
+
+        // Loop around the edges.
+        if (this.currentUserIndex < 0) {
+            this.currentUserIndex = this.userList.length - 1;
+        } else if (this.currentUserIndex > this.userList.length - 1) {
+            this.currentUserIndex = 0;
+        }
+
+        return this.currentUserIndex;
+    }
+
+    /**
+     * Get the details of the user currently shown with the total number of users, and the 1-indexed count of the
+     * current user.
+     *
+     * @returns {Object}
+     */
+    get currentUser() {
+        return {
+            ...this.userList[this.currentUserIndex],
+            total: this.userList.length,
+            displayIndex: this.currentUserIndex + 1,
+        };
+    }
+
+    /**
+     * Get the root node for the User Picker.
+     *
+     * @returns {HTMLElement}
+     */
+    get rootNode() {
+        return this.root;
+    }
+}
+
+/**
+ * Create a new user picker.
+ *
+ * @param {Array} users The list of users
+ * @param {Number} currentUserID The userid of the current user
+ * @param {Function} showUserCallback The function to call to show a specific user
+ * @param {Function} preChangeUserCallback The fucntion to call to save the grade for the current user
+ * @returns {UserPicker}
+ */
+export default async(users, currentUserID, showUserCallback, preChangeUserCallback) => {
+    const userPicker = new UserPicker(users, currentUserID, showUserCallback, preChangeUserCallback, false);
+    await userPicker.render();
 
-    return root;
+    return userPicker;
 };