From 08e6c1bef34a387b14657e78382f186f66036ab1 Mon Sep 17 00:00:00 2001 From: Philippe Ozil <5071767+pozil@users.noreply.github.com> Date: Fri, 10 Apr 2020 00:41:07 +0200 Subject: [PATCH] Added question picker (#57) --- package-lock.json | 222 ++++++++++-------- package.json | 12 +- src/main/default/classes/QuizController.cls | 10 +- .../default/classes/QuizEditorController.cls | 28 +++ .../classes/QuizEditorController.cls-meta.xml | 5 + .../default/classes/QuizQuestionService.cls | 5 + .../classes/QuizQuestionService.cls-meta.xml | 5 + .../default/classes/QuizSessionService.cls | 29 +++ ...uiz_Session_Record_Page.flexipage-meta.xml | 42 ++++ ...ion__c-Quiz Session Layout.layout-meta.xml | 22 +- .../lwc/answerBarChart/answerBarChart.js | 8 +- src/main/default/lwc/errorUtils/errorUtils.js | 8 +- src/main/default/lwc/gameApp/gameApp.js | 16 +- .../default/lwc/leaderBoard/leaderBoard.js | 4 +- src/main/default/lwc/playerList/playerList.js | 12 +- .../lwc/questionPicker/questionPicker.html | 34 +++ .../lwc/questionPicker/questionPicker.js | 131 +++++++++++ .../questionPicker/questionPicker.js-meta.xml | 16 ++ .../Quiz_Session__c.object-meta.xml | 107 +++++++++ .../fields/Current_Question__c.field-meta.xml | 4 +- 20 files changed, 593 insertions(+), 127 deletions(-) create mode 100755 src/main/default/classes/QuizEditorController.cls create mode 100755 src/main/default/classes/QuizEditorController.cls-meta.xml create mode 100755 src/main/default/classes/QuizQuestionService.cls create mode 100755 src/main/default/classes/QuizQuestionService.cls-meta.xml create mode 100644 src/main/default/flexipages/Quiz_Session_Record_Page.flexipage-meta.xml create mode 100755 src/main/default/lwc/questionPicker/questionPicker.html create mode 100755 src/main/default/lwc/questionPicker/questionPicker.js create mode 100755 src/main/default/lwc/questionPicker/questionPicker.js-meta.xml diff --git a/package-lock.json b/package-lock.json index 5429c77..7e2a316 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "sfdx-quiz", - "version": "1.0.2", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -626,9 +626,9 @@ } }, "@babel/runtime": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", - "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -684,17 +684,17 @@ }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true } } }, "@hapi/address": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.0.0.tgz", - "integrity": "sha512-GDDpkCdSUfkQCznmWUHh9dDN85BWf/V8TFKQ2JLuHdGB4Yy3YTEGBzZxoBNxfNBEvreSR/o+ZxBBSNNEVzY+lQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.0.1.tgz", + "integrity": "sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw==", "dev": true, "requires": { "@hapi/hoek": "^9.0.0" @@ -707,18 +707,18 @@ "dev": true }, "@hapi/hoek": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.3.tgz", - "integrity": "sha512-jKtjLLDiH95b002sJVc5c74PE6KKYftuyVdVmsuYId5stTaWcRFqE+5ukZI4gDUKjGn8wv2C3zPn3/nyjEI7gg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz", + "integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw==", "dev": true }, "@hapi/joi": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.0.tgz", - "integrity": "sha512-ob67RcPlwRWxBzLCnWvcwx5qbwf88I3ykD7gcJLWOTRfLLgosK7r6aeChz4thA3XRvuBfI0KB1tPVl2EQFlPXw==", + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz", + "integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==", "dev": true, "requires": { - "@hapi/address": "^4.0.0", + "@hapi/address": "^4.0.1", "@hapi/formula": "^2.0.0", "@hapi/hoek": "^9.0.0", "@hapi/pinpoint": "^2.0.0", @@ -1393,9 +1393,9 @@ }, "dependencies": { "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true } } @@ -4340,14 +4340,14 @@ "dev": true }, "husky": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz", - "integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.5.tgz", + "integrity": "sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ==", "dev": true, "requires": { - "chalk": "^3.0.0", + "chalk": "^4.0.0", "ci-info": "^2.0.0", - "compare-versions": "^3.5.1", + "compare-versions": "^3.6.0", "cosmiconfig": "^6.0.0", "find-versions": "^3.2.0", "opencollective-postinstall": "^2.0.2", @@ -4368,9 +4368,9 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -4418,9 +4418,9 @@ } }, "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -6107,9 +6107,9 @@ "dev": true }, "lint-staged": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.8.tgz", - "integrity": "sha512-Oa9eS4DJqvQMVdywXfEor6F4vP+21fPHF8LUXgBbVWUSWBddjqsvO6Bv1LwMChmgQZZqwUvgJSHlu8HFHAPZmA==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.1.3.tgz", + "integrity": "sha512-o2OkLxgVns5RwSC5QF7waeAjJA5nz5gnUfqL311LkZcFipKV7TztrSlhNUK5nQX9H0E5NELAdduMQ+M/JPT7RQ==", "dev": true, "requires": { "chalk": "^3.0.0", @@ -6178,9 +6178,9 @@ "dev": true }, "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", + "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -6732,9 +6732,9 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mixin-deep": { @@ -6759,12 +6759,12 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "ms": { @@ -7227,9 +7227,9 @@ "dev": true }, "picomatch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, "pify": { @@ -9089,15 +9089,15 @@ "dev": true }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.4.tgz", + "integrity": "sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w==", "dev": true }, "prettier-plugin-apex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-apex/-/prettier-plugin-apex-1.2.0.tgz", - "integrity": "sha512-6cD08DsmIGTj/p1FHBGQ98JhL+ocbvfGahtsczDwfTXLQbJZ3UpFY8eAfB17gLuA7Z0HwUC/1u3NWddhjYsuJQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-apex/-/prettier-plugin-apex-1.3.0.tgz", + "integrity": "sha512-rgfUP5OQIqHKkh/XtGzvcJirO9WA5BgMb235tCQ9dA+8X5PTldk1oJJJSJd1/WfzRhCE6W4obKHbs99nJL+cCQ==", "dev": true, "requires": { "axios": "^0.19.0", @@ -9177,9 +9177,9 @@ "dev": true }, "jest-docblock": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.1.0.tgz", - "integrity": "sha512-370P/mh1wzoef6hUKiaMcsPtIapY25suP6JqM70V9RJvdKLrV4GaGbfUseUVk4FZJw4oTZ1qSCJNdrClKt5JQA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.3.0.tgz", + "integrity": "sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg==", "dev": true, "requires": { "detect-newline": "^3.0.0" @@ -9195,9 +9195,9 @@ } }, "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -9256,9 +9256,9 @@ } }, "yargs": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", - "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -9271,13 +9271,13 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.0" + "yargs-parser": "^18.1.1" } }, "yargs-parser": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.0.tgz", - "integrity": "sha512-o/Jr6JBOv6Yx3pL+5naWSoIA2jJ+ZkMYQG/ie9qFbukBe4uzmBatlXFOiu/tNKRWEtyf+n5w7jc/O16ufqOTdQ==", + "version": "18.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz", + "integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -9452,9 +9452,9 @@ } }, "regenerator-runtime": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz", - "integrity": "sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==", + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", "dev": true }, "regenerator-transform": { @@ -9990,9 +9990,9 @@ }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true } } @@ -10013,9 +10013,9 @@ } }, "semver": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", - "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.2.1.tgz", + "integrity": "sha512-aHhm1pD02jXXkyIpq25qBZjr3CQgg8KST8uX0OWXch3xE6jw+1bfbWnCjzMwojsTquroUmKFHNzU6x26mEiRxw==", "dev": true }, "semver-compare": { @@ -11048,33 +11048,71 @@ } }, "wait-on": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-4.0.1.tgz", - "integrity": "sha512-x83fmTH2X0KL7vXoGt9aV5x4SMCvO8A/NbwWpaYYh4NJ16d3KSgbHwBy9dVdHj0B30cEhOFRvDob4fnpUmZxvA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-4.0.2.tgz", + "integrity": "sha512-Qpmgm3Hw/sXm7xK68FBsYy5r+Uid94/QymwnEjn9GTpfiWTUVYm0bccivVwY/BXGYO2r+5Cd8S/DzrRZqHK/9w==", "dev": true, "requires": { - "@hapi/joi": "^17.1.0", + "@hapi/joi": "^17.1.1", "lodash": "^4.17.15", - "minimist": "^1.2.0", - "request": "^2.88.0", + "minimist": "^1.2.5", + "request": "^2.88.2", "request-promise-native": "^1.0.8", - "rxjs": "^6.5.4" + "rxjs": "^6.5.5" }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", "dev": true, "requires": { "tslib": "^1.9.0" } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } } } }, @@ -11231,9 +11269,9 @@ "dev": true }, "yaml": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.0.tgz", - "integrity": "sha512-6qI/tTx7OVtA4qNqD0OyutbM6Z9EKu4rxWm/2Y3FDEBQ4/2X2XAnyuRXMzAE2+1BPyqzksJZtrIwblOHg0IEzA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.3.tgz", + "integrity": "sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw==", "dev": true, "requires": { "@babel/runtime": "^7.8.7" diff --git a/package.json b/package.json index 8a411b1..c84c1d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sfdx-quiz", - "version": "1.0.2", + "version": "1.1.0", "private": true, "description": "Lightning Web Component Quiz App on a Salesforce Org", "engines": { @@ -21,11 +21,11 @@ "@salesforce/eslint-config-lwc": "^0.5.0", "@salesforce/sfdx-lwc-jest": "^0.7.1", "eslint": "^6.8.0", - "husky": "^4.2.3", - "lint-staged": "^10.0.8", - "prettier": "^1.19.1", - "prettier-plugin-apex": "^1.2.0", - "semver": "^7.1.3", + "husky": "^4.2.5", + "lint-staged": "^10.1.3", + "prettier": "^2.0.4", + "prettier-plugin-apex": "^1.3.0", + "semver": "^7.2.1", "replace-in-file": "^5.0.2" }, "husky": { diff --git a/src/main/default/classes/QuizController.cls b/src/main/default/classes/QuizController.cls index 5a8acf6..cb89dbe 100644 --- a/src/main/default/classes/QuizController.cls +++ b/src/main/default/classes/QuizController.cls @@ -44,7 +44,15 @@ public with sharing class QuizController { if (sessionId == null) { throw new AuraHandledException('Missing session Id.'); } - return sessionService.getCurrentQuestion(sessionId); + Quiz_Question__c question = sessionService.getCurrentQuestion( + sessionId + ); + if (question == null) { + throw new AuraHandledException( + 'Missing current question for session.' + ); + } + return question; } @AuraEnabled diff --git a/src/main/default/classes/QuizEditorController.cls b/src/main/default/classes/QuizEditorController.cls new file mode 100755 index 0000000..63028c2 --- /dev/null +++ b/src/main/default/classes/QuizEditorController.cls @@ -0,0 +1,28 @@ +public with sharing class QuizEditorController { + private static final QuizQuestionService questionService = new QuizQuestionService(); + private static final QuizSessionService sessionService = new QuizSessionService(); + + @AuraEnabled(cacheable=true) + public static List<Quiz_Question__c> getAllQuestions() { + return questionService.getQuestions(); + } + + @AuraEnabled + public static void setSessionQuestions(Id sessionId, List<Id> questionIds) { + if (sessionId == null) { + throw new AuraHandledException('Missing session Id.'); + } + if (questionIds == null) { + throw new AuraHandledException('Missing questions Ids.'); + } + sessionService.setSessionQuestions(sessionId, questionIds); + } + + @AuraEnabled(cacheable=true) + public static List<Quiz_Question__c> getSessionQuestions(Id sessionId) { + if (sessionId == null) { + throw new AuraHandledException('Missing session Id.'); + } + return sessionService.getSessionQuestions(sessionId); + } +} diff --git a/src/main/default/classes/QuizEditorController.cls-meta.xml b/src/main/default/classes/QuizEditorController.cls-meta.xml new file mode 100755 index 0000000..db9bf8c --- /dev/null +++ b/src/main/default/classes/QuizEditorController.cls-meta.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> + <apiVersion>48.0</apiVersion> + <status>Active</status> +</ApexClass> diff --git a/src/main/default/classes/QuizQuestionService.cls b/src/main/default/classes/QuizQuestionService.cls new file mode 100755 index 0000000..853d9e3 --- /dev/null +++ b/src/main/default/classes/QuizQuestionService.cls @@ -0,0 +1,5 @@ +public class QuizQuestionService extends QuizAbstractDataService { + public List<Quiz_Question__c> getQuestions() { + return [SELECT Id, Label__c FROM Quiz_Question__c]; + } +} diff --git a/src/main/default/classes/QuizQuestionService.cls-meta.xml b/src/main/default/classes/QuizQuestionService.cls-meta.xml new file mode 100755 index 0000000..db9bf8c --- /dev/null +++ b/src/main/default/classes/QuizQuestionService.cls-meta.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> + <apiVersion>48.0</apiVersion> + <status>Active</status> +</ApexClass> diff --git a/src/main/default/classes/QuizSessionService.cls b/src/main/default/classes/QuizSessionService.cls index 7be620b..0539d5f 100644 --- a/src/main/default/classes/QuizSessionService.cls +++ b/src/main/default/classes/QuizSessionService.cls @@ -54,4 +54,33 @@ public class QuizSessionService extends QuizAbstractDataService { } return questions; } + + public void setSessionQuestions(Id sessionId, List<Id> questionIds) { + // Get session + Quiz_Session__c session = [ + SELECT Current_Question__c + FROM Quiz_Session__c + WHERE Id = :sessionId + ]; + // Overwrite session questions + delete [ + SELECT Id + FROM Quiz_Session_Question__c + WHERE Session__c = :sessionId + ]; + List<Quiz_Session_Question__c> questions = new List<Quiz_Session_Question__c>(); + for (Integer i = 0; i < questionIds.size(); i++) { + questions.add( + new Quiz_Session_Question__c( + Question__c = questionIds[i], + Question_Index__c = i, + Session__c = sessionId + ) + ); + } + insert questions; + // Replace current question + session.Current_Question__c = questionIds[0]; + update session; + } } diff --git a/src/main/default/flexipages/Quiz_Session_Record_Page.flexipage-meta.xml b/src/main/default/flexipages/Quiz_Session_Record_Page.flexipage-meta.xml new file mode 100644 index 0000000..4898d8a --- /dev/null +++ b/src/main/default/flexipages/Quiz_Session_Record_Page.flexipage-meta.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata"> + <flexiPageRegions> + <componentInstances> + <componentInstanceProperties> + <name>collapsed</name> + <value>false</value> + </componentInstanceProperties> + <componentInstanceProperties> + <name>hideChatterActions</name> + <value>false</value> + </componentInstanceProperties> + <componentInstanceProperties> + <name>numVisibleActions</name> + <value>3</value> + </componentInstanceProperties> + <componentName>force:highlightsPanel</componentName> + </componentInstances> + <name>header</name> + <type>Region</type> + </flexiPageRegions> + <flexiPageRegions> + <componentInstances> + <componentName>questionPicker</componentName> + </componentInstances> + <name>leftcol</name> + <type>Region</type> + </flexiPageRegions> + <flexiPageRegions> + <componentInstances> + <componentName>force:detailPanel</componentName> + </componentInstances> + <name>rightcol</name> + <type>Region</type> + </flexiPageRegions> + <masterLabel>Quiz Session Record Page</masterLabel> + <sobjectType>Quiz_Session__c</sobjectType> + <template> + <name>flexipage:recordHomeTwoColEqualHeaderTemplateDesktop</name> + </template> + <type>RecordPage</type> +</FlexiPage> diff --git a/src/main/default/layouts/Quiz_Session__c-Quiz Session Layout.layout-meta.xml b/src/main/default/layouts/Quiz_Session__c-Quiz Session Layout.layout-meta.xml index 2d24b02..be3addb 100644 --- a/src/main/default/layouts/Quiz_Session__c-Quiz Session Layout.layout-meta.xml +++ b/src/main/default/layouts/Quiz_Session__c-Quiz Session Layout.layout-meta.xml @@ -14,7 +14,7 @@ </layoutColumns> <layoutColumns> <layoutItems> - <behavior>Required</behavior> + <behavior>Edit</behavior> <field>Current_Question__c</field> </layoutItems> </layoutColumns> @@ -57,6 +57,24 @@ <layoutColumns/> <style>CustomLinks</style> </layoutSections> + <platformActionList> + <actionListContext>Record</actionListContext> + <platformActionListItems> + <actionName>Delete</actionName> + <actionType>StandardButton</actionType> + <sortOrder>0</sortOrder> + </platformActionListItems> + <platformActionListItems> + <actionName>Edit</actionName> + <actionType>StandardButton</actionType> + <sortOrder>1</sortOrder> + </platformActionListItems> + <platformActionListItems> + <actionName>Clone</actionName> + <actionType>StandardButton</actionType> + <sortOrder>2</sortOrder> + </platformActionListItems> + </platformActionList> <relatedLists> <fields>NAME</fields> <fields>Quiz_Question__c.NAME</fields> @@ -72,7 +90,7 @@ <showRunAssignmentRulesCheckbox>false</showRunAssignmentRulesCheckbox> <showSubmitAndAttachButton>false</showSubmitAndAttachButton> <summaryLayout> - <masterLabel>00h1g000000MR8k</masterLabel> + <masterLabel>00h1j000000sXjK</masterLabel> <sizeX>4</sizeX> <sizeY>0</sizeY> <summaryLayoutStyle>Default</summaryLayoutStyle> diff --git a/src/main/default/lwc/answerBarChart/answerBarChart.js b/src/main/default/lwc/answerBarChart/answerBarChart.js index afbcc4d..885bd88 100644 --- a/src/main/default/lwc/answerBarChart/answerBarChart.js +++ b/src/main/default/lwc/answerBarChart/answerBarChart.js @@ -16,11 +16,11 @@ export default class AnswerBarChart extends LightningElement { connectedCallback() { getAnswerStats() - .then(data => { - this.answerStats = ANSWER_LABELS.map(label => data[label]); + .then((data) => { + this.answerStats = ANSWER_LABELS.map((label) => data[label]); this.error = undefined; }) - .catch(error => { + .catch((error) => { this.error = reduceErrors(error); this.answerStats = undefined; }); @@ -99,7 +99,7 @@ export default class AnswerBarChart extends LightningElement { }; this.chart = new window.Chart(ctx, config); }) - .catch(error => { + .catch((error) => { this.answerStats = undefined; this.error = error; }); diff --git a/src/main/default/lwc/errorUtils/errorUtils.js b/src/main/default/lwc/errorUtils/errorUtils.js index 9bd1b67..e07fdae 100644 --- a/src/main/default/lwc/errorUtils/errorUtils.js +++ b/src/main/default/lwc/errorUtils/errorUtils.js @@ -14,12 +14,12 @@ export function reduceErrors(errors) { return ( errors // Remove null/undefined items - .filter(error => !!error) + .filter((error) => !!error) // Extract an error message - .map(error => { + .map((error) => { // UI API read errors if (Array.isArray(error.body)) { - return error.body.map(e => e.message); + return error.body.map((e) => e.message); } // UI API DML, Apex and network errors else if (error.body && typeof error.body.message === 'string') { @@ -35,6 +35,6 @@ export function reduceErrors(errors) { // Flatten .reduce((prev, curr) => prev.concat(curr), []) // Remove empty strings - .filter(message => !!message) + .filter((message) => !!message) ); } diff --git a/src/main/default/lwc/gameApp/gameApp.js b/src/main/default/lwc/gameApp/gameApp.js index a35460a..e8ba06c 100644 --- a/src/main/default/lwc/gameApp/gameApp.js +++ b/src/main/default/lwc/gameApp/gameApp.js @@ -14,7 +14,7 @@ export default class GameApp extends LightningElement { @track isNextButtonDisabled = true; @track currentQuestion; - HOST_APP_VERSION = '1.0.2'; + HOST_APP_VERSION = '1.1.0'; @wire(getQuizSettings) wiredQuizSettings({ error, data }) { @@ -27,16 +27,16 @@ export default class GameApp extends LightningElement { } connectedCallback() { - checkSettings().catch(error => { + checkSettings().catch((error) => { this.error = reduceErrors(error); this.isNextButtonDisabled = true; }); getQuizSession() - .then(quizSession => { + .then((quizSession) => { this.quizSession = quizSession; this.refreshCurrentQuestion(); }) - .catch(error => { + .catch((error) => { this.error = reduceErrors(error); this.quizSession = undefined; }); @@ -44,7 +44,7 @@ export default class GameApp extends LightningElement { refreshCurrentQuestion() { getCurrentQuestion({ sessionId: this.quizSession.Id }) - .then(currentQuestion => { + .then((currentQuestion) => { this.currentQuestion = currentQuestion; // Double phase change click prevention // eslint-disable-next-line @lwc/lwc/no-async-operation @@ -54,7 +54,7 @@ export default class GameApp extends LightningElement { } }, 2000); }) - .catch(error => { + .catch((error) => { this.error = reduceErrors(error); this.currentQuestion = undefined; this.isNextButtonDisabled = true; @@ -65,12 +65,12 @@ export default class GameApp extends LightningElement { this.isNextButtonDisabled = true; this.answerCount = undefined; triggerNextPhase({ sessionId: this.quizSession.Id }) - .then(updatedSession => { + .then((updatedSession) => { this.quizSession = updatedSession; this.error = undefined; this.refreshCurrentQuestion(); }) - .catch(error => { + .catch((error) => { this.error = reduceErrors(error); this.quizSession = undefined; }); diff --git a/src/main/default/lwc/leaderBoard/leaderBoard.js b/src/main/default/lwc/leaderBoard/leaderBoard.js index f10ce93..26c4a08 100644 --- a/src/main/default/lwc/leaderBoard/leaderBoard.js +++ b/src/main/default/lwc/leaderBoard/leaderBoard.js @@ -8,11 +8,11 @@ export default class LeaderBoard extends LightningElement { connectedCallback() { getPlayersSortedByScore({ maxFetchCount: 10 }) - .then(players => { + .then((players) => { this.error = undefined; this.displayPlayers(players); }) - .catch(error => { + .catch((error) => { this.error = reduceErrors(error); this.players = undefined; }); diff --git a/src/main/default/lwc/playerList/playerList.js b/src/main/default/lwc/playerList/playerList.js index 8173fc1..063193e 100755 --- a/src/main/default/lwc/playerList/playerList.js +++ b/src/main/default/lwc/playerList/playerList.js @@ -11,24 +11,24 @@ export default class playerList extends LightningElement { connectedCallback() { getPlayersSortedByScore() - .then(players => { - this.playerNames = players.map(player => player.Name); + .then((players) => { + this.playerNames = players.map((player) => player.Name); this.error = undefined; this.initEmpApi(); }) - .catch(error => { + .catch((error) => { this.error = reduceErrors(error); this.playerNames = undefined; }); } initEmpApi() { - empApi.onError(error => { + empApi.onError((error) => { // eslint-disable-next-line no-console console.error('Streaming API error: ' + JSON.stringify(error)); }); empApi - .subscribe('/data/Quiz_Player__ChangeEvent', -1, cdcEvent => { + .subscribe('/data/Quiz_Player__ChangeEvent', -1, (cdcEvent) => { if ( cdcEvent.data.payload.ChangeEventHeader.changeType === 'CREATE' @@ -36,7 +36,7 @@ export default class playerList extends LightningElement { this.handlePlayerCreationEvent(cdcEvent); } }) - .then(response => { + .then((response) => { this.subscription = response; }); } diff --git a/src/main/default/lwc/questionPicker/questionPicker.html b/src/main/default/lwc/questionPicker/questionPicker.html new file mode 100755 index 0000000..1fd468d --- /dev/null +++ b/src/main/default/lwc/questionPicker/questionPicker.html @@ -0,0 +1,34 @@ +<template> + <lightning-card title={cardTitle}> + <lightning-button + slot="actions" + label="Select random questions" + onclick={handleRandomizeClick} + ></lightning-button> + + <div class="slds-var-p-horizontal_small"> + <lightning-spinner + if:true={isLoading} + variant="brand" + alternative-text="Loading questions" + ></lightning-spinner> + + <lightning-dual-listbox + label="Select and sort questions for this session" + source-label="Available" + selected-label={selectedLabel} + options={allQuestions} + value={selectedQuestionIds} + onchange={handleQuestionChange} + ></lightning-dual-listbox> + <div class="slds-var-m-top_small slds-align_absolute-center"> + <lightning-button + label="Save" + variant="brand" + onclick={handleSaveClick} + disabled={isLoading} + ></lightning-button> + </div> + </div> + </lightning-card> +</template> diff --git a/src/main/default/lwc/questionPicker/questionPicker.js b/src/main/default/lwc/questionPicker/questionPicker.js new file mode 100755 index 0000000..b4f3010 --- /dev/null +++ b/src/main/default/lwc/questionPicker/questionPicker.js @@ -0,0 +1,131 @@ +import { LightningElement, api, wire } from 'lwc'; +import { ShowToastEvent } from 'lightning/platformShowToastEvent'; +import setSessionQuestions from '@salesforce/apex/QuizEditorController.setSessionQuestions'; +import getSessionQuestions from '@salesforce/apex/QuizEditorController.getSessionQuestions'; +import getAllQuestions from '@salesforce/apex/QuizEditorController.getAllQuestions'; + +export default class QuestionPicker extends LightningElement { + @api recordId; + + allQuestions = []; + selectedQuestionIds = []; + isSaving = false; + isDirty = false; + + @wire(getAllQuestions) + getAllQuestions({ data, error }) { + if (data) { + this.allQuestions = data.map((question) => ({ + value: question.Id, + label: question.Label__c + })); + } else if (error) { + console.error(error); + this.showToast('Failed to load all questions', undefined, 'error'); + } + } + + @wire(getSessionQuestions, { sessionId: '$recordId' }) + getSessionQuestions({ data, error }) { + if (data) { + this.selectedQuestionIds = data.map((question) => question.Id); + } else if (error) { + console.error(error); + this.showToast( + 'Failed to load session questions', + undefined, + 'error' + ); + } + } + + handleQuestionChange(event) { + this.selectedQuestionIds = event.detail.value; + this.isDirty = true; + } + + handleSaveClick() { + this.isSaving = true; + setSessionQuestions({ + sessionId: this.recordId, + questionIds: this.selectedQuestionIds + }) + .then(() => { + this.isSaving = false; + this.isDirty = false; + this.showToast('Success', 'Session questions saved', 'success'); + }) + .catch((error) => { + console.error(error); + this.showToast( + 'Failed to save session questions', + undefined, + 'error' + ); + }); + } + + handleRandomizeClick() { + // Prompt number of questions + // eslint-disable-next-line no-alert + const input = prompt( + 'Enter the number of questions you would like to select', + '5' + ); + const totalQuestionCount = this.allQuestions.length; + const selectionCount = parseInt(input, 10); + if ( + isNaN(selectionCount) || + selectionCount < 1 || + selectionCount > totalQuestionCount + ) { + this.showToast( + 'Operation aborted', + 'Invalid question count', + 'info' + ); + return; + } + // Select random questions + const selectedIds = []; + const allQuestions = JSON.parse(JSON.stringify(this.allQuestions)); + for (let i = 0; i < selectionCount; i++) { + const index = Math.floor(Math.random() * allQuestions.length); + const question = allQuestions.splice(index, 1)[0]; + selectedIds.push(question.value); + } + // Save selection + this.selectedQuestionIds = selectedIds; + this.isDirty = true; + // Notify user + this.showToast( + 'Success', + `${selectionCount} random questions selected. Don't forget to save them.`, + 'success' + ); + } + + showToast(title, message, variant) { + this.dispatchEvent( + new ShowToastEvent({ + title, + message, + variant + }) + ); + } + + get isLoading() { + return ( + this.isSaving || !(this.allQuestions && this.selectedQuestionIds) + ); + } + + get cardTitle() { + return `Session Questions ${this.isDirty ? '(modified)' : ''}`; + } + + get selectedLabel() { + return `Selected (${this.selectedQuestionIds.length})`; + } +} diff --git a/src/main/default/lwc/questionPicker/questionPicker.js-meta.xml b/src/main/default/lwc/questionPicker/questionPicker.js-meta.xml new file mode 100755 index 0000000..16a698f --- /dev/null +++ b/src/main/default/lwc/questionPicker/questionPicker.js-meta.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> + <apiVersion>48.0</apiVersion> + <isExposed>true</isExposed> + <masterLabel>Question Picker</masterLabel> + <targets> + <target>lightning__RecordPage</target> + </targets> + <targetConfigs> + <targetConfig targets="lightning__RecordPage"> + <objects> + <object>Quiz_Session__c</object> + </objects> + </targetConfig> + </targetConfigs> +</LightningComponentBundle> \ No newline at end of file diff --git a/src/main/default/objects/Quiz_Session__c/Quiz_Session__c.object-meta.xml b/src/main/default/objects/Quiz_Session__c/Quiz_Session__c.object-meta.xml index b8fb5bb..75d6da9 100644 --- a/src/main/default/objects/Quiz_Session__c/Quiz_Session__c.object-meta.xml +++ b/src/main/default/objects/Quiz_Session__c/Quiz_Session__c.object-meta.xml @@ -4,38 +4,144 @@ <actionName>Accept</actionName> <type>Default</type> </actionOverrides> + <actionOverrides> + <actionName>Accept</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Accept</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>CancelEdit</actionName> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>CancelEdit</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> <actionOverrides> <actionName>CancelEdit</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Clone</actionName> <type>Default</type> </actionOverrides> <actionOverrides> <actionName>Clone</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Clone</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Delete</actionName> <type>Default</type> </actionOverrides> <actionOverrides> <actionName>Delete</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Delete</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Edit</actionName> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Edit</actionName> + <formFactor>Large</formFactor> <type>Default</type> </actionOverrides> <actionOverrides> <actionName>Edit</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>List</actionName> <type>Default</type> </actionOverrides> <actionOverrides> <actionName>List</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>List</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>New</actionName> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>New</actionName> + <formFactor>Large</formFactor> <type>Default</type> </actionOverrides> <actionOverrides> <actionName>New</actionName> + <formFactor>Small</formFactor> <type>Default</type> </actionOverrides> <actionOverrides> <actionName>SaveEdit</actionName> <type>Default</type> </actionOverrides> + <actionOverrides> + <actionName>SaveEdit</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>SaveEdit</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> <actionOverrides> <actionName>Tab</actionName> <type>Default</type> </actionOverrides> + <actionOverrides> + <actionName>Tab</actionName> + <formFactor>Large</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>Tab</actionName> + <formFactor>Small</formFactor> + <type>Default</type> + </actionOverrides> + <actionOverrides> + <actionName>View</actionName> + <comment>Action override created by Lightning App Builder during activation.</comment> + <content>Quiz_Session_Record_Page</content> + <formFactor>Large</formFactor> + <skipRecordTypeSelect>false</skipRecordTypeSelect> + <type>Flexipage</type> + </actionOverrides> + <actionOverrides> + <actionName>View</actionName> + <comment>Action override created by Lightning App Builder during activation.</comment> + <content>Quiz_Session_Record_Page</content> + <formFactor>Small</formFactor> + <skipRecordTypeSelect>false</skipRecordTypeSelect> + <type>Flexipage</type> + </actionOverrides> <actionOverrides> <actionName>View</actionName> <type>Default</type> @@ -52,6 +158,7 @@ <enableSearch>true</enableSearch> <enableSharing>true</enableSharing> <enableStreamingApi>true</enableStreamingApi> + <externalSharingModel>Private</externalSharingModel> <label>Quiz Session</label> <nameField> <displayFormat>QS-{0000}</displayFormat> diff --git a/src/main/default/objects/Quiz_Session__c/fields/Current_Question__c.field-meta.xml b/src/main/default/objects/Quiz_Session__c/fields/Current_Question__c.field-meta.xml index 0cee65e..8ea0a30 100644 --- a/src/main/default/objects/Quiz_Session__c/fields/Current_Question__c.field-meta.xml +++ b/src/main/default/objects/Quiz_Session__c/fields/Current_Question__c.field-meta.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <CustomField xmlns="http://soap.sforce.com/2006/04/metadata"> <fullName>Current_Question__c</fullName> - <deleteConstraint>Restrict</deleteConstraint> + <deleteConstraint>SetNull</deleteConstraint> <externalId>false</externalId> <label>Current Question</label> <referenceTo>Quiz_Question__c</referenceTo> <relationshipLabel>Sessions</relationshipLabel> <relationshipName>Quiz_Sessions</relationshipName> - <required>true</required> + <required>false</required> <trackTrending>false</trackTrending> <type>Lookup</type> </CustomField>