Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit ebb8408

Browse files
author
Kerry
authored
Poll history - read only list of polls in current timeline (#10055)
* add settings while under development * very basic tests for roomsummarycard * empty poll history dialog and option in room summary * pollS history in settings * render an ugly list of polls in current timeline * readonly poll history list items * fix scroll window * use short year code in date format, tidy * no results message + tests * strict fix * mock intldatetimeformat for stable date formatting * extract date format fn into date-utils * jsdoc
1 parent 544baa3 commit ebb8408

File tree

20 files changed

+572
-7
lines changed

20 files changed

+572
-7
lines changed

res/css/_components.pcss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
@import "./components/views/beacon/_ShareLatestLocation.pcss";
1818
@import "./components/views/beacon/_StyledLiveBeaconIcon.pcss";
1919
@import "./components/views/context_menus/_KebabContextMenu.pcss";
20+
@import "./components/views/dialogs/polls/_PollListItem.pcss";
2021
@import "./components/views/elements/_FilterDropdown.pcss";
2122
@import "./components/views/elements/_LearnMore.pcss";
2223
@import "./components/views/location/_EnableLiveShare.pcss";
@@ -161,6 +162,8 @@
161162
@import "./views/dialogs/_UserSettingsDialog.pcss";
162163
@import "./views/dialogs/_VerifyEMailDialog.pcss";
163164
@import "./views/dialogs/_WidgetCapabilitiesPromptDialog.pcss";
165+
@import "./views/dialogs/polls/_PollHistoryDialog.pcss";
166+
@import "./views/dialogs/polls/_PollHistoryList.pcss";
164167
@import "./views/dialogs/security/_AccessSecretStorageDialog.pcss";
165168
@import "./views/dialogs/security/_CreateCrossSigningDialog.pcss";
166169
@import "./views/dialogs/security/_CreateKeyBackupDialog.pcss";
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
.mx_PollListItem {
18+
width: 100%;
19+
display: grid;
20+
justify-content: left;
21+
align-items: center;
22+
grid-gap: $spacing-8;
23+
grid-template-columns: auto auto auto;
24+
grid-template-rows: auto;
25+
26+
color: $primary-content;
27+
}
28+
29+
.mx_PollListItem_icon {
30+
height: 14px;
31+
width: 14px;
32+
color: $quaternary-content;
33+
padding-left: $spacing-8;
34+
}
35+
36+
.mx_PollListItem_question {
37+
white-space: nowrap;
38+
overflow: hidden;
39+
text-overflow: ellipsis;
40+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
.mx_PollHistoryDialog_content {
18+
height: 600px;
19+
width: 100%;
20+
21+
display: flex;
22+
flex-direction: column;
23+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
.mx_PollHistoryList {
18+
display: flex;
19+
flex-direction: column;
20+
flex: 1 1 auto;
21+
max-height: 100%;
22+
}
23+
24+
.mx_PollHistoryList_list {
25+
overflow: auto;
26+
list-style: none;
27+
margin-block: 0;
28+
padding-inline: 0;
29+
flex: 1 1 0;
30+
align-content: flex-start;
31+
display: grid;
32+
grid-gap: $spacing-20;
33+
padding-right: $spacing-64;
34+
margin: $spacing-32 0;
35+
}
36+
37+
.mx_PollHistoryList_noResults {
38+
height: 100%;
39+
width: 100%;
40+
display: flex;
41+
align-items: center;
42+
justify-content: center;
43+
color: $secondary-content;
44+
}

src/DateUtils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,16 @@ export function formatPreciseDuration(durationMs: number): string {
269269
}
270270
return _t("%(value)ss", { value: seconds });
271271
}
272+
273+
/**
274+
* Formats a timestamp to a short date
275+
* (eg 25/12/22 in uk locale)
276+
* localised by system locale
277+
* @param timestamp - epoch timestamp
278+
* @returns {string} formattedDate
279+
*/
280+
export const formatLocalDateShort = (timestamp: number): string =>
281+
new Intl.DateTimeFormat(
282+
undefined, // locales
283+
{ day: "2-digit", month: "2-digit", year: "2-digit" },
284+
).format(timestamp);

src/components/views/dialogs/polls/PollHistoryDialog.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,26 @@ limitations under the License.
1515
*/
1616

1717
import React from "react";
18+
import { MatrixClient } from "matrix-js-sdk/src/client";
1819

1920
import { _t } from "../../../../languageHandler";
2021
import BaseDialog from "../BaseDialog";
2122
import { IDialogProps } from "../IDialogProps";
23+
import { PollHistoryList } from "./PollHistoryList";
24+
import { getPolls } from "./usePollHistory";
2225

2326
type PollHistoryDialogProps = Pick<IDialogProps, "onFinished"> & {
2427
roomId: string;
28+
matrixClient: MatrixClient;
2529
};
30+
export const PollHistoryDialog: React.FC<PollHistoryDialogProps> = ({ roomId, matrixClient, onFinished }) => {
31+
const pollStartEvents = getPolls(roomId, matrixClient);
2632

27-
export const PollHistoryDialog: React.FC<PollHistoryDialogProps> = ({ onFinished }) => {
2833
return (
2934
<BaseDialog title={_t("Polls history")} onFinished={onFinished}>
30-
{/* @TODO(kerrya) to be implemented in PSG-906 */}
35+
<div className="mx_PollHistoryDialog_content">
36+
<PollHistoryList pollStartEvents={pollStartEvents} />
37+
</div>
3138
</BaseDialog>
3239
);
3340
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import React from "react";
18+
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
19+
20+
import PollListItem from "./PollListItem";
21+
import { _t } from "../../../../languageHandler";
22+
23+
type PollHistoryListProps = {
24+
pollStartEvents: MatrixEvent[];
25+
};
26+
export const PollHistoryList: React.FC<PollHistoryListProps> = ({ pollStartEvents }) => {
27+
return (
28+
<div className="mx_PollHistoryList">
29+
{!!pollStartEvents.length ? (
30+
<ol className="mx_PollHistoryList_list">
31+
{pollStartEvents.map((pollStartEvent) => (
32+
<PollListItem key={pollStartEvent.getId()!} event={pollStartEvent} />
33+
))}
34+
</ol>
35+
) : (
36+
<span className="mx_PollHistoryList_noResults">{_t("There are no polls in this room")}</span>
37+
)}
38+
</div>
39+
);
40+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import React from "react";
18+
import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
19+
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
20+
21+
import { Icon as PollIcon } from "../../../../../res/img/element-icons/room/composer/poll.svg";
22+
import { formatLocalDateShort } from "../../../../DateUtils";
23+
24+
interface Props {
25+
event: MatrixEvent;
26+
}
27+
28+
const PollListItem: React.FC<Props> = ({ event }) => {
29+
const pollEvent = event.unstableExtensibleEvent as unknown as PollStartEvent;
30+
if (!pollEvent) {
31+
return null;
32+
}
33+
const formattedDate = formatLocalDateShort(event.getTs());
34+
return (
35+
<li data-testid={`pollListItem-${event.getId()!}`} className="mx_PollListItem">
36+
<span>{formattedDate}</span>
37+
<PollIcon className="mx_PollListItem_icon" />
38+
<span className="mx_PollListItem_question">{pollEvent.question.text}</span>
39+
</li>
40+
);
41+
};
42+
43+
export default PollListItem;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
18+
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
19+
import { MatrixClient } from "matrix-js-sdk/src/client";
20+
21+
/**
22+
* Get poll start events in a rooms live timeline
23+
* @param roomId - id of room to retrieve polls for
24+
* @param matrixClient - client
25+
* @returns {MatrixEvent[]} - array fo poll start events
26+
*/
27+
export const getPolls = (roomId: string, matrixClient: MatrixClient): MatrixEvent[] => {
28+
const room = matrixClient.getRoom(roomId);
29+
30+
if (!room) {
31+
throw new Error("Cannot find room");
32+
}
33+
34+
// @TODO(kerrya) poll history will be actively fetched in PSG-1043
35+
// for now, just display polls that are in the current timeline
36+
const timelineEvents = room.getLiveTimeline().getEvents();
37+
const pollStartEvents = timelineEvents.filter((event) => M_POLL_START.matches(event.getType()));
38+
39+
return pollStartEvents;
40+
};

src/components/views/right_panel/RoomSummaryCard.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
286286
const onRoomPollHistoryClick = (): void => {
287287
Modal.createDialog(PollHistoryDialog, {
288288
roomId: room.roomId,
289+
matrixClient: cli,
289290
});
290291
};
291292

@@ -353,7 +354,11 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
353354
{_t("Export chat")}
354355
</Button>
355356
)}
356-
<Button className="mx_RoomSummaryCard_icon_share" onClick={onShareRoomClick}>
357+
<Button
358+
data-testid="shareRoomButton"
359+
className="mx_RoomSummaryCard_icon_share"
360+
onClick={onShareRoomClick}
361+
>
357362
{_t("Share room")}
358363
</Button>
359364
<Button className="mx_RoomSummaryCard_icon_settings" onClick={onRoomSettingsClick}>

src/i18n/strings/en_EN.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3141,6 +3141,7 @@
31413141
"<b>Warning</b>: You should only set up key backup from a trusted computer.": "<b>Warning</b>: You should only set up key backup from a trusted computer.",
31423142
"Access your secure message history and set up secure messaging by entering your Security Key.": "Access your secure message history and set up secure messaging by entering your Security Key.",
31433143
"If you've forgotten your Security Key you can <button>set up new recovery options</button>": "If you've forgotten your Security Key you can <button>set up new recovery options</button>",
3144+
"There are no polls in this room": "There are no polls in this room",
31443145
"Send custom account data event": "Send custom account data event",
31453146
"Send custom room account data event": "Send custom room account data event",
31463147
"Event Type": "Event Type",

0 commit comments

Comments
 (0)