Skip to content

Commit

Permalink
Release v4.19.0
Browse files Browse the repository at this point in the history
  • Loading branch information
antoinejaussoin authored Feb 4, 2023
1 parent d44fb54 commit 19d200c
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/alpha.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: 'Alpha Build'

on:
push:
branches: [v4190/other-deps]
branches: [v4190/release]

jobs:
build:
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ This will run a demo version, which you can turn into a fully licenced version b

## Versions History

### Version 4.19.0

- Feature: Adding the ability to set a timer for a session. This is optional and can be enabled in the settings. (👏 Thanks to [@Xyaren](https://github.com/Xyaren) for the idea)
- Feature: Confirm before deleting a post. Avoids accidental deletion of posts. (👏 Thanks to [@vadamovsky](https://github.com/vadamovsky) for the idea)
- Feature: Allow users to cancel their votes on a specific ticket. This feature can be disabled in the settings. (👏 Thanks to [@Xyaren](https://github.com/Xyaren) for the idea)
- Feature: Self-Hosted only: Display the number of logged users (👏 Thanks to [@dayByte](https://github.com/dayByte) for the idea)
- Upgrade to the latest version of TypeORM
- Convert all backend code to ESM
- 🇩🇪 German language updates (👏 Thanks to [@dayByte](https://github.com/dayByte) for his contribution)

### Version 4.18.1 (hotfix)

- Reinstates the Enter icon on board input on mobiles (👏 Thanks to Hans K. for the idea)
Expand Down Expand Up @@ -709,7 +719,7 @@ Many thanks to the following contributors who helped translating the app:
- Polish: [@olaf-cichocki](https://github.com/olaf-cichocki)
- Arabic: [@FrenchTechLead](https://github.com/FrenchTechLead)
- Japanese: [@sat0yu](https://github.com/sat0yu)
- German: [@PaulBrandt](https://github.com/PaulBrandt)
- German: [@PaulBrandt](https://github.com/PaulBrandt), [@dayByte](https://github.com/dayByte)
- Italian: [@mventuri](https://github.com/mventuri)

If you are a native speaker of another language, please don't hesitate to make a pull request to add a translation.
Expand Down
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@retrospected/backend",
"version": "4.18.1",
"version": "4.19.0",
"license": "GNU GPLv3",
"private": true,
"type": "module",
Expand Down
6 changes: 3 additions & 3 deletions backend/src/common/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ export const defaultOptions: SessionOptions = {
allowGiphy: true,
allowGrouping: true,
allowReordering: true,
allowCancelVote: false,
allowCancelVote: true,
blurCards: false,
newPostsFirst: true,
allowTimer: false,
timerDuration: 0,
allowTimer: true,
timerDuration: 15 * 60,
readonlyOnTimerEnd: true,
};

Expand Down
4 changes: 2 additions & 2 deletions backend/src/db/entities/SessionOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ export default class SessionOptionsEntity {
public allowGrouping: boolean;
@Column({ default: true })
public allowReordering: boolean;
@Column({ default: false })
@Column({ default: true })
public allowCancelVote: boolean;
@Column({ default: false })
@Column({ default: true })
public allowTimer: boolean;
@Column({ type: 'numeric', default: 15 * 60 })
public timerDuration: number;
Expand Down
4 changes: 2 additions & 2 deletions backend/src/db/migrations/1674589758156-AllowCancelVote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ 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`);
await queryRunner.query(`ALTER TABLE "templates" ADD "options_allow_cancel_vote" boolean NOT NULL DEFAULT true`);
await queryRunner.query(`ALTER TABLE "sessions" ADD "options_allow_cancel_vote" boolean NOT NULL DEFAULT true`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
Expand Down
4 changes: 2 additions & 2 deletions backend/src/db/migrations/1674905786619-TimerOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ export class TimerOptions1674905786619 implements MigrationInterface {
name = 'TimerOptions1674905786619'

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

Expand Down
20 changes: 20 additions & 0 deletions backend/src/db/migrations/1675515259530-ChangeDefaults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class ChangeDefaults1675515259530 implements MigrationInterface {
name = 'ChangeDefaults1675515259530'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "templates" ALTER COLUMN "options_allow_cancel_vote" SET DEFAULT true`);
await queryRunner.query(`ALTER TABLE "templates" ALTER COLUMN "options_allow_timer" SET DEFAULT true`);
await queryRunner.query(`ALTER TABLE "sessions" ALTER COLUMN "options_allow_cancel_vote" SET DEFAULT true`);
await queryRunner.query(`ALTER TABLE "sessions" ALTER COLUMN "options_allow_timer" SET DEFAULT true`);
}

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

}
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "4.18.1",
"version": "4.19.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@retrospected/frontend",
"version": "4.18.1",
"version": "4.19.0",
"license": "GNU GPLv3",
"private": true,
"dependencies": {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/common/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export const defaultOptions: SessionOptions = {
allowReordering: true,
blurCards: false,
newPostsFirst: true,
allowCancelVote: false,
allowTimer: false,
timerDuration: 0,
allowCancelVote: true,
allowTimer: true,
timerDuration: 15 * 60,
readonlyOnTimerEnd: true,
};

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/views/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,11 @@ function GamePage() {
<GameFooter
onReady={onUserReady}
messages={session.messages}
timer={session.options.allowTimer}
timerDuration={session.options.timerDuration}
options={session.options}
onTimerReset={onTimerReset}
onTimerStart={onTimerStart}
onMessage={onChatMessage}
onConfigure={onEditOptions}
/>
</ParticipantContainer>
</div>
Expand Down
31 changes: 15 additions & 16 deletions frontend/src/views/game/footer/GameFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import styled from '@emotion/styled';
import useUser from '../../../auth/useUser';
import { useCallback, useEffect, useState } from 'react';
import { trackEvent } from '../../../track';
import { Message } from 'common';
import { Message, SessionOptions } from 'common';
import useModal from '../../../hooks/useModal';
import ChatModal from '../chat/ChatModal';
import { useTranslation } from 'react-i18next';
Expand All @@ -21,22 +21,22 @@ import useCanModifyOptions from '../board/header/useCanModifyOptions';

type GameFooterProps = {
onReady: () => void;
timer: boolean;
timerDuration: number;
messages: Message[];
options: SessionOptions;
onMessage: (content: string) => void;
onTimerStart: () => void;
onTimerReset: () => void;
onConfigure: (options: SessionOptions) => void;
};

function GameFooter({
onReady,
onMessage,
messages,
timer,
timerDuration,
options,
onTimerStart,
onTimerReset,
onConfigure,
}: GameFooterProps) {
const { session } = useSession();
const user = useUser();
Expand All @@ -61,16 +61,15 @@ function GameFooter({
<UsersContainer>
<Users />
</UsersContainer>
{timer ? (
<TimerContainer>
<Timer
canControl={canActionTimer}
duration={timerDuration}
onStart={onTimerStart}
onStop={onTimerReset}
/>
</TimerContainer>
) : null}
<TimerContainer>
<Timer
canControl={canActionTimer}
options={options}
onStart={onTimerStart}
onStop={onTimerReset}
onConfigure={onConfigure}
/>
</TimerContainer>

<EndControlsContainer>
{user && !fullScreen ? (
Expand All @@ -86,7 +85,7 @@ function GameFooter({
<Button
onClick={handleReady}
variant="outlined"
endIcon={
startIcon={
isUserReady ? (
<Create htmlColor={colors.orange[500]} />
) : (
Expand Down
81 changes: 60 additions & 21 deletions frontend/src/views/game/footer/Timer.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import styled from '@emotion/styled';
import { PlayArrow, Stop, TimerOutlined } from '@mui/icons-material';
import { PlayArrow, Settings, Stop, TimerOutlined } from '@mui/icons-material';
import { Color, colors, IconButton } from '@mui/material';
import { SessionOptions } from 'common';
import { differenceInSeconds } from 'date-fns';
import useModal from 'hooks/useModal';
import { noop } from 'lodash';
import { useConfirm } from 'material-ui-confirm';
import { useCallback, useEffect, useState, memo } from 'react';
import { useTranslation } from 'react-i18next';
import { useTimer } from '../useTimer';
import { TimerSettingsModal } from './TimerSettingsModal';

type TimerProps = {
duration: number;
options: SessionOptions;
canControl: boolean;
onStart: () => void;
onStop: () => void;
onConfigure: (options: SessionOptions) => void;
};

export const Timer = memo(function Timer({
duration,
canControl,
options,
onStart,
onStop,
onConfigure,
}: TimerProps) {
const confirm = useConfirm();
const end = useTimer();
const { t } = useTranslation();
const [remaining, setRemaining] = useState<Time>(
getTime(end, duration, end ? differenceInSeconds(end, new Date()) : null)
getTime(
end,
options.timerDuration,
end ? differenceInSeconds(end, new Date()) : null
)
);
const [opened, open, close] = useModal();

const handleStop = useCallback(() => {
confirm({
Expand All @@ -43,35 +53,64 @@ export const Timer = memo(function Timer({

useEffect(() => {
if (!end) {
setRemaining(getTime(null, duration, null));
setRemaining(getTime(null, options.timerDuration, null));
return;
}
const handle = setInterval(() => {
const time = getTime(end, duration, differenceInSeconds(end, new Date()));
const time = getTime(
end,
options.timerDuration,
differenceInSeconds(end, new Date())
);
setRemaining(time);
}, 1000);

return () => clearInterval(handle);
}, [end, duration]);
}, [end, options.timerDuration]);

const color = getColor(duration, end);
const color = getColor(options.timerDuration, end);

return (
<Container>
<TimerOutlined fontSize="large" htmlColor={color[600]} />
<Remaining color={color[400]}>
{remaining.minutes}:{remaining.seconds}
</Remaining>
{options.allowTimer || canControl ? (
<TimerOutlined fontSize="large" htmlColor={color[600]} />
) : null}
{options.allowTimer ? (
<>
<Remaining color={color[400]}>
{remaining.minutes}:{remaining.seconds}
</Remaining>
{canControl ? (
end ? (
<IconButton onClick={handleStop}>
<Stop />
</IconButton>
) : (
<IconButton onClick={onStart}>
<PlayArrow />
</IconButton>
)
) : null}
</>
) : null}
{canControl ? (
end ? (
<IconButton onClick={handleStop}>
<Stop />
</IconButton>
) : (
<IconButton onClick={onStart}>
<PlayArrow />
</IconButton>
)
<IconButton onClick={open}>
<Settings />
</IconButton>
) : null}
{opened ? (
<TimerSettingsModal
open
onClose={close}
onChange={(updatedOptions) => {
if (!updatedOptions.allowTimer && !!end) {
onStop();
}
onConfigure(updatedOptions);
close();
}}
options={options}
/>
) : null}
</Container>
);
Expand Down
Loading

0 comments on commit 19d200c

Please sign in to comment.