Skip to content

Commit

Permalink
fix(contests): minor fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
uatisdeproblem committed Mar 24, 2024
1 parent f087a6a commit 69f9a71
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 22 deletions.
9 changes: 6 additions & 3 deletions back-end/src/handlers/contests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { User } from '../models/user.model';
///

const PROJECT = process.env.PROJECT;
const STAGE = process.env.STAGE;
const DDB_TABLES = { users: process.env.DDB_TABLE_users, contests: process.env.DDB_TABLE_contests };
const ddb = new DynamoDB();

Expand All @@ -27,6 +28,7 @@ class ContestsRC extends ResourceController {

constructor(event: any, callback: any) {
super(event, callback, { resourceId: 'contestId' });
if (STAGE === 'prod') this.silentLambdaLogs(); // to make the vote anonymous
}

protected async checkAuthBeforeRequest(): Promise<void> {
Expand Down Expand Up @@ -115,10 +117,11 @@ class ContestsRC extends ResourceController {
await ddb.transactWrites([{ Update: markUserContestVoted }, { Update: addUserVoteToContest }]);
}
private async publishResults(): Promise<void> {
if (!this.user.permissions.canManageContents) throw new HandledError('Unauthorized');

if (this.contest.publishedResults) throw new HandledError('Already public');

if (!this.contest.voteEndsAt || new Date().toISOString() <= this.contest.voteEndsAt)
throw new HandledError('Vote is not done');
if (!this.contest.isVoteEnded()) throw new HandledError('Vote is not done');

await ddb.update({
TableName: DDB_TABLES.contests,
Expand Down Expand Up @@ -155,7 +158,7 @@ class ContestsRC extends ResourceController {
if (!this.user.permissions.canManageContents) {
contests = contests.filter(c => c.enabled);
contests.forEach(contest => {
if (contest.publishedResults) delete contest.results;
if (!contest.publishedResults) delete contest.results;
});
}

Expand Down
13 changes: 7 additions & 6 deletions back-end/src/models/contest.model.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Resource, epochISOString } from 'idea-toolbox';

/**
* A contest to which people can vote in.
* A contest to which users can vote in.
*/
export class Contest extends Resource {
/**
Expand All @@ -13,11 +13,11 @@ export class Contest extends Resource {
*/
createdAt: epochISOString;
/**
* Whether the contest is enabled and therefore shown in the menu.
* Whether the contest is enabled and therefore shown in the menu to everyone.
*/
enabled: boolean;
/**
* If set, the vote is active (users can vote) and ends at the configured timestamp.
* If set, the vote is active (users can vote), and it ends at the configured timestamp.
*/
voteEndsAt?: epochISOString;
/**
Expand All @@ -38,7 +38,7 @@ export class Contest extends Resource {
candidates: ContestCandidate[];
/**
* The count of votes for each of the sorted candidates.
* Note: the order of the candidates list must not change after a vote is open.
* Note: the order of the candidates list must not change after the vote is open.
* This attribute is not accessible to non-admin users until `publishedResults` is true.
*/
results?: number[];
Expand Down Expand Up @@ -66,9 +66,10 @@ export class Contest extends Resource {
safeLoad(newData: any, safeData: any): void {
super.safeLoad(newData, safeData);
this.contestId = safeData.contestId;
this.results = safeData.results;
this.createdAt = safeData.createdAt;
if (safeData.isVoteStarted()) {
this.candidates = safeData.candidates;
this.results = safeData.results;
}
}

Expand Down Expand Up @@ -110,7 +111,7 @@ export class ContestCandidate extends Resource {
* The country of the candidate.
* This is particularly important beacuse, if set, users can't vote for candidates of their own countries.
*/
country: string;
country: string | null;

load(x: any): void {
super.load(x);
Expand Down
14 changes: 7 additions & 7 deletions front-end/src/app/tabs/contests/contest.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ import { Contest } from '@models/contest.model';
<ion-card-title>{{ contest.name }}</ion-card-title>
<ion-card-subtitle>
@if(contest.isVoteStarted()) { @if(contest.isVoteEnded()) { @if(contest.publishedResults) {
<ion-badge color="primary">{{ 'CONTESTS.RESULTS' | translate }}</ion-badge>
<ion-badge color="ESNgreen">{{ 'CONTESTS.RESULTS' | translate }}</ion-badge>
} @else {
<ion-badge color="ESNpink">{{ 'CONTESTS.VOTE_ENDED' | translate }}</ion-badge>
} } @else {
<ion-badge color="ESNgreen">
<ion-badge color="primary">
{{ 'CONTESTS.VOTE_NOW_UNTIL' | translate : { deadline: (contest.voteEndsAt | dateLocale : 'short') } }}
</ion-badge>
} } @else {
Expand Down Expand Up @@ -85,12 +85,12 @@ import { Contest } from '@models/contest.model';
<ion-button slot="end" fill="clear" (click)="_app.openURL(candidate.url)">
<ion-icon icon="link" slot="icon-only" />
</ion-button>
} @if(contest.publishedResults) { @if( isCandidateWinnerByIndex($index)) {
<ion-icon slot="end" icon="trophy" color="ESNgreen" />
} @if(contest.publishedResults) { @if(isCandidateWinnerByIndex($index)) {
<ion-icon slot="end" icon="trophy" color="ESNgreen" style="margin-left: 6px" />
}
<ion-badge
slot="end"
style="width: 80px; text-align: right"
style="width: 80px; text-align: right; margin-left: 6px"
[color]="isCandidateWinnerByIndex($index) ? 'ESNgreen' : 'primary'"
>
{{ contest.results[$index] ?? 0 }} {{ 'CONTESTS.VOTES' | translate | lowercase }}
Expand Down Expand Up @@ -161,7 +161,7 @@ export class ContestPage implements OnInit {
} catch (err) {
this._message.error('COMMON.NOT_FOUND');
} finally {
await this._loading.hide();
this._loading.hide();
}
}

Expand Down Expand Up @@ -208,7 +208,7 @@ export class ContestPage implements OnInit {
} catch (err) {
this._message.error('COMMON.OPERATION_FAILED');
} finally {
await this._loading.hide();
this._loading.hide();
}
};

Expand Down
4 changes: 2 additions & 2 deletions front-end/src/app/tabs/contests/contests.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ import { Contest } from '@models/contest.model';
<ion-item color="white" button detail (click)="selectContest(contest)">
<ion-label class="ion-text-wrap">{{ contest.name }}</ion-label>
@if(contest.isVoteStarted()) { @if(contest.isVoteEnded()) { @if(contest.publishedResults) {
<ion-badge color="primary">{{ 'CONTESTS.RESULTS' | translate }}</ion-badge>
<ion-badge color="ESNgreen">{{ 'CONTESTS.RESULTS' | translate }}</ion-badge>
} @else {
<ion-badge color="ESNpink">{{ 'CONTESTS.VOTE_ENDED' | translate }}</ion-badge>
} } @else {
<ion-badge color="ESNgreen">{{ 'CONTESTS.VOTE_NOW' | translate }}</ion-badge>
<ion-badge color="primary">{{ 'CONTESTS.VOTE_NOW' | translate }}</ion-badge>
} }
</ion-item>
} @empty { @if(contests) {
Expand Down
10 changes: 6 additions & 4 deletions front-end/src/app/tabs/contests/manageContest.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ import { Contest, ContestCandidate } from '@models/contest.model';
</ion-item>
<ion-item [class.fieldHasError]="hasFieldAnError('candidates[' + $index + '].url')">
<ion-label position="stacked">{{ 'CONTESTS.CANDIDATE_URL' | translate }}</ion-label>
<ion-input [(ngModel)]="candidate.url" [disabled]="contest.isVoteStarted()" />
<ion-input type="url" [(ngModel)]="candidate.url" [disabled]="contest.isVoteStarted()" />
</ion-item>
<ion-item [class.fieldHasError]="hasFieldAnError('candidates[' + $index + '].country')">
<ion-select
Expand All @@ -118,6 +118,7 @@ import { Contest, ContestCandidate } from '@models/contest.model';
[(ngModel)]="candidate.country"
[disabled]="contest.isVoteStarted()"
>
<ion-select-option [value]="null"></ion-select-option>
@for(country of _app.configurations.sectionCountries; track $index) {
<ion-select-option [value]="country">{{ country }}</ion-select-option>
}
Expand Down Expand Up @@ -154,7 +155,7 @@ import { Contest, ContestCandidate } from '@models/contest.model';
}
<ion-badge
slot="end"
style="width: 80px; text-align: right"
style="width: 80px; text-align: right; margin-left: 6px"
[color]="isCandidateWinnerByIndex($index) ? 'ESNgreen' : 'primary'"
>
{{ contest.results[$index] ?? 0 }} {{ 'CONTESTS.VOTES' | translate | lowercase }}
Expand Down Expand Up @@ -281,7 +282,8 @@ export class ManageContestComponent implements OnInit {
this.contest.candidates.push(new ContestCandidate());
}
removeCandidate(candidate: ContestCandidate): void {
this.contest.candidates.splice(this.contest.candidates.indexOf(candidate), 1);
const candidateIndex = this.contest.candidates.indexOf(candidate);
if (candidateIndex !== -1) this.contest.candidates.splice(candidateIndex, 1);
}

isCandidateWinnerByIndex(candidateIndex: number): boolean {
Expand All @@ -300,7 +302,7 @@ export class ManageContestComponent implements OnInit {
} catch (err) {
this._message.error('COMMON.OPERATION_FAILED');
} finally {
await this._loading.hide();
this._loading.hide();
}
};

Expand Down

0 comments on commit 69f9a71

Please sign in to comment.