diff --git a/.eslintrc.json b/.eslintrc.json index 6f824cb..8ad1efa 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,44 +1,55 @@ { - "env": { - "browser": true, - "es2021": true + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "plugin:react/recommended", + "airbnb", + "prettier" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true }, - "extends": [ - "plugin:react/recommended", - "airbnb", - "prettier" + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "react", + "eslint-plugin-prettier" + ], + "rules": { + "react/jsx-filename-extension": [ + 1, + { + "extensions": [ + ".js", + ".jsx" + ] + } ], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": [ - "react" + "no-console": "off", + "no-unused-vars": "off", + "react/react-in-jsx-scope": "off", + "import/prefer-default-export": "off", + "indent": [ + "off", + 0 ], - "rules": { - "react/jsx-filename-extension": [ - 1, - { - "extensions": [ - ".js", - ".jsx" - ] - } - ], - "no-console": "off", - "no-unused-vars": "off", - "react/react-in-jsx-scope": "off", - "indent": [ - "warn", - 2 - ], - "react/prop-types": "off", - "default-param-last": "off", - "default-case": "off", - "no-case-declarations": "off", - "jsx-a11y/anchor-is-valid": "off" - } + "react/prop-types": "off", + "default-param-last": "off", + "default-case": "off", + "no-case-declarations": "off", + "jsx-a11y/anchor-is-valid": "off", + "prettier/prettier": [ + "error", + { + "singleQuote": true, + "tabWidth": 2, + "semi": true, + "endOfLine": "lf" + } + ] + } } \ No newline at end of file diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 512437e..2817c2f 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -11,7 +11,7 @@ on: jobs: build: - runs-on: self-hosted + runs-on: ubuntu-latest strategy: matrix: @@ -19,16 +19,13 @@ jobs: # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: clean: false - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm ci - run: npm run build --if-present - - run: pm2 reload next-js - env: - CI: true diff --git a/.vscode/settings.json b/.vscode/settings.json index c3fce85..be09572 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { - "editor.defaultFormatter": "esbenp.prettier-vscode", + "[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, + "[javascriptreact]": { "editor.defaultFormatter": "rvest.vs-code-prettier-eslint" }, + "[typescript]": { "editor.defaultFormatter": "rvest.vs-code-prettier-eslint" }, "editor.formatOnPaste": true, "editor.formatOnSave": true, "editor.formatOnType": true diff --git a/actions.js b/actions.js index cebd57b..b709408 100644 --- a/actions.js +++ b/actions.js @@ -2,7 +2,6 @@ import { signOut } from 'next-auth/react'; import * as types from './types'; - // https://allover.twodee.org/remote-state/fetching-memories/ function assertResponse(response) { if (response.status >= 200 && response.status < 300) { @@ -39,73 +38,69 @@ export function retrieveEnrollments(djangoToken) { export function fetchEnrollments() { return (dispatch, getState) => { - const { currentUser: {token} } = getState(); + const { + currentUser: { token }, + } = getState(); return token ? retrieveEnrollments(token) - .then((courses) => dispatch(gotEnrollments(courses))) - .catch((...rest) => { - console.log('catch rest'); - console.log(rest); - }) + .then((courses) => dispatch(gotEnrollments(courses))) + .catch((...rest) => { + console.log('catch rest'); + console.log(rest); + }) : null; }; } export const newCourse = - ({ - name, - startDate: start_date, - endDate: end_date, - slug = 'slug', - userId, - }) => - async(dispatch, getState) => { - const { - currentUser: { token } - } = getState(); - const params = { - name, - start_date, - end_date, - slug, - owner: userId, - }; - const options = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Token ${token}`, - }, - body: JSON.stringify(params), - }; + ({ name, startDate: start_date, endDate: end_date, slug = 'slug', userId }) => + async (dispatch, getState) => { + const { + currentUser: { token }, + } = getState(); + const params = { + name, + start_date, + end_date, + slug, + owner: userId, + }; + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Token ${token}`, + }, + body: JSON.stringify(params), + }; - const enrollOptions = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Token ${token}`, - }, - }; - var newSlug; - await fetch(`${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/`, options) - .then(assertResponse) - .then((response) => response.json()) - .then((data) => { - const enrollParams = { - user: userId, - role: 1, - course: data.id, - }; - newSlug = data.slug; - enrollOptions.body = JSON.stringify(enrollParams); - return fetch( - `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/enrollments/`, - enrollOptions - ); - }) - .then(() => dispatch(fetchEnrollments())); - return newSlug; + const enrollOptions = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Token ${token}`, + }, }; + let newSlug; + await fetch(`${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/`, options) + .then(assertResponse) + .then((response) => response.json()) + .then((data) => { + const enrollParams = { + user: userId, + role: 1, + course: data.id, + }; + newSlug = data.slug; + enrollOptions.body = JSON.stringify(enrollParams); + return fetch( + `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/enrollments/`, + enrollOptions, + ); + }) + .then(() => dispatch(fetchEnrollments())); + return newSlug; + }; export function addedFromRoster(courseSlug, enrollments) { return { @@ -129,17 +124,17 @@ export function fetchRoster({ courseSlug }) { Authorization: `Token ${token}`, 'Content-Type': 'application/json', }, - } + }, ) .then((response) => response.json()) - .then((enrollments) => dispatch(gotRoster({enrollments, courseSlug}))); + .then((enrollments) => dispatch(gotRoster({ enrollments, courseSlug }))); }; } export function uploadRoster({ body, courseSlug }) { return (dispatch, getState) => { const { - currentUser: { token } + currentUser: { token }, } = getState(); fetch( `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/${courseSlug}/roster/`, @@ -149,17 +144,15 @@ export function uploadRoster({ body, courseSlug }) { }, method: 'POST', body, - } + }, ) .then(assertResponse) .then((response) => response.json()) .then((res) => { dispatch(addedFromRoster(courseSlug, res)); }) - .then(() => - dispatch(fetchRoster({ djangoToken: token, courseSlug })) - ); - } + .then(() => dispatch(fetchRoster({ djangoToken: token, courseSlug }))); + }; } export function gotInstruments(instruments) { @@ -182,16 +175,16 @@ export function fetchInstruments() { }) .then(assertResponse) .then((response) => response.json()) - .then((instruments) => + .then((instruments) => dispatch( - gotInstruments(instruments.sort((a, b) => (a.name < b.name ? -1 : 1))) - ) + gotInstruments( + instruments.sort((a, b) => (a.name < b.name ? -1 : 1)), + ), + ), ); - } + }; } - - export function enrollmentUpdated({ enrollment, instrument }) { return { type: types.Action.UpdatedEnrollmentInstrument, @@ -209,10 +202,7 @@ export function setInstrumentActivity(enrollmentId, activityState) { }; } -export function updateEnrollmentInstrument({ - enrollmentId, - instrument, -}) { +export function updateEnrollmentInstrument({ enrollmentId, instrument }) { return (dispatch, getState) => { const { currentUser: { token }, @@ -227,19 +217,19 @@ export function updateEnrollmentInstrument({ }, method: 'PATCH', body: JSON.stringify({ instrument: instrument.id }), - } + }, ) .then(assertResponse) .then((res) => res.json()) .then((enrollment) => { dispatch( - setInstrumentActivity(enrollmentId, types.ActivityState.Success) + setInstrumentActivity(enrollmentId, types.ActivityState.Success), ); dispatch(enrollmentUpdated({ enrollment, instrument })); }) .catch(() => { dispatch( - setInstrumentActivity(enrollmentId, types.ActivityState.Erroneous) + setInstrumentActivity(enrollmentId, types.ActivityState.Erroneous), ); }); }; @@ -264,11 +254,11 @@ export function fetchStudentAssignments({ slug }) { Authorization: `Token ${token}`, 'Content-Type': 'application/json', }, - } + }, ) .then((response) => response.json()) .then((assignments) => dispatch(gotAssignments(assignments))); - } + }; } export function loggedOut() { @@ -292,7 +282,7 @@ export function logoutUser() { .then(assertResponse) .then((res) => res.json()) .then(loggedOut); - } + }; } export function gotActivities({ activities, slug }) { @@ -310,22 +300,25 @@ export function fetchActivities({ slug }) { const { currentUser: { token }, } = getState(); - return token && fetch( - `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/${slug}/assignments/`, - { - headers: { - Authorization: `Token ${token}`, - 'Content-Type': 'application/json', + return ( + token && + fetch( + `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/${slug}/assignments/`, + { + headers: { + Authorization: `Token ${token}`, + 'Content-Type': 'application/json', + }, }, - } - ) - .then(assertResponse) - .then((response) => response.json()) - .then((activities) => dispatch(gotActivities({ activities, slug }))) - .catch((e) => { - console.error('caught', e) - }); - } + ) + .then(assertResponse) + .then((response) => response.json()) + .then((activities) => dispatch(gotActivities({ activities, slug }))) + .catch((e) => { + console.error('caught', e); + }) + ); + }; } export function gotPieces(pieces) { @@ -351,7 +344,7 @@ export function fetchPieces() { .then((pieces) => { dispatch(gotPieces(pieces.sort((a, b) => (a.name < b.name ? -1 : 1)))); }); - } + }; } export function assignedPiece({ piece, slug }) { @@ -385,12 +378,12 @@ export function assignPiece({ slug, piece }) { method: 'POST', body: JSON.stringify({ piece_id: piece.id }), // body: data, - } + }, ) .then(assertResponse) .then((response) => response.json()) .then((pieceResponse) => dispatch(assignedPiece({ piece, slug }))); - } + }; } export function setPieceChangeState({ piece, state }) { @@ -409,7 +402,7 @@ export function unassignPiece({ piece, slug }) { setPieceChangeState({ pieceId: piece.id, state: types.ActivityState.Active, - }) + }), ); // const data = new FormData(); // data.append("piece_id", piece); @@ -423,7 +416,7 @@ export function unassignPiece({ piece, slug }) { method: 'POST', body: JSON.stringify({ piece_id: piece.id }), // body: data, - } + }, ) .then(assertResponse) .then(() => dispatch(unassignedPiece({ piece, slug }))) @@ -432,15 +425,15 @@ export function unassignPiece({ piece, slug }) { setPieceChangeState({ pieceId: piece.id, state: types.ActivityState.Success, - }) - ) + }), + ), ) .catch((err) => { dispatch( setPieceChangeState({ pieceId: piece.id, state: types.ActivityState.Erroneous, - }) + }), ); }); }; @@ -482,7 +475,7 @@ export function getUserProfile() { signOut({ callbackUrl: '/' }); } }); - } + }; } export function selectEnrollment(enrollment) { @@ -502,7 +495,7 @@ export function selectAssignment(assignment) { export function beginUpload(id) { return { type: types.Action.BeginUpload, - payload: {id} + payload: { id }, }; } @@ -526,14 +519,13 @@ export function uploadFailed(id) { }; } - export function postRecording({ slug, assignmentId, audio, composition, submissionId, - index=0 + index = 0, }) { return (dispatch, getState) => { const { @@ -542,13 +534,13 @@ export function postRecording({ dispatch(beginUpload(submissionId)); // let body = '' - let bodyObj = {"content":"N/A for Perform submissions"}; + let bodyObj = { content: 'N/A for Perform submissions' }; if (composition) { bodyObj = { content: composition }; } - + bodyObj.index = index; - let body = JSON.stringify(bodyObj); + const body = JSON.stringify(bodyObj); return fetch( `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/${slug}/assignments/${assignmentId}/submissions/`, { @@ -558,7 +550,7 @@ export function postRecording({ }, method: 'POST', body, - } + }, ) .then(assertResponse) .then((res) => res.json()) @@ -571,12 +563,11 @@ export function postRecording({ }, method: 'POST', body: audio, - } + }, ) .then(assertResponse) .then((response) => response.json()) - .then((res) => { - }); + .then((res) => {}); }) .then(() => { // success case @@ -601,8 +592,13 @@ export function postRespond({ slug, assignmentId, response }) { currentUser: { token }, } = getState(); if (!slug || !assignmentId || !response) { - console.error('missing requirements to submit', slug, assignmentId, response) - return; + console.error( + 'missing requirements to submit', + slug, + assignmentId, + response, + ); + return null; } dispatch(beginUpload(assignmentId)); const body = JSON.stringify({ content: JSON.stringify(response) }); @@ -615,7 +611,7 @@ export function postRespond({ slug, assignmentId, response }) { }, method: 'POST', body, - } + }, ) .then(assertResponse) .then((res) => res.json()) @@ -652,7 +648,7 @@ export function postConnect({ slug, assignmentId, response }) { }, method: 'POST', body, - } + }, ) .then(assertResponse) .then((res) => res.json()) @@ -673,7 +669,6 @@ export function postConnect({ slug, assignmentId, response }) { }; } - export function gotSingleStudentAssignment(assignment) { return { type: types.Action.GotSingleAssignment, @@ -684,7 +679,7 @@ export function gotSingleStudentAssignment(assignment) { export function fetchSingleStudentAssignment({ slug, assignmentId }) { if (!assignmentId) { console.error('assignmentId is required'); - return; + return null; } return (dispatch, getState) => { const { @@ -697,16 +692,16 @@ export function fetchSingleStudentAssignment({ slug, assignmentId }) { Authorization: `Token ${token}`, 'Content-Type': 'application/json', }, - } + }, ) .then(assertResponse) .then((response) => response.json()) .then((assignment) => dispatch(selectAssignment(assignment))); - } + }; } export function didInstrument() { return { type: types.Action.DidInstrument, }; -} \ No newline at end of file +} diff --git a/api.js b/api.js index 765969a..6f893e6 100644 --- a/api.js +++ b/api.js @@ -11,11 +11,16 @@ function assertResponse(response) { async function getDjangoToken() { const session = await getSession(); - if (!session || !session.djangoToken) return; - return session.djangoToken + if (!session || !session.djangoToken) return null; + return session.djangoToken; } -async function makeRequest(endpoint, method="GET", body=null, headers={}) { +async function makeRequest( + endpoint, + method = 'GET', + body = null, + headers = {}, +) { const token = await getDjangoToken(); if (!token) return {}; @@ -23,16 +28,16 @@ async function makeRequest(endpoint, method="GET", body=null, headers={}) { ...headers, Authorization: `Token ${token}`, 'Content-Type': 'application/json', - } + }; const API = `${process.env.NEXT_PUBLIC_BACKEND_HOST}/api`; - const url = `${API}/${endpoint}` + const url = `${API}/${endpoint}`; const response = await fetch(url, { method, headers: requestHeaders, - body: body ? JSON.stringify(body) : null - }) + body: body ? JSON.stringify(body) : null, + }); assertResponse(response); @@ -41,7 +46,7 @@ async function makeRequest(endpoint, method="GET", body=null, headers={}) { } export async function getEnrollments() { - const endpoint = "enrollments/"; + const endpoint = 'enrollments/'; const json = await makeRequest(endpoint); return json; } @@ -50,32 +55,32 @@ export function getStudentAssignments(slug) { return async () => { const endpoint = `courses/${slug}/assignments/`; const json = await makeRequest(endpoint); - return json - } + return json; + }; } export function getAllPieces(slug) { return async () => { const endpoint = `courses/${slug}/piece-plans/`; const json = await makeRequest(endpoint); - return json.map((r) => ({...r.piece, piece_plan_id: r.id})); - } + return json.map((r) => ({ ...r.piece, piece_plan_id: r.id })); + }; } export function mutateAssignPiece(slug) { return async (piecePlanId) => { - const endpoint = `courses/${slug}/assign_piece_plan/` - const json = await makeRequest(endpoint, 'POST', {piece_id: piecePlanId}) - return json - } + const endpoint = `courses/${slug}/assign_piece_plan/`; + const json = await makeRequest(endpoint, 'POST', { piece_id: piecePlanId }); + return json; + }; } export function mutateUnassignPiece(slug) { return async (piece) => { - const endpoint = `courses/${slug}/unassign/` - const json = await makeRequest(endpoint, 'POST', {piece_id: piece.id}); - return json - } + const endpoint = `courses/${slug}/unassign/`; + const json = await makeRequest(endpoint, 'POST', { piece_id: piece.id }); + return json; + }; } export function getRecentSubmissions({ slug, piece, partType }) { @@ -83,40 +88,40 @@ export function getRecentSubmissions({ slug, piece, partType }) { const endpoint = `courses/${slug}/submissions/recent/?piece_slug=${piece}&activity_name=${partType}`; const json = await makeRequest(endpoint); return json; - } + }; } export function mutateGradeSubmission(slug) { - return async ({ student_submission, rhythm, tone, expression, grader }) => { + return async ({ studentSubmission, rhythm, tone, expression, grader }) => { const endpoint = `courses/${slug}/grades/`; const body = { - student_submission: [student_submission], + student_submission: [studentSubmission], own_submission: [], rhythm, tone, expression, - grader + grader, }; - + const json = await makeRequest(endpoint, 'POST', body); - + return json; - } + }; } // should i make this mutator optionally have a recording or?? export function mutateCreateSubmission({ slug }) { return async (submission, assignmentId) => { - const endpoint = `courses/${slug}/assignments/${assignmentId}/submissions/` - - const json = await makeRequest(endpoint, 'POST', submission) - + const endpoint = `courses/${slug}/assignments/${assignmentId}/submissions/`; + + const json = await makeRequest(endpoint, 'POST', submission); + return json; - } + }; } export async function getMySubmissionsForAssignment({ slug, assignmentId }) { - const endpoint = `courses/${slug}/assignments/${assignmentId}/submissions/` + const endpoint = `courses/${slug}/assignments/${assignmentId}/submissions/`; const json = await makeRequest(endpoint); return json; } @@ -124,28 +129,28 @@ export async function getMySubmissionsForAssignment({ slug, assignmentId }) { export function mutateCourse(slug) { // expecting params to be any subset of name, start_date, end_date, slug return async (params) => { - const endpoint = `courses/${slug}/` - + const endpoint = `courses/${slug}/`; + const json = await makeRequest(endpoint, 'PATCH', params); - + return json; - } + }; } - + export async function mutateAssignmentInstrument(slug, pieceId, instrument) { const endpoint = `courses/${slug}/change_piece_instrument/`; - const body = {piece_id: pieceId, instrument_id: instrument.id}; - + const body = { piece_id: pieceId, instrument_id: instrument.id }; + const json = await makeRequest(endpoint, 'PATCH', body); - + return json; } export function getAssignedPieces(assignments) { return () => { const pieces = {}; - if (Object.values(assignments).length == 0) return pieces; - + if (Object.values(assignments).length === 0) return pieces; + for (const pieceKey of Object.keys(assignments)) { for (const pieceAssignment of assignments[pieceKey]) { if (!(pieceKey in pieces)) { @@ -167,4 +172,3 @@ export function getAssignedPieces(assignments) { return pieces; }; } - diff --git a/components/chordScaleBucketScore.js b/components/chordScaleBucketScore.js index 5fe7160..40a56aa 100644 --- a/components/chordScaleBucketScore.js +++ b/components/chordScaleBucketScore.js @@ -1,6 +1,11 @@ import React, { useEffect, useState } from 'react'; import Embed from 'flat-embed'; -import { colorNotes, getChordScaleInKey, keyFromScoreJSON, colorMap} from '../lib/flat'; +import { + colorNotes, + getChordScaleInKey, + keyFromScoreJSON, + colorMap, +} from '../lib/flat'; function ChordScaleBucketScore({ height, @@ -14,13 +19,13 @@ function ChordScaleBucketScore({ const editorRef = React.createRef(); // *FIX* Need to get rid of arrow, make it a normal function as we did with keyFromScoreJSON, and getChordScaleInKey below. - function embedTransposed ( + function embedTransposed( bucket, transposeEmbed, // templt, keySig, instrName, - octaveShift + octaveShift, ) { const template = JSON.parse( JSON.stringify({ @@ -79,7 +84,7 @@ function ChordScaleBucketScore({ }, ], }, - }) + }), ); // change the notes in the score from whatever they are in tonic and eb to what we're given const scorePart = @@ -103,7 +108,7 @@ function ChordScaleBucketScore({ note.pitch.alter = alter; } return note; - } + }, ); // change the key signature in the score from whatever it is in tonic and eb to what we're given @@ -111,19 +116,22 @@ function ChordScaleBucketScore({ (element) => { if (element.key) { // FIXME + // eslint-disable-next-line no-param-reassign element.key.fifths = keySig.keyAsJSON.fifths; } if (element.clef) { // FIXME + // eslint-disable-next-line no-param-reassign element.clef = keySig.clef; } - } + }, ); if (octaveShift !== 0) { template?.[ 'score-partwise' ]?.part?.[0]?.measure?.[0]?.attributes?.forEach((element) => { + // eslint-disable-next-line no-param-reassign element.transpose = { chromatic: '0', 'octave-change': `${octaveShift}`, @@ -134,7 +142,7 @@ function ChordScaleBucketScore({ .ready() .then(() => transposeEmbed.loadJSON(template)); return resultTransposed; - }; + } useEffect(() => { const embedParams = { @@ -165,7 +173,11 @@ function ChordScaleBucketScore({ }, [height]); useEffect(() => { - if (referenceScoreJSON !== '' && referenceScoreJSON !== undefined && embed) { + if ( + referenceScoreJSON !== '' && + referenceScoreJSON !== undefined && + embed + ) { // Makes sure we don't accidentally run this code and prevents runtime error. const copyJSON = JSON.parse(referenceScoreJSON); // Creates our JSON object to use in our functions below. @@ -183,7 +195,7 @@ function ChordScaleBucketScore({ if (colors) { let mappedColors = colors; - if(Array.isArray(colors) && colors.length > 0) { + if (Array.isArray(colors) && colors.length > 0) { mappedColors = colors.map(colorMap); } else { mappedColors = colorMap(colors); @@ -196,9 +208,7 @@ function ChordScaleBucketScore({ } }, [referenceScoreJSON, chordScaleBucket, embed]); - return ( -
- ); + return
; } export default ChordScaleBucketScore; diff --git a/components/courseSelector.js b/components/courseSelector.js index 7374243..5e169ec 100644 --- a/components/courseSelector.js +++ b/components/courseSelector.js @@ -1,78 +1,123 @@ -import { useQuery } from "react-query"; -import { getEnrollments } from "../api"; -import Form from "react-bootstrap/Form"; -import { useRouter } from "next/router"; -import Spinner from "react-bootstrap/Spinner"; -import { Nav } from "react-bootstrap"; -import Link from "next/link"; -import { useSelector } from "react-redux"; - +import { useQuery } from 'react-query'; +import Form from 'react-bootstrap/Form'; +import { useRouter } from 'next/router'; +import Spinner from 'react-bootstrap/Spinner'; +import { Nav } from 'react-bootstrap'; +import Link from 'next/link'; +import { useSelector } from 'react-redux'; +import { getEnrollments } from '../api'; function CourseSelector() { - const { loaded: userLoaded, groups } = useSelector(state => state.currentUser) + const { loaded: userLoaded, groups } = useSelector( + (state) => state.currentUser, + ); const router = useRouter(); const changeCourse = (ev) => { - router.push(`/courses/${ev.target.value}`) - } + router.push(`/courses/${ev.target.value}`); + }; const { slug } = router.query; - const { isLoading, error, data: enrollments } = useQuery('enrollments', getEnrollments, {staleTime: 5 * 60 * 1000}) + const { + isLoading, + error, + data: enrollments, + } = useQuery('enrollments', getEnrollments, { staleTime: 5 * 60 * 1000 }); - const currentEnrollment = slug && - enrollments ? enrollments.filter((elem) => elem.course.slug === slug)[0] : null; + const currentEnrollment = + slug && enrollments + ? enrollments.filter((elem) => elem.course.slug === slug)[0] + : null; const selectedCourse = currentEnrollment?.course; // if the enrollments haven't loaded yet, show a spinner if (!enrollments && isLoading) { - return + return ( + + + + ); } // if they aren't logged in, or have no enrollments - if (enrollments && (enrollments.length === 0 || JSON.stringify(enrollments) === '{}')) { + if ( + enrollments && + (enrollments.length === 0 || JSON.stringify(enrollments) === '{}') + ) { return null; } // if the user has only one enrollment, don't show the dropdown - if (enrollments && enrollments.length === 1 && (!groups || !groups.some(gName => gName === "Teacher"))) { - return - {enrollments[0].course.name} - + if ( + enrollments && + enrollments.length === 1 && + (!groups || !groups.some((gName) => gName === 'Teacher')) + ) { + return ( + + + {enrollments[0].course.name} + + + ); } - //probably don't need the spinner here? - return - {!enrollments && isLoading ? - : (enrollments && ( -
- {enrollments && } - {enrollments && enrollments.map((enrollment) => ( - - ))} - {groups && groups.some(gName => gName === "Teacher") && - - - } -
- ))} -
+ // probably don't need the spinner here? + return ( + + {!enrollments && isLoading ? ( + + ) : ( + enrollments && ( +
+ + {enrollments && ( + + )} + {enrollments && + enrollments.map((enrollment) => ( + + ))} + {groups && groups.some((gName) => gName === 'Teacher') && ( + + + + + )} + +
+ ) + )} +
+ ); } -export default CourseSelector; \ No newline at end of file +export default CourseSelector; diff --git a/components/enrollments.js b/components/enrollments.js index 4034302..d93d42c 100644 --- a/components/enrollments.js +++ b/components/enrollments.js @@ -1,5 +1,5 @@ -import { useEffect } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import Card from 'react-bootstrap/Card'; import Button from 'react-bootstrap/Button'; import Link from 'next/link'; @@ -10,32 +10,53 @@ import { FaEdit, FaPlus, } from 'react-icons/fa'; -import { useQuery } from "react-query"; -import { format } from 'date-fns' -import { getEnrollments } from "../api"; +import { useQuery } from 'react-query'; +import { format } from 'date-fns'; +import { getEnrollments } from '../api'; // import { fetchEnrollments } from "../actions"; export default function Enrollments({ children }) { - const {loaded: userLoaded, groups } = useSelector(state => state.currentUser) - const { isLoading, error, data: enrollments } = useQuery('enrollments', getEnrollments, {staleTime: 5 * 60 * 1000}) - if (isLoading) return 'Loading...' - if (error) return `An error has occurred: ${ error.message}` + const { loaded: userLoaded, groups } = useSelector( + (state) => state.currentUser, + ); + const { + isLoading, + error, + data: enrollments, + } = useQuery('enrollments', getEnrollments, { staleTime: 5 * 60 * 1000 }); + if (isLoading) return 'Loading...'; + if (error) return `An error has occurred: ${error.message}`; return (
{enrollments && enrollments.map((enrollment) => ( - - + + {enrollment.course.name} {/* */} - {format(new Date(enrollment.course.start_date), 'MMM d')} -  + + {format(new Date(enrollment.course.start_date), 'MMM d')} + +  -  {/*
*/} {/* */} - {format(new Date(enrollment.course.end_date), 'MMM d')} + + {format(new Date(enrollment.course.end_date), 'MMM d')} +
{/* @@ -53,16 +74,17 @@ export default function Enrollments({ children }) {
))} - {groups && groups.some(gName => gName === "Teacher") && - - - - Add New Course - {/* + {groups && groups.some((gName) => gName === 'Teacher') && ( + + + + + Add New Course + {/* */} - - {/* + + {/* */} - - } +
+ + )}
); -} \ No newline at end of file +} diff --git a/components/exploratoryCompose.js b/components/exploratoryCompose.js index 1cb96ee..b522de1 100644 --- a/components/exploratoryCompose.js +++ b/components/exploratoryCompose.js @@ -2,15 +2,11 @@ import React, { useEffect, useState } from 'react'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import Embed from 'flat-embed'; -import { - trimScore, - pitchesToRests, - colorMeasures, -} from '../lib/flat' +import { trimScore, pitchesToRests, colorMeasures } from '../lib/flat'; function ExploratoryCompose({ - height=300, - width='100%', + height = 300, + width = '100%', onUpdate, referenceScoreJSON, trim, @@ -31,83 +27,80 @@ function ExploratoryCompose({ controlsPrint: false, displayFirstLinePartsNames: false, toolsetId: '64be80de738efff96cc27edd', - mode: 'edit' + mode: 'edit', }; useEffect(() => { const allParams = { height: `${height}`, - width: width, + width, embedParams, }; setEmbed(new Embed(editorRef.current, allParams)); }, [height]); - - function createJsonFromReference(reference, colors) { + function createJsonFromReference(reference, colorList) { let result = pitchesToRests(JSON.parse(reference)); result = trim ? trimScore(result, trim) : result; - if (colors && colors.length > result['score-partwise'].part[0].measure.length) { - let measures = result['score-partwise'].part[0].measure; - result['score-partwise'].part[0].measure = colorMeasures(measures, colors); + if ( + colorList && + colorList.length > result['score-partwise'].part[0].measure.length + ) { + const measures = result['score-partwise'].part[0].measure; + result['score-partwise'].part[0].measure = colorMeasures( + measures, + colorList, + ); // result['score-partwise'].part[0].measure } return result; } useEffect(() => { - if (!embed) return; - - embed - .ready() - .then(() => { - if (!referenceScoreJSON) return embed; - - const result = createJsonFromReference(referenceScoreJSON, colors); + if (!embed) return; - return ( - embed.loadJSON(result).then(() => { - embed.off('noteDetails'); - embed.on('noteDetails', (ev) => { - embed.getJSON().then((jd) => { - const jsonData = jd; - if ( - colors && - jsonData['score-partwise'].part[0].measure.some((m) => - m.note.some((n) => !n.$color || n.$color === '#000000') - ) - ) { - jsonData['score-partwise'].part[0].measure = - colorMeasures( - jsonData['score-partwise'].part[0].measure, - colors - ); - embed.getCursorPosition().then((position) => - embed.loadJSON(jsonData).then(() => { - embed.setCursorPosition(position); - }) - ); - } - if (onUpdate) { - onUpdate(JSON.stringify(jsonData)); - } - }); - }); - }) - ); - }) - }, [referenceScoreJSON, embed]); + embed.ready().then(() => { + if (!referenceScoreJSON) return embed; + + const result = createJsonFromReference(referenceScoreJSON, colors); + + return embed.loadJSON(result).then(() => { + embed.off('noteDetails'); + embed.on('noteDetails', (ev) => { + embed.getJSON().then((jd) => { + const jsonData = jd; + if ( + colors && + jsonData['score-partwise'].part[0].measure.some((m) => + m.note.some((n) => !n.$color || n.$color === '#000000'), + ) + ) { + jsonData['score-partwise'].part[0].measure = colorMeasures( + jsonData['score-partwise'].part[0].measure, + colors, + ); + embed.getCursorPosition().then((position) => + embed.loadJSON(jsonData).then(() => { + embed.setCursorPosition(position); + }), + ); + } + if (onUpdate) { + onUpdate(JSON.stringify(jsonData)); + } + }); + }); + }); + }); + }, [referenceScoreJSON, embed]); return ( - <> - - -
- - - + + +
+ + ); } - -export default React.memo(ExploratoryCompose) +export default React.memo(ExploratoryCompose); diff --git a/components/flatEditor.js b/components/flatEditor.js index 617f3c7..a0f457b 100644 --- a/components/flatEditor.js +++ b/components/flatEditor.js @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import Embed from 'flat-embed'; +import { Button } from 'react-bootstrap'; import { pitchesToRests, trimScore, @@ -11,9 +12,8 @@ import { keyFromScoreJSON, getChordScaleInKey, colorNotes, - colorMeasures + colorMeasures, } from '../lib/flat'; -import { Button } from 'react-bootstrap'; import { correctMeasure, correctScore } from '../lib/variations'; const validateScore = (proposedScore, permittedPitches) => { @@ -23,7 +23,7 @@ const validateScore = (proposedScore, permittedPitches) => { measure.note.forEach((note, k) => { if (note.pitch && !permittedPitches.includes(note.pitch.step)) { result.ok = false; - result.errors.push({ note, part: i, measure: j, note: k }); + result.errors.push({ part: i, measure: j, note: k }); } }); }); @@ -34,7 +34,7 @@ const validateScore = (proposedScore, permittedPitches) => { function FlatEditor({ edit = false, height, - width='100%', + width = '100%', score = { // scoreId: '61e09029dffcd50014571a80', // sharingKey: @@ -54,9 +54,8 @@ function FlatEditor({ slice, sliceIdx, debugMsg, - selectedMeasure + selectedMeasure, }) { - function onFlatEditorError(e) { if (debugMsg) { console.error('debugMsg', debugMsg); @@ -73,11 +72,11 @@ function FlatEditor({ // *FIX* Need to get rid of arrow, make it a normal function as we did with keyFromScoreJSON, and getChordScaleInKey below. const embedTransposed = ( bucket, - embed, + embedding, // templt, keySig, instrName, - octaveShift + octaveShift, ) => { const template = JSON.parse( JSON.stringify({ @@ -136,14 +135,14 @@ function FlatEditor({ }, ], }, - }) + }), ); // change the notes in the score from whatever they are in tonic and eb to what we're given const scorePart = template?.['score-partwise']?.['part-list']?.['score-part']?.[0]; - scorePart['part-name'] = instrName; //embed.instrumentName; - scorePart['part-abbreviation'] = instrName; //embed.instrumentAbbreviation; - scorePart['score-instrument']['instrument-name'] = instrName; //embed.instrumentName; + scorePart['part-name'] = instrName; + scorePart['part-abbreviation'] = instrName; + scorePart['score-instrument']['instrument-name'] = instrName; // start from bucket, create the notes, add them to measure template['score-partwise'].part[0].measure[0].note = bucket.map( @@ -160,27 +159,31 @@ function FlatEditor({ note.pitch.alter = alter; } return note; - } + }, ); // change the key signature in the score from whatever it is in tonic and eb to what we're given template?.['score-partwise']?.part?.[0]?.measure?.[0]?.attributes?.forEach( (element) => { if (element.key) { - //FIXME + // FIXME + // eslint-disable-next-line no-param-reassign element.key.fifths = keySig.keyAsJSON.fifths; } if (element.clef) { - //FIXME + // FIXME + // eslint-disable-next-line no-param-reassign element.clef = keySig.clef; } - } + }, ); if (octaveShift !== 0) { template?.[ 'score-partwise' ]?.part?.[0]?.measure?.[0]?.attributes?.forEach((element) => { + // FIXME + // eslint-disable-next-line no-param-reassign element.transpose = { chromatic: '0', 'octave-change': `${octaveShift}`, @@ -188,9 +191,10 @@ function FlatEditor({ }); } - const resultTransposed = embed.ready().then(() => { - return embed.loadJSON(template).catch(onFlatEditorError); - }).catch(onFlatEditorError); + const resultTransposed = embedding + .ready() + .then(() => embedding.loadJSON(template).catch(onFlatEditorError)) + .catch(onFlatEditorError); return resultTransposed; }; @@ -242,7 +246,7 @@ function FlatEditor({ const allParams = { height: `${computedHeight}`, - width: width, + width, embedParams, }; setEmbed(new Embed(editorRef.current, allParams)); @@ -269,7 +273,7 @@ function FlatEditor({ result = trimScore(result, trim); } if (slice) { - result = sliceScore(result, slice) + result = sliceScore(result, slice); } // FIXME: should slice and sliceIdx be mutually exclusive? if (sliceIdx !== undefined) { const [colorStart, colorStop] = nthSliceIdxs(result, sliceIdx); @@ -277,90 +281,154 @@ function FlatEditor({ if (colors) { result['score-partwise'].part[0].measure = colorMeasures( result['score-partwise'].part[0].measure, - colors.slice(colorStart, colorStop) + colors.slice(colorStart, colorStop), ); } - } - else if (colors) { + } else if (colors) { result['score-partwise'].part[0].measure = colorMeasures( result['score-partwise'].part[0].measure, - colors + colors, ); } return ( // if a user adds a note that is black or does not have a color assigned to it, then we apply the color from the chord scale pattern to match. score.scoreId === 'blank' && - embed.loadJSON(result).then(() => { - embed.off('cursorPosition'); - embed.on('cursorPosition', (ev) => { - // FIXME probably we need to debounce this event. when the paste has succeeded, don't notice that resulting change of cursor and try to do this again. - // selectedMeasure - if (json.current && selectedMeasure && selectedMeasure.current && JSON.stringify(selectedMeasure.current)!== '{}' && json.current !== '{}') { - const scoreData = JSON.parse(json.current); - const correctedSelection = correctMeasure(JSON.parse(JSON.stringify(selectedMeasure.current))); - if (Object.hasOwn(scoreData['score-partwise'].part[0].measure[ev.measureIdx], 'harmony')){ - correctedSelection.harmony = scoreData['score-partwise'].part[0].measure[ev.measureIdx].harmony - } - scoreData['score-partwise'].part[0].measure[ev.measureIdx] = correctedSelection - //FIXME - if (!Object.hasOwn(scoreData['score-partwise'].part[0].measure[ev.measureIdx], 'attributes')) { - scoreData['score-partwise'].part[0].measure[ev.measureIdx].attributes = [{}]; - - } - if (!Object.hasOwn(scoreData['score-partwise'].part[0].measure[ev.measureIdx].attributes[0], '$adagio-location')) { - scoreData['score-partwise'].part[0].measure[ev.measureIdx].attributes[0]['$adagio-location'] = { - "timePos": 0, - "dpq": 1 - } - } - if (!Object.hasOwn(scoreData['score-partwise'].part[0].measure[ev.measureIdx].attributes[0], '$adagio-time')) { - scoreData['score-partwise'].part[0].measure[ev.measureIdx].attributes[0]['$adagio-time'] = { - "beats": "4", - "beat-type": "4" - } - } - if (Object.hasOwn(scoreData['score-partwise'].part[0].measure[ev.measureIdx], 'barline')) { - delete scoreData['score-partwise'].part[0].measure[ev.measureIdx].barline; - } - selectedMeasure.current = {}; - const toLoad = JSON.stringify(scoreData); - embed.loadJSON(toLoad).catch(onFlatEditorError); - } - }); - embed.off('noteDetails'); - embed.on('noteDetails', (info) => { - embed.getJSON().then((jd) => { - const jsonData = jd; - //try to let the outer context know when this thing has data - + embed + .loadJSON(result) + .then(() => { + embed.off('cursorPosition'); + embed.on('cursorPosition', (ev) => { + // FIXME probably we need to debounce this event. when the paste has succeeded, don't notice that resulting change of cursor and try to do this again. + // selectedMeasure if ( - colors && - jsonData['score-partwise'].part[0].measure.some((m) => - m.note.some((n) => !n.$color || n.$color === '#000000') - ) + json.current && + selectedMeasure && + selectedMeasure.current && + JSON.stringify(selectedMeasure.current) !== '{}' && + json.current !== '{}' ) { - jsonData['score-partwise'].part[0].measure = - colorMeasures( - jsonData['score-partwise'].part[0].measure, - colors - ); - embed.getCursorPosition().then((position) => - embed.loadJSON(jsonData).then(() => { - if (edit) { - embed.setCursorPosition(position); - } - }).catch(onFlatEditorError) + const scoreData = JSON.parse(json.current); + const correctedSelection = correctMeasure( + JSON.parse(JSON.stringify(selectedMeasure.current)), ); - } - const data = JSON.stringify(jsonData); - // validateScore(jsonData, []) - json.current = data; - if (onUpdate) { - onUpdate(data); + if ( + Object.hasOwn( + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ], + 'harmony', + ) + ) { + correctedSelection.harmony = + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].harmony; + } + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ] = correctedSelection; + // FIXME + if ( + !Object.hasOwn( + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ], + 'attributes', + ) + ) { + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].attributes = [{}]; + } + if ( + !Object.hasOwn( + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].attributes[0], + '$adagio-location', + ) + ) { + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].attributes[0]['$adagio-location'] = { + timePos: 0, + dpq: 1, + }; + } + if ( + !Object.hasOwn( + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].attributes[0], + '$adagio-time', + ) + ) { + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].attributes[0]['$adagio-time'] = { + beats: '4', + 'beat-type': '4', + }; + } + if ( + Object.hasOwn( + scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ], + 'barline', + ) + ) { + delete scoreData['score-partwise'].part[0].measure[ + ev.measureIdx + ].barline; + } + // FIXME + // eslint-disable-next-line no-param-reassign + selectedMeasure.current = {}; + const toLoad = JSON.stringify(scoreData); + embed.loadJSON(toLoad).catch(onFlatEditorError); } }); - }); - }).catch(onFlatEditorError) + embed.off('noteDetails'); + embed.on('noteDetails', (info) => { + embed.getJSON().then((jd) => { + const jsonData = jd; + // try to let the outer context know when this thing has data + + if ( + colors && + jsonData['score-partwise'].part[0].measure.some((m) => + m.note.some( + (n) => !n.$color || n.$color === '#000000', + ), + ) + ) { + jsonData['score-partwise'].part[0].measure = + colorMeasures( + jsonData['score-partwise'].part[0].measure, + colors, + ); + embed.getCursorPosition().then((position) => + embed + .loadJSON(jsonData) + .then(() => { + if (edit) { + embed.setCursorPosition(position); + } + }) + .catch(onFlatEditorError), + ); + } + const data = JSON.stringify(jsonData); + // validateScore(jsonData, []) + json.current = data; + if (onUpdate) { + onUpdate(data); + } + }); + }); + }) + .catch(onFlatEditorError) ); } return embed; @@ -374,31 +442,39 @@ function FlatEditor({ embed .getJSON() .then( - (jsonData) => giveJSON && giveJSON(JSON.stringify(jsonData)) + (jsonData) => + giveJSON && giveJSON(JSON.stringify(jsonData)), ); setRefId(score.scoreId); }) .catch((e) => { - if (e && e.message) { e.message = `flat error: ${e?.message}, not loaded from scoreId, score: ${JSON.stringify(score)}, orig: ${orig}, colors: ${colors}`; - if (debugMsg){ + if (debugMsg) { e.message = `${e?.message}, debugMsg: ${debugMsg}`; } - } else if(debugMsg) { + } else if (debugMsg) { console.error('debugMsg', debugMsg); - if (score){console.error('score', score);} - if (orig){console.error('orig', orig);} - if (colors){console.error('colors', colors);} + if (score) { + console.error('score', score); + } + if (orig) { + console.error('orig', orig); + } + if (colors) { + console.error('colors', colors); + } } console.error('score not loaded from scoreId'); console.error('score', score); - if (loadParams) { console.error('loadParams', loadParams)} + if (loadParams) { + console.error('loadParams', loadParams); + } console.error('orig', orig); console.error('colors', colors); // console.error(e); throw e; - }) + }), ) .catch(onFlatEditorError); } else if (scoreJSON && embed) { @@ -431,20 +507,27 @@ function FlatEditor({ }, [score, scoreJSON, chordScaleBucket, embed]); return ( - <> - - -
- { edit && onSubmit && } - - - + + +
+ {edit && onSubmit && ( + + )} + + ); } diff --git a/components/flatMelodyViewer.js b/components/flatMelodyViewer.js index 89f3f26..8e48f75 100644 --- a/components/flatMelodyViewer.js +++ b/components/flatMelodyViewer.js @@ -3,15 +3,14 @@ import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import Embed from 'flat-embed'; - function FlatMelodyViewer({ - height=300, - width='100%', + height = 300, + width = '100%', score, onLoad, - debugMsg + debugMsg, }) { - //const [embed, setEmbed] = useState(); + // const [embed, setEmbed] = useState(); const editorRef = React.createRef(); const embedParams = { @@ -29,52 +28,51 @@ function FlatMelodyViewer({ }; const allParams = { - height: `${height}`, - width: width, - embedParams, + height: `${height}`, + width, + embedParams, }; - useEffect(() => { - if (!editorRef.current) return; + if (!editorRef.current) return; const loadParams = { score: score.scoreId, }; if (score.sharingKey) { loadParams.sharingKey = score.sharingKey; } - const embed = new Embed(editorRef.current, allParams) + const embed = new Embed(editorRef.current, allParams); - embed.ready() + embed + .ready() .then(() => embed.loadFlatScore(loadParams)) .then(() => embed.getJSON()) .then((jsonData) => onLoad && onLoad(JSON.stringify(jsonData))) .catch((e) => { if (e && e.message) { e.message = `flat error: ${e?.message}, not loaded from scoreId, score: ${JSON.stringify(score)}`; - if (debugMsg){ + if (debugMsg) { e.message = `${e?.message}, debugMsg: ${debugMsg}`; } - } else if(debugMsg) { + } else if (debugMsg) { console.error('debugMsg', debugMsg); - if (score){console.error('score', score);} + if (score) { + console.error('score', score); + } } console.error('score not loaded from scoreId'); console.error('score', score); throw e; - }) - }, [editorRef.current]); + }); + }, [editorRef.current]); return ( - <> - - -
- - - + + +
+ + ); } - -export default React.memo(FlatMelodyViewer) +export default React.memo(FlatMelodyViewer); diff --git a/components/forms/addEditCourse.js b/components/forms/addEditCourse.js index 5a92a10..86d1637 100644 --- a/components/forms/addEditCourse.js +++ b/components/forms/addEditCourse.js @@ -23,12 +23,14 @@ export default function AddEditCourse() { isLoading, error, data: enrollments, - } = useQuery('enrollments', getEnrollments, {staleTime: 5 * 60 * 1000}); + } = useQuery('enrollments', getEnrollments, { staleTime: 5 * 60 * 1000 }); // const router = useRouter(); // const { slug } = router.query; - - const currentEnrollment = slug && - enrollments ? enrollments.filter((elem) => elem.course.slug === slug)[0] : null; + + const currentEnrollment = + slug && enrollments + ? enrollments.filter((elem) => elem.course.slug === slug)[0] + : null; // const selectedEnrollment = enrollments.items.filter((enrollment) => enrollment.course.slug === slug)[0]; const selectedCourse = currentEnrollment?.course; @@ -52,10 +54,10 @@ export default function AddEditCourse() { const [name, setName] = useState(''); const [startDate, setStartDate] = useState( - today.toISOString().substring(0, 10) + today.toISOString().substring(0, 10), ); const [endDate, setEndDate] = useState( - sampleEnd.toISOString().substring(0, 10) + sampleEnd.toISOString().substring(0, 10), ); useEffect(() => { @@ -64,7 +66,7 @@ export default function AddEditCourse() { setStartDate(selectedCourse.start_date); setEndDate(selectedCourse.end_date); } - }, [slug, selectedCourse]) + }, [slug, selectedCourse]); const queryClient = useQueryClient(); const courseMutation = useMutation(mutateCourse(slug), { @@ -78,7 +80,7 @@ export default function AddEditCourse() { if (old) { return [ ...old.map((enrollment) => - enrollment.id === updatedCourse.id ? updatedCourse : enrollment + enrollment.id === updatedCourse.id ? updatedCourse : enrollment, ), ]; } @@ -137,7 +139,7 @@ export default function AddEditCourse() { endDate, token: userInfo.token, userId: userInfo.id, - }) + }), ).then((newSlug) => { router.push(`/courses/${newSlug}/edit`); }); diff --git a/components/forms/addEditStudent.js b/components/forms/addEditStudent.js index b0cced6..17a1c14 100644 --- a/components/forms/addEditStudent.js +++ b/components/forms/addEditStudent.js @@ -9,7 +9,6 @@ function AddEditStudent() { const [grade, setGrade] = useState(); const addStudent = (ev) => { - // TODO: actually dispatch action to add a student here // don't refresh the page diff --git a/components/forms/studentInstrument.js b/components/forms/studentInstrument.js index 2b4a5bb..6c04975 100644 --- a/components/forms/studentInstrument.js +++ b/components/forms/studentInstrument.js @@ -10,22 +10,24 @@ import * as types from '../../types'; function StudentInstrument({ enrollment, token, options: instruments }) { const [instrument, setInstrument] = useState( - enrollment?.instrument?.id ?? '' + enrollment?.instrument?.id ?? '', ); const dispatch = useDispatch(); const updateInstrument = (ev) => { - const instrumentObj = instruments.find((instr) => instr.id == ev.target.value); + const instrumentObj = instruments.find( + (instr) => instr.id === ev.target.value, + ); if (instrumentObj) { - dispatch( - updateEnrollmentInstrument({ - djangoToken: token, - enrollmentId: enrollment.id, - instrument: instrumentObj, - }) - ); - setInstrument(ev.target.value); + dispatch( + updateEnrollmentInstrument({ + djangoToken: token, + enrollmentId: enrollment.id, + instrument: instrumentObj, + }), + ); + setInstrument(ev.target.value); } }; diff --git a/components/forms/uploadStudents.js b/components/forms/uploadStudents.js index 548f80b..fd2c2ef 100644 --- a/components/forms/uploadStudents.js +++ b/components/forms/uploadStudents.js @@ -17,12 +17,12 @@ function UploadStudents() { const userInfo = useSelector((state) => state.currentUser); const { shouldInstrument = false } = useSelector( - (state) => state.enrollments + (state) => state.enrollments, ); if (shouldInstrument && router.asPath.endsWith('/edit')) { router.push(router.asPath.replace('/edit', '/instruments')); - dispatch(didInstrument()) + dispatch(didInstrument()); } const uploadStudents = async (ev) => { @@ -44,7 +44,7 @@ function UploadStudents() { body: formData, djangoToken: userInfo.token, courseSlug: slug, - }) + }), ); setLoading(false); }; @@ -65,7 +65,7 @@ function UploadStudents() { this example roster csv file {' '} - in case it's easiest to just edit that. + in case it's easiest to just edit that. {/* Plese use{' '} @@ -88,8 +88,12 @@ function UploadStudents() { /> -
diff --git a/components/instrumentSelector.js b/components/instrumentSelector.js index f7f0b42..91c3e58 100644 --- a/components/instrumentSelector.js +++ b/components/instrumentSelector.js @@ -1,12 +1,13 @@ -import { fetchInstruments } from "../actions"; -import Form from "react-bootstrap/Form"; +import Form from 'react-bootstrap/Form'; import { useDispatch, useSelector } from 'react-redux'; -import Spinner from "react-bootstrap/Spinner"; +import Spinner from 'react-bootstrap/Spinner'; +import { fetchInstruments } from '../actions'; - -export default function InstrumentSelector({defaultInstrument, onChange}) { +export default function InstrumentSelector({ defaultInstrument, onChange }) { + // FIXME + // eslint-disable-next-line prefer-const let { items: instruments, loaded: instrumentsLoaded } = useSelector( - (state) => state.instruments + (state) => state.instruments, ); if (!instrumentsLoaded) { @@ -15,24 +16,21 @@ export default function InstrumentSelector({defaultInstrument, onChange}) { } return instrumentsLoaded ? ( - onChange(instruments[e.target.value])} - defaultValue={Object.values(instruments).find(i => i.name === defaultInstrument).id} + defaultValue={ + Object.values(instruments).find((i) => i.name === defaultInstrument).id + } > - {instruments && ( + {instruments && Object.values(instruments).map((instrument) => ( - - )) - )} + + ))} ) : ( - - ) + + ); } diff --git a/components/layout.js b/components/layout.js index 720ddbc..edc20d2 100644 --- a/components/layout.js +++ b/components/layout.js @@ -1,14 +1,15 @@ 'use client'; + import Container from 'react-bootstrap/Container'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { useSession } from 'next-auth/react'; import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { Spinner } from 'react-bootstrap'; import Navigation from './nav'; import styles from './layout.module.css'; import { getUserProfile, gotUser } from '../actions'; -import { Spinner } from 'react-bootstrap'; const PUBLIC_PATHS = ['/', '/about', '/auth/signin', '/api/auth/signout']; @@ -18,34 +19,51 @@ export default function Layout({ children }) { const { status, data } = useSession({ required: !PUBLIC_PATHS.includes(router.pathname), }); - const dispatch = useDispatch() + const dispatch = useDispatch(); useEffect(() => { - if (status === "authenticated") { - dispatch(gotUser({user:data.user, token: data.djangoToken})) - dispatch(getUserProfile({token: data.djangoToken})) + if (status === 'authenticated') { + dispatch(gotUser({ user: data.user, token: data.djangoToken })); + dispatch(getUserProfile({ token: data.djangoToken })); } - },[status, dispatch]); + }, [status, dispatch]); - const {loaded: userLoaded, token } = useSelector(state => state.currentUser) + const { loaded: userLoaded, token } = useSelector( + (state) => state.currentUser, + ); return ( <> MusicCPR - Create, Perform, Respond, and Connect - + - - + + - - + + @@ -55,16 +73,16 @@ export default function Layout({ children }) {
{children}
) : ( - + )} ); diff --git a/components/loginout.js b/components/loginout.js index 4997b02..3fc2ac5 100644 --- a/components/loginout.js +++ b/components/loginout.js @@ -1,7 +1,7 @@ import { useSession } from 'next-auth/react'; import Link from 'next/link'; import Nav from 'react-bootstrap/Nav'; -import { useSelector } from "react-redux"; +import { useSelector } from 'react-redux'; function LoginOut() { const { data: session } = useSession(); @@ -9,10 +9,9 @@ function LoginOut() { // const loginStatus = useSelector((state) => state.loginStatus); return session ? ( - Logout - { - currentUserInfo.loaded ? ` ${currentUserInfo.username}` : "" - } + + Logout + {currentUserInfo.loaded ? ` ${currentUserInfo.username}` : ''} ) : ( diff --git a/components/mergingScore.js b/components/mergingScore.js index 1513ed3..43e8fca 100644 --- a/components/mergingScore.js +++ b/components/mergingScore.js @@ -49,7 +49,7 @@ function MergingScore({ } }, [scores, height, instrumentName, giveJSON]); - return
+ return
; } export default MergingScore; diff --git a/components/nav.js b/components/nav.js index 9014bd2..20470fb 100644 --- a/components/nav.js +++ b/components/nav.js @@ -1,4 +1,5 @@ 'use client'; + import Nav from 'react-bootstrap/Nav'; import Navbar from 'react-bootstrap/Navbar'; import Container from 'react-bootstrap/Container'; @@ -8,15 +9,19 @@ import { useQuery } from 'react-query'; import LoginOut from './loginout'; import { getEnrollments } from '../api'; import CourseSelector from './courseSelector'; -import {NavActivityPicker} from './student/navActivityPicker'; +import { NavActivityPicker } from './student/navActivityPicker'; import { PiecePicker } from './student/piecePicker'; function Navigation() { const router = useRouter(); const { slug, piece } = router.query; - const { isLoading, error, data: enrollments } = useQuery('enrollments', getEnrollments, {staleTime: 5 * 60 * 1000}) + const { + isLoading, + error, + data: enrollments, + } = useQuery('enrollments', getEnrollments, { staleTime: 5 * 60 * 1000 }); // const currentEnrollment = slug && enrollments && enrollments.filter((elem) => elem.course.slug === slug)[0] - + return ( @@ -26,13 +31,15 @@ function Navigation() { diff --git a/components/pasted.json b/components/pasted.json deleted file mode 100644 index 6f69402..0000000 --- a/components/pasted.json +++ /dev/null @@ -1,1852 +0,0 @@ -{ - "score-partwise": { - "$version": "3.1", - "identification": { - "creator": { - "content": "Brittany J. Green", - "$type": "composer" - }, - "encoding": { - "software": "Flat", - "encoding-date": "2024-02-25" - }, - "source": "https://flat.io/score/62ec0df25205540013decb45-freedom-2040-the-tomorrow-we-ll-build-melody-concert-pitch-bc?sharingKey=66cf421ace7733fa9d91bd2b10899642c27058fe4cdbdda5d7297db2176bc4ed7b086d12c0de3a47c7e8beafc0b92a4a60a41c72c652205598a3471507ea5a12" - }, - "defaults": { - "scaling": { - "millimeters": "7.2319", - "tenths": "40" - }, - "page-layout": { - "page-height": "1545", - "page-width": "1194", - "page-margins": { - "$type": "both", - "left-margin": "70", - "right-margin": "70", - "top-margin": "70", - "bottom-margin": "70" - } - }, - "system-layout": { - "system-margins": { - "left-margin": "0", - "right-margin": "0" - }, - "system-distance": "121", - "top-system-distance": "70" - }, - "appearance": { - "line-width": [ - { - "content": "0.7487", - "$type": "stem" - }, - { - "content": "5", - "$type": "beam" - }, - { - "content": "0.7487", - "$type": "staff" - }, - { - "content": "0.7487", - "$type": "light barline" - }, - { - "content": "5", - "$type": "heavy barline" - }, - { - "content": "0.7487", - "$type": "leger" - }, - { - "content": "0.7487", - "$type": "ending" - }, - { - "content": "0.7487", - "$type": "wedge" - }, - { - "content": "0.7487", - "$type": "enclosure" - }, - { - "content": "0.7487", - "$type": "tuplet bracket" - } - ], - "note-size": [ - { - "content": "60", - "$type": "grace" - }, - { - "content": "60", - "$type": "cue" - } - ], - "distance": [ - { - "content": "120", - "$type": "hyphen" - }, - { - "content": "7.5", - "$type": "beam" - } - ] - }, - "music-font": { - "$font-family": "Bravura" - }, - "staff-layout": { - "staff-distance": "70.24433413072636" - }, - "$adagio-systemBreakPolicy": { - "maxNbMeasuresPerLine": 4, - "forbiddenCounts": { - - } - } - }, - "credit": [ - { - "credit-type": "title", - "credit-words": "Freedom 2040: The Tomorrow We'll Build Melody - Concert Pitch BC" - } - ], - "part-list": { - "score-part": [ - { - "$id": "P1", - "part-name": { - "content": "Bass Clef", - "$print-object": "no" - }, - "part-abbreviation": { - "content": "Tbn.", - "$print-object": "no" - }, - "score-instrument": { - "$id": "P1-I1", - "instrument-name": "SmartMusicSoftSynth", - "instrument-sound": "brass.trombone", - "virtual-instrument": { - - } - }, - "midi-device": "SmartMusicSoftSynth", - "midi-instrument": { - "$id": "P1-I1", - "midi-channel": "12", - "midi-bank": "15489", - "midi-program": 58, - "pan": "11" - }, - "uuid": "b5df740f-a552-a687-e79c-87ee073ec48b", - "voiceMapping": { - "0": [ - 0 - ] - }, - "staffMapping": [ - { - "voices": [ - 0 - ], - "mainVoiceIdx": 0, - "staffUuid": "6c402e97-f252-438a-e745-40f27e480ad6" - } - ], - "voiceIdxToUuidMapping": { - "0": "1da43ccc-c300-6740-7cf9-6b445b100dc9" - }, - "voiceUuidToIdxMapping": { - "1da43ccc-c300-6740-7cf9-6b445b100dc9": 0 - } - } - ] - }, - "part": [ - { - "$id": "P1", - "measure": [ - { - "$number": "1", - "$width": "179", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "3", - "step": "E", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "32nd", - "$color": "#E75B5C", - "isRest": false, - "oPos": 6, - "uPos": 7, - "split": true, - "beam": [ - { - "$number": "1", - "content": "begin" - }, - { - "$number": "2", - "content": "begin" - }, - { - "$number": "3", - "content": "forward hook" - } - ] - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 1 - }, - "type": "16th", - "$color": "#E75B5C", - "isRest": false, - "oPos": 0, - "uPos": 1, - "beam": [ - { - "$number": "1", - "content": "continue" - }, - { - "$number": "2", - "content": "continue" - } - ] - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "B", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 3 - }, - "type": "16th", - "$color": "#E75B5C", - "isRest": false, - "oPos": 2, - "uPos": 3, - "beam": [ - { - "$number": "1", - "content": "continue" - }, - { - "$number": "2", - "content": "continue" - } - ] - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 5 - }, - "type": "16th", - "$color": "#E75B5C", - "isRest": false, - "oPos": 4, - "uPos": 5, - "beam": [ - { - "$number": "1", - "content": "continue" - }, - { - "$number": "2", - "content": "continue" - } - ] - }, - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "3", - "step": "E", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 7 - }, - "type": "32nd", - "$color": "#E75B5C", - "isRest": false, - "oPos": 6, - "uPos": 7, - "beam": [ - { - "$number": "1", - "content": "end" - }, - { - "$number": "2", - "content": "end" - }, - { - "$number": "3", - "content": "backward hook" - } - ] - } - ], - "attributes": [ - { - "divisions": "8", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - }, - "$adagio-time": { - "beats": "1", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "sound": [ - { - "$adagio-swing": { - "swing": false - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - } - }, - { - "$tempo": "120", - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - } - } - ], - "direction": [ - { - "$placement": "above", - "staff": "1", - "$adagio-location": { - "timePos": 0 - }, - "direction-type": { - "metronome": { - "per-minute": "120", - "beat-unit": "quarter" - } - }, - "noteBefore": -1, - "$adagio-isFirst": true - } - ], - "$adagio-beatsList": [ - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "2", - "$width": "44", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "3", - "$width": "65", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "A", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#265C5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "4", - "$width": "45", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "5", - "$width": "63", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "6", - "$width": "55", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "C" - }, - "kind": { - "content": "minor", - "$halign": "center", - "$text": "m" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#265C5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "7", - "$width": "63", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "B", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "bass": { - "bass-step": "D" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#4390E2", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "8", - "$width": "44", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "9", - "$width": "62", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "10", - "$width": "44", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "A", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#265C5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "11", - "$width": "67", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "B", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#4390E2", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "12", - "$width": "44", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "13", - "$width": "63", - "harmony": [ - { - "root": { - "root-step": "C" - }, - "kind": "minor", - "$adagio-kind": "minor", - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "$type": "explicit", - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#265C5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "14", - "$width": "51", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "A", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#265C5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#265C5C", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "15", - "$width": "53", - "harmony": [ - { - "root": { - "root-step": "B", - "root-alter": "-1" - }, - "kind": "major", - "$adagio-kind": "major", - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "$type": "explicit", - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#4390E2", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#4390E2", - "type": "quarter" - } - ], - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - }, - { - "$number": "16", - "$width": "44", - "harmony": [ - { - "$default-y": "40", - "root": { - "root-step": "E", - "root-alter": "-1" - }, - "kind": { - "content": "major", - "$halign": "center", - "$text": "" - }, - "$adagio-location": { - "timePos": 0, - "dpq": 8 - }, - "staff": "1", - "$placement": "above", - "noteBefore": -1 - } - ], - "note": [ - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 0 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 8 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 16 - }, - "$color": "#E75B5C", - "type": "quarter" - }, - { - "rest": { - - }, - "duration": "8", - "$adagio-location": { - "timePos": 24 - }, - "$color": "#E75B5C", - "type": "quarter" - } - ], - "barline": { - "$location": "right", - "bar-style": "light-heavy", - "$adagio-location": { - "timePos": 32, - "dpq": 8 - }, - "noteBefore": 3 - }, - "attributes": [ - { - "$adagio-time": { - "beats": "4", - "beat-type": "4" - }, - "noteBefore": -1, - "$adagio-location": { - "timePos": 0, - "dpq": 1 - } - } - ], - "$adagio-beatsList": [ - 1, - 1, - 1, - 1 - ], - "$adagio-restsInsideBeams": false - } - ], - "uuid": "b5df740f-a552-a687-e79c-87ee073ec48b" - } - ], - "measure-list": { - "score-measure": [ - { - "uuid": "4aff7f54-e591-b150-3722-6d307d492d5f" - }, - { - "uuid": "e46ebd5c-0021-2132-2df7-fd93d834cbeb" - }, - { - "uuid": "c70cac65-0d38-1424-554f-553e2337fef6" - }, - { - "uuid": "ab720bba-4190-6993-0579-8bdfe1bbfb4a" - }, - { - "uuid": "5bbca97e-fb80-c283-cf76-f2dee933b5bb" - }, - { - "uuid": "aaafab19-e95f-3b55-41b9-ce0458286fe1" - }, - { - "uuid": "aca1df6a-b73a-3487-eb50-efe1facd854d" - }, - { - "uuid": "142dfc0b-6a65-9309-7d13-6e0652a7128b" - }, - { - "uuid": "dad683ea-a2d6-5255-b65d-ed9cb24a274d" - }, - { - "uuid": "b1f6e36b-ec30-d5df-9982-b28b8e3e204b" - }, - { - "uuid": "7b987ed8-1e2c-7dd7-3e72-f4b7b41c8b28" - }, - { - "uuid": "5ed15da9-79ad-4126-a599-a9053fa1b3c7" - }, - { - "uuid": "9401461c-1148-e775-7dfe-5bf112988efc" - }, - { - "uuid": "830a61d8-6769-1fed-1b2d-93fe46d16a75" - }, - { - "uuid": "15286491-e4af-c76e-7ecd-b11ec26a10b0" - }, - { - "uuid": "1782cf56-edeb-f270-0544-43fe7ec63f2c" - } - ] - }, - "$adagio-formatVersion": 55, - "work": { - "work-title": "Freedom 2040: The Tomorrow We'll Build Melody - Concert Pitch BC" - } - } -} diff --git a/components/recorder.js b/components/recorder.js index 100c866..978e279 100644 --- a/components/recorder.js +++ b/components/recorder.js @@ -4,9 +4,19 @@ import MicRecorder from 'mic-recorder-to-mp3'; import { useEffect, useRef, useState } from 'react'; import Button from 'react-bootstrap/Button'; import { - FaMicrophone, FaStop, FaCloudUploadAlt, - FaSpinner, FaTimesCircle, FaCheck, FaPlay, FaPause, - FaVolumeOff, FaVolumeMute, FaVolumeDown, FaVolumeUp, FaRegTrashAlt + FaMicrophone, + FaStop, + FaCloudUploadAlt, + FaSpinner, + FaTimesCircle, + FaCheck, + FaPlay, + FaPause, + FaVolumeOff, + FaVolumeMute, + FaVolumeDown, + FaVolumeUp, + FaRegTrashAlt, } from 'react-icons/fa'; import { useDispatch, useSelector } from 'react-redux'; import ListGroup from 'react-bootstrap/ListGroup'; @@ -14,9 +24,9 @@ import ListGroupItem from 'react-bootstrap/ListGroupItem'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import { useRouter } from 'next/router'; +import WaveSurfer from 'wavesurfer.js'; import { UploadStatusEnum } from '../types'; import StatusIndicator from './statusIndicator'; -import WaveSurfer from 'wavesurfer.js'; import styles from '../styles/recorder.module.css'; function AudioViewer({ src }) { @@ -25,10 +35,41 @@ function AudioViewer({ src }) { const volume = useRef(null); const play = ; const pause = ; - const vMute = ; - const vOff = ; - const vDown = ; - const vUp = ; + const vMute = ( + + ); + const vOff = ( + + ); + const vDown = ( + + ); + const vUp = ( + + ); const [playing, setPlay] = useState(play); const [volumeIndex, changeVolume] = useState(vUp); @@ -44,7 +85,7 @@ function AudioViewer({ src }) { cursorWidth: 3, height: 200, barGap: 3, - dragToSeek: true + dragToSeek: true, // plugins:[ // WaveSurferRegions.create({maxLength: 60}), // WaveSurferTimeLinePlugin.create({container: containerT.current}) @@ -62,34 +103,30 @@ function AudioViewer({ src }) { function handleVolumeChange() { waveSurf.current.setVolume(volume.current.value); - let volumeNum = volume.current.value * 100; - volume.current.style.setProperty('--volumePercent', volumeNum + '%'); - if (volume.current.value == 0) { + const volumeNum = volume.current.value * 100; + volume.current.style.setProperty('--volumePercent', `${volumeNum}%`); + if (volume.current.value === 0) { changeVolume(vMute); - } - else if (volume.current.value < .25) { + } else if (volume.current.value < 0.25) { changeVolume(vOff); - } - else if (volume.current.value < .5) { + } else if (volume.current.value < 0.5) { changeVolume(vDown); - } - else if (volume.current.value < .75) { + } else if (volume.current.value < 0.75) { changeVolume(vUp); } } function toggleVolume() { if (volume.current) { - if (volume.current.value != 0) { + if (volume.current.value !== 0) { volume.current.value = 0; waveSurf.current.setVolume(volume.current.value); - volume.current.style.setProperty('--volumePercent', 0 + '%'); + volume.current.style.setProperty('--volumePercent', `${0}%`); changeVolume(vMute); - } - else { + } else { volume.current.value = 1; waveSurf.current.setVolume(volume.current.value); - volume.current.style.setProperty('--volumePercent', 100 + '%'); + volume.current.style.setProperty('--volumePercent', `${100}%`); changeVolume(vUp); } } @@ -99,12 +136,11 @@ function AudioViewer({ src }) { if (waveSurf.current.isPlaying()) { setPlay(play); waveSurf.current.pause(); - } - else { + } else { setPlay(pause); waveSurf.current.play(); } - }; + } if (waveSurf.current) { waveSurf.current.on('finish', () => { setPlay(play); @@ -112,27 +148,53 @@ function AudioViewer({ src }) { } return ( -
-
-
- - + }} + > + + {volumeIndex}
@@ -205,14 +267,14 @@ export default function Recorder({ submit, accompaniment }) { 'file', new File([blobInfo[i].data], 'student-recoding.mp3', { mimeType: 'audio/mpeg', - }) + }), ); // dispatch(submit({ audio: formData })); submit({ audio: formData, submissionId }); }; function deleteTake(index) { - let newInfo = blobInfo.slice(); + const newInfo = blobInfo.slice(); newInfo.splice(index, 1); setBlobInfo(newInfo); } @@ -225,7 +287,9 @@ export default function Recorder({ submit, accompaniment }) { navigator.mediaDevices.getUserMedia ) { navigator.mediaDevices - .getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false } }) + .getUserMedia({ + audio: { echoCancellation: false, noiseSuppression: false }, + }) .then(() => { setIsBlocked(false); }) @@ -307,8 +371,7 @@ export default function Recorder({ submit, accompaniment }) { > -
diff --git a/components/source.json b/components/source.json deleted file mode 100644 index 33f1b43..0000000 --- a/components/source.json +++ /dev/null @@ -1,1156 +0,0 @@ -{ - "current": { - "score-partwise": { - "part-list": { - "score-part": [ - { - "part-name": { - "content": "Bass Clef", - "$print-object": "no" - }, - "voiceMapping": { - "0": [ - 0 - ] - }, - "staffMapping": [ - { - "voices": [ - 0 - ], - "mainVoiceIdx": 0, - "staffUuid": "6c402e97-f252-438a-e745-40f27e480ad6" - } - ], - "voiceIdxToUuidMapping": { - "0": "1da43ccc-c300-6740-7cf9-6b445b100dc9" - }, - "voiceUuidToIdxMapping": { - "1da43ccc-c300-6740-7cf9-6b445b100dc9": 0 - }, - "part-abbreviation": { - "content": "Tbn.", - "$print-object": "no" - }, - "score-instrument": { - "$id": "P1-I1", - "instrument-name": "SmartMusicSoftSynth", - "instrument-sound": "brass.trombone", - "virtual-instrument": {} - }, - "$id": "P1", - "uuid": "P1" - } - ] - }, - "part": [ - { - "measure": [ - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 7, - "split": true - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 1 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 0, - "uPos": 1 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 3 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 2, - "uPos": 3 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 5 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 5 - }, - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 7 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 7 - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 8 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 0, - "uPos": 2 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 2, - "uPos": 4 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 6 - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 7, - "split": true - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 9 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 3 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 0, - "uPos": 3 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 5 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 2, - "uPos": 5 - }, - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 7 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 7 - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 7, - "split": true - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 1 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 0, - "uPos": 1 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 3 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 2, - "uPos": 3 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 5 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 5 - }, - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 7 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 7 - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 8 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 2 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 0, - "uPos": 2 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 4 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 2, - "uPos": 4 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 6 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 6 - } - ], - "$number": "1", - "barline": { - "bar-style": "light-barline", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - }, - { - "note": [ - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 7, - "split": true - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "A", - "alter": "-1" - }, - "$adagio-location": { - "timePos": 0 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 6, - "uPos": 9 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "2", - "step": "G" - }, - "$adagio-location": { - "timePos": 3 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 0, - "uPos": 3 - }, - { - "staff": "1", - "voice": "1", - "duration": "2", - "pitch": { - "octave": "3", - "step": "G" - }, - "$adagio-location": { - "timePos": 5 - }, - "type": "quarter", - "$color": "#265C5C", - "isRest": false, - "oPos": 2, - "uPos": 5 - }, - { - "staff": "1", - "voice": "1", - "duration": "1", - "pitch": { - "octave": "3", - "step": "D" - }, - "$adagio-location": { - "timePos": 7 - }, - "type": "eighth", - "$color": "#265C5C", - "isRest": false, - "oPos": 4, - "uPos": 7 - } - ], - "$number": "1", - "barline": { - "bar-style": "light-heavy", - "noteBefore": -1 - }, - "attributes": [ - { - "divisions": "2", - "time": { - "beats": "4", - "beat-type": "4" - }, - "clef": { - "sign": "F", - "line": "4" - }, - "key": { - "fifths": "-3" - }, - "staff-details": { - "staff-lines": "5" - } - } - ] - } - ], - "$id": "P1", - "uuid": "P1" - } - ] - } - } -} \ No newline at end of file diff --git a/components/statusIndicator.js b/components/statusIndicator.js index 2ae03ad..4e8eee6 100644 --- a/components/statusIndicator.js +++ b/components/statusIndicator.js @@ -3,7 +3,7 @@ import { FaCheck, FaSpinner, FaTimesCircle } from 'react-icons/fa'; import { useSelector } from 'react-redux'; import { UploadStatusEnum } from '../types'; -export default function StatusIndicator({statusId}) { +export default function StatusIndicator({ statusId }) { const { submissions } = useSelector((state) => state.submission); const status = submissions?.[statusId]; diff --git a/components/student/activityPicker.js b/components/student/activityPicker.js deleted file mode 100644 index 9780409..0000000 --- a/components/student/activityPicker.js +++ /dev/null @@ -1,116 +0,0 @@ -import Link from "next/link"; -import { useRouter } from "next/router"; -import { ListGroup } from "react-bootstrap"; -import { FaBook, FaDrum, FaGuitar, FaLink, FaPenFancy } from "react-icons/fa"; -import { getMySubmissionsForAssignment } from "../../api"; -import { useQuery } from "react-query"; - -function ActivityPicker (assignment) { - const router = useRouter(); - - const { slug, piece, actCategory = 'Create', partType } = router.query; - - const { - isLoading, - isIdle, - error, - data: submissions, - } = useQuery( - ['submissions', slug, assignment.id], - () => getMySubmissionsForAssignment({ slug, assignmentId: assignment.id }), - { - enabled: !!assignment && !!slug && !!assignment.id, - } - ); - - // const - const composer = assignment?.part?.piece?.composer?.name; - const composerCheat = composer?.split(' ').pop(); - const connectLink = `Connect ${composerCheat}`; - const hasCompose = ['Benjamin', 'Danyew', 'Green'].includes(composerCheat); -return - - - - Melody - - - - - - - Bassline - - - - - - - Create - - - - - - - Reflect - - - - {/* FIXME: why isn't this hasCompose doc'ed?! this should be solved better */} - {hasCompose && ( - - - - Connect - - - - )} - -} - -export default ActivityPicker; \ No newline at end of file diff --git a/components/student/assignment.js b/components/student/assignment.js index ac9d472..65f83e6 100644 --- a/components/student/assignment.js +++ b/components/student/assignment.js @@ -14,13 +14,12 @@ import Layout from '../layout'; import Instructions from './instructions'; import { getMySubmissionsForAssignment } from '../../api'; import RecentSubmission from './recentSubmission'; -import ActivityPicker from './activityPicker'; export default function StudentAssignment({ children, assignment }) { const router = useRouter(); const { slug, piece, actCategory = 'Create', partType } = router.query; - + const { isLoading, isIdle, @@ -31,7 +30,7 @@ export default function StudentAssignment({ children, assignment }) { () => getMySubmissionsForAssignment({ slug, assignmentId: assignment.id }), { enabled: !!assignment && !!slug && !!assignment.id, - } + }, ); // const @@ -50,11 +49,13 @@ export default function StudentAssignment({ children, assignment }) { {/* moved to navbar */}

- {(actCategory == 'Perform' || actCategory == 'Create') && + {(actCategory === 'Perform' || actCategory === 'Create') && `${actCategory} `} {assignment?.activity?.activity_type?.name} Activity

- + {assignment.submissions.length > 0 ? ( diff --git a/components/student/connect.js b/components/student/connect.js index d2000a7..0da7387 100644 --- a/components/student/connect.js +++ b/components/student/connect.js @@ -22,15 +22,14 @@ export default function ConnectActivity() { } }, [slug, userInfo.token]); const { items: activities, loaded: loadedActivities } = useSelector( - (state) => state.activities + (state) => state.activities, ); const currentAssignment = useSelector((state) => state.selectedAssignment); const assignment = loadedActivities && activities && - activities?.[piece].filter( - (assn) => - assn.activity_type_category.startsWith(actCategory) + activities?.[piece].filter((assn) => + assn.activity_type_category.startsWith(actCategory), )?.[0]; const assignmentId = assignment?.id; useEffect(() => { @@ -39,7 +38,7 @@ export default function ConnectActivity() { fetchSingleStudentAssignment({ slug, assignmentId, - }) + }), ); } }, [slug, loadedActivities, activities]); @@ -52,7 +51,7 @@ export default function ConnectActivity() { slug, assignmentId, response: reflection, - }) + }), ); }; @@ -67,7 +66,7 @@ export default function ConnectActivity() { frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen - > + /> )}
+