Skip to content

Commit

Permalink
Allowing to cancel votes (#457)
Browse files Browse the repository at this point in the history
  • Loading branch information
antoinejaussoin authored Jan 25, 2023
1 parent 9cf0509 commit 43c4b8d
Show file tree
Hide file tree
Showing 39 changed files with 331 additions and 22 deletions.
4 changes: 2 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"start": "nodemon --exec 'yarn fix & ts-node' --esm --files ./src/index.ts",
"create-migration": "scripty",
"create-empty-migration": "scripty",
"migrate": "typeorm-ts-node-commonjs -d src/db/index.ts migration:run",
"revert": "typeorm-ts-node-commonjs -d src/db/index.ts migration:revert",
"migrate": "typeorm-ts-node-esm -d src/db/index.ts migration:run",
"revert": "typeorm-ts-node-esm -d src/db/index.ts migration:revert",
"lint": "eslint 'src/**/*.ts'",
"test": "yarn jest",
"ci-test": "CI=true yarn test",
Expand Down
2 changes: 1 addition & 1 deletion backend/scripts/create-empty-migration.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
./node_modules/.bin/typeorm-ts-node-commonjs migration:create src/db/migrations/$1
./node_modules/.bin/typeorm-ts-node-esm migration:create src/db/migrations/$1
2 changes: 1 addition & 1 deletion backend/scripts/create-migration.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
./node_modules/.bin/typeorm-ts-node-commonjs -d src/db/index.ts migration:generate src/db/migrations/$1
./node_modules/.bin/typeorm-ts-node-esm -d src/db/index.ts migration:generate src/db/migrations/$1
2 changes: 2 additions & 0 deletions backend/src/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const actions = {
EDIT_POST: 'retrospected/posts/edit',
MOVE_POST: 'retrospected/posts/move',
LIKE_SUCCESS: 'retrospected/posts/like/success',
CANCEL_VOTES_SUCCESS: 'retrospected/posts/cancel-votes/success',
ADD_POST_GROUP_SUCCESS: 'retrospected/group/add/success',
DELETE_POST_GROUP: 'retrospected/group/delete',
EDIT_POST_GROUP: 'retrospected/group/edit',
Expand All @@ -24,6 +25,7 @@ const actions = {
RECEIVE_EDIT_POST: 'retrospected/posts/receive/edit',
RECEIVE_MOVE_POST: 'retrospected/posts/receive/move',
RECEIVE_LIKE: 'retrospected/posts/receive/like',
RECEIVE_CANCEL_VOTES: 'retrospected/posts/receive/cancel-votes',
RECEIVE_POST_GROUP: 'retrospected/group/receive/add',
RECEIVE_DELETE_POST_GROUP: 'retrospected/group/receive/delete',
RECEIVE_EDIT_POST_GROUP: 'retrospected/group/receive/edit',
Expand Down
1 change: 1 addition & 0 deletions backend/src/common/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const defaultOptions: SessionOptions = {
allowGiphy: true,
allowGrouping: true,
allowReordering: true,
allowCancelVote: false,
blurCards: false,
newPostsFirst: true,
};
Expand Down
1 change: 1 addition & 0 deletions backend/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface SessionOptions {
allowGiphy: boolean;
allowGrouping: boolean;
allowReordering: boolean;
allowCancelVote: boolean;
blurCards: boolean;
newPostsFirst: boolean;
}
Expand Down
10 changes: 10 additions & 0 deletions backend/src/common/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,19 @@ export interface WsReceiveLikeUpdatePayload {
vote: VoteExtract;
}

export interface WsReceiveCancelVotesPayload {
postId: string;
userId: string;
}

export interface WsDeletePostPayload {
postId: string;
}

export interface WsCancelVotesPayload {
postId: string;
}

export interface WsDeleteGroupPayload {
groupId: string;
}
Expand Down Expand Up @@ -73,6 +82,7 @@ export type WsErrorType =
| 'cannot_delete_group'
| 'cannot_rename_session'
| 'cannot_record_chat_message'
| 'cannot_cancel_votes'
| 'unknown_error'
| 'action_unauthorised';

Expand Down
20 changes: 20 additions & 0 deletions backend/src/db/actions/votes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ import {
} from '../repositories/index.js';
import { transaction } from './transaction.js';

export async function cancelVotes(
userId: string,
sessionId: string,
postId: string
): Promise<void> {
return await transaction(async (manager) => {
const sessionRepository = manager.withRepository(SessionRepository);
const voteRepository = manager.withRepository(VoteRepository);
const session = await sessionRepository.findOne({
where: { id: sessionId },
});
if (session && session.options.allowCancelVote) {
await voteRepository.delete({
user: { id: userId },
post: { id: postId },
});
}
});
}

export async function registerVote(
userId: string,
sessionId: string,
Expand Down
3 changes: 3 additions & 0 deletions backend/src/db/entities/SessionOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export default class SessionOptionsEntity {
@Column({ default: true })
public allowReordering: boolean;
@Column({ default: false })
public allowCancelVote: boolean;
@Column({ default: false })
public blurCards: boolean;
@Column({ default: true })
public newPostsFirst: boolean;
Expand All @@ -49,6 +51,7 @@ export default class SessionOptionsEntity {
this.allowGiphy = optionsWithDefault.allowGiphy;
this.allowGrouping = optionsWithDefault.allowGrouping;
this.allowReordering = optionsWithDefault.allowMultipleVotes;
this.allowCancelVote = optionsWithDefault.allowCancelVote;
this.blurCards = optionsWithDefault.blurCards;
this.newPostsFirst = optionsWithDefault.newPostsFirst;
}
Expand Down
16 changes: 16 additions & 0 deletions backend/src/db/migrations/1674589758156-AllowCancelVote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class AllowCancelVote1674589758156 implements MigrationInterface {
name = 'AllowCancelVote1674589758156'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "templates" ADD "options_allow_cancel_vote" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`ALTER TABLE "sessions" ADD "options_allow_cancel_vote" boolean NOT NULL DEFAULT false`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "sessions" DROP COLUMN "options_allow_cancel_vote"`);
await queryRunner.query(`ALTER TABLE "templates" DROP COLUMN "options_allow_cancel_vote"`);
}

}
29 changes: 28 additions & 1 deletion backend/src/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
WsGroupUpdatePayload,
WsUserReadyPayload,
Message,
WsCancelVotesPayload,
WsReceiveCancelVotesPayload,
} from './common/index.js';
import { RateLimiterMemory } from 'rate-limiter-flexible';
import chalk from 'chalk-template';
Expand Down Expand Up @@ -58,7 +60,7 @@ import {
updatePostGroup,
} from './db/actions/posts.js';
import config from './config.js';
import { registerVote } from './db/actions/votes.js';
import { cancelVotes, registerVote } from './db/actions/votes.js';
import { deserialiseIds, UserIds } from './utils.js';
import { QueryFailedError } from 'typeorm';
import { saveChatMessage } from './db/actions/chat.js';
Expand All @@ -79,6 +81,8 @@ const {
ADD_POST_GROUP_SUCCESS,
DELETE_POST,
LIKE_SUCCESS,
CANCEL_VOTES_SUCCESS,
RECEIVE_CANCEL_VOTES,
EDIT_POST,
DELETE_POST_GROUP,
EDIT_POST_GROUP,
Expand Down Expand Up @@ -478,6 +482,28 @@ export default (io: Server) => {
}
};

const onCancelVotes = async (
userIds: UserIds | null,
sessionId: string,
data: WsCancelVotesPayload,
socket: Socket
) => {
if (checkUser(userIds, socket)) {
await cancelVotes(userIds.userId, sessionId, data.postId);

sendToAllOrError<WsReceiveCancelVotesPayload>(
socket,
sessionId,
RECEIVE_CANCEL_VOTES,
'cannot_cancel_votes',
{
postId: data.postId,
userId: userIds.userId,
}
);
}
};

const onEditPost = async (
_userIds: UserIds | null,
sessionId: string,
Expand Down Expand Up @@ -607,6 +633,7 @@ export default (io: Server) => {
{ type: EDIT_POST, handler: onEditPost },
{ type: DELETE_POST, handler: onDeletePost },
{ type: LIKE_SUCCESS, handler: onLikePost },
{ type: CANCEL_VOTES_SUCCESS, handler: onCancelVotes },

{ type: ADD_POST_GROUP_SUCCESS, handler: onAddPostGroup },
{ type: EDIT_POST_GROUP, handler: onEditPostGroup },
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const actions = {
EDIT_POST: 'retrospected/posts/edit',
MOVE_POST: 'retrospected/posts/move',
LIKE_SUCCESS: 'retrospected/posts/like/success',
CANCEL_VOTES_SUCCESS: 'retrospected/posts/cancel-votes/success',
ADD_POST_GROUP_SUCCESS: 'retrospected/group/add/success',
DELETE_POST_GROUP: 'retrospected/group/delete',
EDIT_POST_GROUP: 'retrospected/group/edit',
Expand All @@ -24,6 +25,7 @@ const actions = {
RECEIVE_EDIT_POST: 'retrospected/posts/receive/edit',
RECEIVE_MOVE_POST: 'retrospected/posts/receive/move',
RECEIVE_LIKE: 'retrospected/posts/receive/like',
RECEIVE_CANCEL_VOTES: 'retrospected/posts/receive/cancel-votes',
RECEIVE_POST_GROUP: 'retrospected/group/receive/add',
RECEIVE_DELETE_POST_GROUP: 'retrospected/group/receive/delete',
RECEIVE_EDIT_POST_GROUP: 'retrospected/group/receive/edit',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/common/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const defaultOptions: SessionOptions = {
allowReordering: true,
blurCards: false,
newPostsFirst: true,
allowCancelVote: false,
};

export const defaultSession: Omit<Session, 'createdBy'> = {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface SessionOptions {
allowGiphy: boolean;
allowGrouping: boolean;
allowReordering: boolean;
allowCancelVote: boolean;
blurCards: boolean;
newPostsFirst: boolean;
}
Expand Down
12 changes: 11 additions & 1 deletion frontend/src/common/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
User,
VoteExtract,
VoteType,
} from './types';
} from './types.js';

export interface WebsocketMessage<T> {
payload: T;
Expand Down Expand Up @@ -41,10 +41,19 @@ export interface WsReceiveLikeUpdatePayload {
vote: VoteExtract;
}

export interface WsReceiveCancelVotesPayload {
postId: string;
userId: string;
}

export interface WsDeletePostPayload {
postId: string;
}

export interface WsCancelVotesPayload {
postId: string;
}

export interface WsDeleteGroupPayload {
groupId: string;
}
Expand Down Expand Up @@ -73,6 +82,7 @@ export type WsErrorType =
| 'cannot_delete_group'
| 'cannot_rename_session'
| 'cannot_record_chat_message'
| 'cannot_cancel_votes'
| 'unknown_error'
| 'action_unauthorised';

Expand Down
6 changes: 5 additions & 1 deletion frontend/src/translations/locales/ar-SA.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"voteRemainingMultiple": "لديك {{number}} {{type}}ثانية متبقية.",
"voteRemainingOne": "لديك فقط {{type}} واحد متبقي، جعله عديم!",
"voteRemainingNone": "ليس لديك أي {{type}} متبقي.",
"toggleGiphyButton": "تبديل الصورة الجافية"
"toggleGiphyButton": "تبديل الصورة الجافية",
"cancelVote": "إلغاء تصويتك على هذا المنشور"
},
"Customize": {
"title": "تخصيص الجلسة الخاصة بك",
Expand All @@ -77,6 +78,8 @@
"allowSelfVotingHelp": "ما إذا كان يسمح للمستخدم بالتصويت على مشاركته الخاصة",
"allowMultipleVotes": "السماح بتعدد الأصوات",
"allowMultipleVotesHelp": "ما إذا كان يسمح للمستخدم بالتصويت عدة مرات على نفس المنشور",
"allowCancelVote": "السماح بإلغاء التصويت",
"allowCancelVoteHelp": "ما إذا كان يسمح للمستخدم بإلغاء تصويته على مشاركة محددة",
"allowActions": "السماح بالإجراءات",
"allowActionsHelp": "ما إذا كان سيتم السماح بحقل \"الإجراء\" (المتابعة) في كل مشاركة",
"allowAuthorVisible": "إظهار المؤلف",
Expand Down Expand Up @@ -129,6 +132,7 @@
"error_cannot_rename_session": "فشل إعادة تسمية الجلسة",
"error_cannot_save_columns": "فشل حفظ الأعمدة",
"error_cannot_save_options": "فشل حفظ الخيارات",
"error_cannot_cancel_votes": "فشل إلغاء الأصوات",
"maxPostsReached": "لقد وصلت إلى الحد الأقصى لعدد المشاركات التي حددها المشرف",
"iAmDone": "لقد انتهيت!",
"iAmNotDoneYet": "أنا لم أنتهِ بعد...",
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/translations/locales/de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"voteRemainingMultiple": "Sie können noch {{number}} mal {{type}}.",
"voteRemainingOne": "Sie können noch ein mal {{type}}, überlegen Sie es sich gut!",
"voteRemainingNone": "Sie können nicht mehr {{type}}.",
"toggleGiphyButton": "Giphy-Bild umschalten"
"toggleGiphyButton": "Giphy-Bild umschalten",
"cancelVote": "Deine Stimme für diesen Beitrag abbrechen"
},
"Customize": {
"title": "Personalisieren Sie die Sitzung",
Expand All @@ -77,6 +78,8 @@
"allowSelfVotingHelp": "Soll es Nutzern möglich sein für seine eigenen Beiträge zu stimmen?",
"allowMultipleVotes": "Mehrfachstimmen",
"allowMultipleVotesHelp": "Soll es Nutzern möglich sein mehrfach zu abzustimmen?",
"allowCancelVote": "Abstimmungen abbrechen",
"allowCancelVoteHelp": "Gibt an, ob ein Benutzer seine Stimme für einen bestimmten Beitrag abbrechen kann",
"allowActions": "Erlaube Maßnahmen",
"allowActionsHelp": "Bestimmt ob Maßnahmen hinzugefügt werden können",
"allowAuthorVisible": "Zeige Autor",
Expand Down Expand Up @@ -129,6 +132,7 @@
"error_cannot_rename_session": "Umbenennen der Sitzung fehlgeschlagen",
"error_cannot_save_columns": "Spalten speichern fehlgeschlagen",
"error_cannot_save_options": "Speichern der Optionen fehlgeschlagen",
"error_cannot_cancel_votes": "Abbruch der Abstimmung fehlgeschlagen",
"maxPostsReached": "Sie haben die vom Moderator festgelegte maximale Anzahl von Beiträgen erreicht.",
"iAmDone": "Ich bin fertig!",
"iAmNotDoneYet": "Ich bin noch nicht fertig...",
Expand Down Expand Up @@ -442,4 +446,4 @@
"Chat": {
"writeAMessage": "Hier eine Nachricht schreiben..."
}
}
}
6 changes: 5 additions & 1 deletion frontend/src/translations/locales/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"voteRemainingMultiple": "You have {{number}} {{type}}s remaining.",
"voteRemainingOne": "You only have one {{type}} remaining, make it count!",
"voteRemainingNone": "You don't have any {{type}} remaining.",
"toggleGiphyButton": "Toggle Giphy image"
"toggleGiphyButton": "Toggle Giphy image",
"cancelVote": "Cancel your votes on this post"
},
"Customize": {
"title": "Customise your Session",
Expand All @@ -77,6 +78,8 @@
"allowSelfVotingHelp": "Whether to allow a user to vote on their own post",
"allowMultipleVotes": "Allow Multiple Votes",
"allowMultipleVotesHelp": "Whether to allow a user to vote multiple times on the same post",
"allowCancelVote": "Allow Cancel Votes",
"allowCancelVoteHelp": "Whether to allow a user to cancel their vote on a specific post",
"allowActions": "Allow Actions",
"allowActionsHelp": "Whether to allow the 'Action' (follow-up) field on each post",
"allowAuthorVisible": "Show Author",
Expand Down Expand Up @@ -129,6 +132,7 @@
"error_cannot_rename_session": "Renaming the session failed",
"error_cannot_save_columns": "Saving columns failed",
"error_cannot_save_options": "Saving options failed",
"error_cannot_cancel_votes": "Cancelling votes failed",
"maxPostsReached": "You have reached the maximum number of posts set by the moderator.",
"iAmDone": "I'm done!",
"iAmNotDoneYet": "I'm not done yet...",
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/translations/locales/es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"voteRemainingMultiple": "Tienes {{number}} {{type}}s restantes.",
"voteRemainingOne": "Solo te queda un {{type}} restante, ¡hazlo contar!",
"voteRemainingNone": "No te quedan {{type}}.",
"toggleGiphyButton": "Cambiar imagen de Giphy"
"toggleGiphyButton": "Cambiar imagen de Giphy",
"cancelVote": "Cancela tus votos en esta publicación"
},
"Customize": {
"title": "Personaliza tu sesión",
Expand All @@ -77,6 +78,8 @@
"allowSelfVotingHelp": "Si permitir que un usuario vote en su propio post",
"allowMultipleVotes": "Permitir múltiples votos",
"allowMultipleVotesHelp": "Si permitir que un usuario vote varias veces en el mismo post",
"allowCancelVote": "Permitir Cancel Votes",
"allowCancelVoteHelp": "Si permitir que un usuario cancele su voto en un mensaje específico",
"allowActions": "Permitir acciones",
"allowActionsHelp": "Si permitir o no el campo 'Acción' (seguimiento) en cada publicación",
"allowAuthorVisible": "Mostrar autor",
Expand Down Expand Up @@ -129,6 +132,7 @@
"error_cannot_rename_session": "Fallo al renombrar la sesión",
"error_cannot_save_columns": "Error al guardar columnas",
"error_cannot_save_options": "Fallo al guardar opciones",
"error_cannot_cancel_votes": "Falló la cancelación de votos",
"maxPostsReached": "Has alcanzado el número máximo de mensajes establecidos por el moderador.",
"iAmDone": "¡He terminado!",
"iAmNotDoneYet": "No he terminado todavía...",
Expand Down
Loading

0 comments on commit 43c4b8d

Please sign in to comment.