Skip to content

Commit

Permalink
Added question picker (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
pozil authored Apr 9, 2020
1 parent a769082 commit 08e6c1b
Show file tree
Hide file tree
Showing 20 changed files with 593 additions and 127 deletions.
222 changes: 130 additions & 92 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand All @@ -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": {
Expand Down
10 changes: 9 additions & 1 deletion src/main/default/classes/QuizController.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions src/main/default/classes/QuizEditorController.cls
Original file line number Diff line number Diff line change
@@ -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);
}
}
5 changes: 5 additions & 0 deletions src/main/default/classes/QuizEditorController.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -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>
5 changes: 5 additions & 0 deletions src/main/default/classes/QuizQuestionService.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class QuizQuestionService extends QuizAbstractDataService {
public List<Quiz_Question__c> getQuestions() {
return [SELECT Id, Label__c FROM Quiz_Question__c];
}
}
5 changes: 5 additions & 0 deletions src/main/default/classes/QuizQuestionService.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -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>
29 changes: 29 additions & 0 deletions src/main/default/classes/QuizSessionService.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<behavior>Edit</behavior>
<field>Current_Question__c</field>
</layoutItems>
</layoutColumns>
Expand Down Expand Up @@ -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>
Expand All @@ -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>
Expand Down
8 changes: 4 additions & 4 deletions src/main/default/lwc/answerBarChart/answerBarChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
Expand Down Expand Up @@ -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;
});
Expand Down
8 changes: 4 additions & 4 deletions src/main/default/lwc/errorUtils/errorUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand All @@ -35,6 +35,6 @@ export function reduceErrors(errors) {
// Flatten
.reduce((prev, curr) => prev.concat(curr), [])
// Remove empty strings
.filter(message => !!message)
.filter((message) => !!message)
);
}
16 changes: 8 additions & 8 deletions src/main/default/lwc/gameApp/gameApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) {
Expand All @@ -27,24 +27,24 @@ 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;
});
}

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
Expand All @@ -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;
Expand All @@ -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;
});
Expand Down
4 changes: 2 additions & 2 deletions src/main/default/lwc/leaderBoard/leaderBoard.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
Expand Down
12 changes: 6 additions & 6 deletions src/main/default/lwc/playerList/playerList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,32 @@ 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'
) {
this.handlePlayerCreationEvent(cdcEvent);
}
})
.then(response => {
.then((response) => {
this.subscription = response;
});
}
Expand Down
Loading

0 comments on commit 08e6c1b

Please sign in to comment.