From fdb7b4df2ff3e1bc1d3579dfec37265f0b294d6e Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 27 Jun 2024 13:10:59 +0200
Subject: [PATCH 1/9] 1765: Added columns to playlist slides
---
CHANGELOG.md | 1 +
src/components/playlist/playlists-columns.jsx | 4 +-
.../playlist/shared-playlists-column.jsx | 4 +-
src/components/slide/slides-columns.jsx | 15 ++--
.../drag-and-drop-table.jsx | 3 +-
.../multi-and-table/select-slides-table.jsx | 5 +-
.../util/{published.jsx => publishing.jsx} | 44 +++++-----
src/components/util/publishingStatus.jsx | 86 +++++++++++++++++++
src/translations/da/common.json | 10 ++-
9 files changed, 133 insertions(+), 39 deletions(-)
rename src/components/util/{published.jsx => publishing.jsx} (56%)
create mode 100644 src/components/util/publishingStatus.jsx
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2afe3020..fda8c98f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+- Added option to sort slides in playlist by published.
- Changed from vite CJS to ESM.
- Removed array spread.
- Fixed HMR setup.
diff --git a/src/components/playlist/playlists-columns.jsx b/src/components/playlist/playlists-columns.jsx
index 06605e61..6189db7f 100644
--- a/src/components/playlist/playlists-columns.jsx
+++ b/src/components/playlist/playlists-columns.jsx
@@ -4,7 +4,7 @@ import ColumnHoc from "../util/column-hoc";
import SelectColumnHoc from "../util/select-column-hoc";
import UserContext from "../../context/user-context";
import ListButton from "../util/list/list-button";
-import Published from "../util/published";
+import Publishing from "../util/publishing.jsx";
/**
* Columns for playlists lists.
@@ -33,7 +33,7 @@ function getPlaylistColumns({
label: t("published"),
// eslint-disable-next-line react/prop-types
content: ({ publishedFrom, publishedTo, published }) => (
-
),
diff --git a/src/components/playlist/shared-playlists-column.jsx b/src/components/playlist/shared-playlists-column.jsx
index ee50fbe7..6a8300bf 100644
--- a/src/components/playlist/shared-playlists-column.jsx
+++ b/src/components/playlist/shared-playlists-column.jsx
@@ -1,6 +1,6 @@
import { React } from "react";
import { useTranslation } from "react-i18next";
-import Published from "../util/published";
+import Publishing from "../util/publishing.jsx";
/**
* Columns for shared playlists lists.
@@ -25,7 +25,7 @@ function getSharedPlaylistColumns() {
path: "published",
label: t("published"),
// eslint-disable-next-line react/prop-types
- content: ({ published }) => ,
+ content: ({ published }) => ,
},
];
diff --git a/src/components/slide/slides-columns.jsx b/src/components/slide/slides-columns.jsx
index 1dc0dbc2..748836c7 100644
--- a/src/components/slide/slides-columns.jsx
+++ b/src/components/slide/slides-columns.jsx
@@ -2,9 +2,10 @@ import { React } from "react";
import { useTranslation } from "react-i18next";
import TemplateLabelInList from "../util/template-label-in-list";
import ListButton from "../util/list/list-button";
-import Published from "../util/published";
+import Publishing from "../util/publishing.jsx";
import ColumnHoc from "../util/column-hoc";
import SelectColumnHoc from "../util/select-column-hoc";
+import PublishingStatus from "../util/publishingStatus.jsx";
/**
* Columns for slides lists.
@@ -48,10 +49,14 @@ function getSlidesColumns({
label: t("columns.slide-on-playlists"),
},
{
- key: "published",
- // eslint-disable-next-line react/prop-types
- content: ({ published }) => ,
- label: t("columns.published"),
+ key: "publishing",
+ content: ({ published }) => ,
+ label: t("columns.publishing"),
+ },
+ {
+ key: "active",
+ content: ({ published }) => ,
+ label: t("columns.status"),
},
];
diff --git a/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx b/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx
index 9dd1ebc8..0c234473 100644
--- a/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx
+++ b/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx
@@ -134,6 +134,7 @@ function DragAndDropTable({
providedSnapshot.isDragging,
providedDraggable.draggableProps.style
)}
+ className={data.className ?? ''}
>
{
if (data) {
setTotalItems(data["hydra:totalItems"]);
const newSlides = data["hydra:member"].map(({ slide }) => {
return slide;
});
+
setSelectedData([...selectedData, ...newSlides]);
// Get all selected slides. If a next page is defined, get the next page.
diff --git a/src/components/util/published.jsx b/src/components/util/publishing.jsx
similarity index 56%
rename from src/components/util/published.jsx
rename to src/components/util/publishing.jsx
index 9793d97b..54f72f78 100644
--- a/src/components/util/published.jsx
+++ b/src/components/util/publishing.jsx
@@ -1,58 +1,54 @@
-import { React, useEffect, useState } from "react";
+import { React, useEffect } from "react";
import PropTypes from "prop-types";
import dayjs from "dayjs";
import localeDa from "dayjs/locale/da";
import localizedFormat from "dayjs/plugin/localizedFormat";
import { useTranslation } from "react-i18next";
-import calculateIsPublished from "./helpers/calculate-is-published";
/**
* @param {object} props The props.
* @param {object} props.published Object with from and to.
* @returns {object} The published yes/no component.
*/
-function Published({ published }) {
+function Publishing({ published }) {
const { t } = useTranslation("common", { keyPrefix: "published" });
- const [isPublished, setIsPublished] = useState(false);
useEffect(() => {
dayjs.extend(localizedFormat);
}, []);
- useEffect(() => {
- setIsPublished(calculateIsPublished(published));
- }, [published]);
-
- if (!published.from && !published.to) {
- return {isPublished ? t("yes") : t("no")} ;
- }
-
- let publishedFrom = "-";
- let publishedTo = "-";
+ let publishedFrom = null;
+ let publishedTo = null;
if (published.from) {
- publishedFrom = dayjs(published.from).locale(localeDa).format("LLLL");
+ publishedFrom = dayjs(published.from).locale(localeDa).format("LLL");
}
+
if (published.to) {
- publishedTo = dayjs(published.to).locale(localeDa).format("LLLL");
+ publishedTo = dayjs(published.to).locale(localeDa).format("LLL");
}
+
return (
<>
-
- {t("from")}: {publishedFrom}
-
-
- {t("to")}: {publishedTo}
-
+ {publishedFrom && (
+
+ {t("from")}: {publishedFrom}
+
+ )}
+ {publishedTo && (
+
+ {t("to")}: {publishedTo}
+
+ )}
>
);
}
-Published.propTypes = {
+Publishing.propTypes = {
published: PropTypes.shape({
from: PropTypes.string,
to: PropTypes.string,
}).isRequired,
};
-export default Published;
+export default Publishing;
diff --git a/src/components/util/publishingStatus.jsx b/src/components/util/publishingStatus.jsx
new file mode 100644
index 00000000..b6d99fef
--- /dev/null
+++ b/src/components/util/publishingStatus.jsx
@@ -0,0 +1,86 @@
+import { React, useEffect, useState } from "react";
+import PropTypes from "prop-types";
+import dayjs from "dayjs";
+import localizedFormat from "dayjs/plugin/localizedFormat";
+import { useTranslation } from "react-i18next";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+ faMinusCircle,
+ faCheckCircle,
+ faClock,
+} from "@fortawesome/free-solid-svg-icons";
+
+/**
+ * @param {object} props The props.
+ * @param {object} props.published Object with from and to.
+ * @returns {object} The published yes/no component.
+ */
+function PublishingStatus({ published }) {
+ const PUBLISHED_EXPIRED = "EXPIRED";
+ const PUBLISHED_ACTIVE = "ACTIVE";
+ const PUBLISHED_FUTURE = "FUTURE";
+
+ const { t } = useTranslation("common", { keyPrefix: "published-state" });
+ const [publishedState, setPublishedState] = useState(null);
+
+ useEffect(() => {
+ dayjs.extend(localizedFormat);
+ }, []);
+
+ useEffect(() => {
+ let newPublishedState = null;
+ const now = dayjs(new Date());
+
+ const from = published.from ? dayjs(published.from) : null;
+ const to = published.to ? dayjs(published.to) : null;
+
+ if (from !== null) {
+ if (from.isAfter(now)) {
+ newPublishedState = PUBLISHED_FUTURE;
+ }
+ }
+
+ if (to !== null) {
+ if (to.isBefore(now)) {
+ newPublishedState = PUBLISHED_EXPIRED;
+ }
+ }
+
+ setPublishedState(newPublishedState ?? PUBLISHED_ACTIVE);
+
+ return () => {};
+ }, [published]);
+
+ // TODO: Fix to follow system colors.
+ return (
+
+ {publishedState === PUBLISHED_EXPIRED && (
+ <>
+ {" "}
+ {t("expired")}
+ >
+ )}
+ {publishedState === PUBLISHED_ACTIVE && (
+ <>
+ {" "}
+ {t("active")}
+ >
+ )}
+ {publishedState === PUBLISHED_FUTURE && (
+ <>
+ {" "}
+ {t("future")}
+ >
+ )}
+
+ );
+}
+
+PublishingStatus.propTypes = {
+ published: PropTypes.shape({
+ from: PropTypes.string,
+ to: PropTypes.string,
+ }).isRequired,
+};
+
+export default PublishingStatus;
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index c59ff732..384a8803 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -28,7 +28,8 @@
"columns": {
"template": "Skabelon",
"slide-on-playlists": "Spillelister",
- "published": "Udgivet"
+ "publishing": "Udgivelse",
+ "status": "Status"
},
"info-modal": {
"slide-on-playlists": "Slidet er på de følgende spillelister"
@@ -641,7 +642,7 @@
"drag-and-drop-table": {
"not-available": "Ikke tilgængeligt",
"table-header-for-indicator": "Drag and drop indikator",
- "help-text": "Brug space til at vælge et element til flytning, og brug derefter piltasterne til at trække op eller ned. Brug space til at slippe elementet igen, og brug escape til at annullere. Nogle skærmlæsere skal være i fokus før det virker."
+ "help-text": "Brug space til at vælge et element til flytning, og brug derefter piletasterne til at trække op eller ned. Brug space til at slippe elementet igen, og brug escape til at annullere. Nogle skærmlæsere skal være i fokus før det virker."
},
"link-for-list": {
"label": "Rediger"
@@ -981,5 +982,10 @@
"loading-messages": {
"saving-activation-code": "Opretter aktiveringskode"
}
+ },
+ "published-state": {
+ "active": "Aktiv",
+ "future": "Fremtidig",
+ "expired": "Udløbet"
}
}
From fed3ef51e334860e6cf708d854a8f619ab659590 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Fri, 28 Jun 2024 08:48:39 +0200
Subject: [PATCH 2/9] 1765: Added always as option for showing publishing
---
src/components/util/publishing.jsx | 3 +++
src/translations/da/common.json | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/components/util/publishing.jsx b/src/components/util/publishing.jsx
index 54f72f78..f3f99ab1 100644
--- a/src/components/util/publishing.jsx
+++ b/src/components/util/publishing.jsx
@@ -40,6 +40,9 @@ function Publishing({ published }) {
{t("to")}: {publishedTo}
)}
+ {publishedFrom === null && publishedTo === null && (
+ {t("always")}
+ )}
>
);
}
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 384a8803..33559409 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -557,7 +557,8 @@
"yes": "Ja",
"no": "Nej",
"from": "Fra",
- "to": "Til"
+ "to": "Til",
+ "always": "Ubegrænset"
},
"modal-dialog": {
"cancel": "Annuller",
From 52fddd34c3ee2e8150a5cf4818b30874fcc359e6 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Mon, 1 Jul 2024 11:09:48 +0200
Subject: [PATCH 3/9] 1765: Simplified table
---
.../playlist/playlist-campaign-form.jsx | 2 +-
src/components/slide/slides-columns.jsx | 68 ++++++++++++++-----
src/components/util/date-value.jsx | 24 +++++++
.../drag-and-drop-table.jsx | 2 +-
.../multi-and-table/select-slides-table.jsx | 62 +++++++++++++++++
src/components/util/publishing.jsx | 4 +-
src/components/util/publishingStatus.jsx | 1 -
src/translations/da/common.json | 5 +-
8 files changed, 146 insertions(+), 22 deletions(-)
create mode 100644 src/components/util/date-value.jsx
diff --git a/src/components/playlist/playlist-campaign-form.jsx b/src/components/playlist/playlist-campaign-form.jsx
index 69f9fd65..b30e3213 100644
--- a/src/components/playlist/playlist-campaign-form.jsx
+++ b/src/components/playlist/playlist-campaign-form.jsx
@@ -1,5 +1,5 @@
import { React, useState } from "react";
-import { Button, Col, Form, Row } from "react-bootstrap";
+import { Alert, Button, Col, Form, Row } from "react-bootstrap";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
diff --git a/src/components/slide/slides-columns.jsx b/src/components/slide/slides-columns.jsx
index 748836c7..a7da0857 100644
--- a/src/components/slide/slides-columns.jsx
+++ b/src/components/slide/slides-columns.jsx
@@ -6,6 +6,7 @@ import Publishing from "../util/publishing.jsx";
import ColumnHoc from "../util/column-hoc";
import SelectColumnHoc from "../util/select-column-hoc";
import PublishingStatus from "../util/publishingStatus.jsx";
+import DateValue from "../util/date-value.jsx";
/**
* Columns for slides lists.
@@ -15,6 +16,7 @@ import PublishingStatus from "../util/publishingStatus.jsx";
* @param {string} props.infoModalRedirect - The url for redirecting in the info modal.
* @param {string} props.infoModalTitle - The info modal title.
* @param {string} props.dataKey The data key for mapping the data. the list button
+ * @param props.hideColumns
* @returns {object} The columns for the slides lists.
*/
function getSlidesColumns({
@@ -22,19 +24,39 @@ function getSlidesColumns({
infoModalRedirect,
infoModalTitle,
dataKey,
+ hideColumns = {},
}) {
const { t } = useTranslation("common", { keyPrefix: "slides-list" });
- const columns = [
- {
+ const columns = [];
+
+ if (!hideColumns?.title) {
+ columns.push({
+ path: "title",
+ label: t("columns.name"),
+ });
+ }
+
+ if (!hideColumns?.createdBy) {
+ columns.push({
+ path: "createdBy",
+ label: t("columns.created-by"),
+ });
+ }
+
+ if (!hideColumns?.template) {
+ columns.push({
// eslint-disable-next-line react/prop-types
content: ({ templateInfo }) => (
),
key: "template",
label: t("columns.template"),
- },
- {
+ });
+ }
+
+ if (!hideColumns?.playlists) {
+ columns.push({
key: "playlists",
// eslint-disable-next-line react/prop-types
content: ({ onPlaylists }) => (
@@ -47,23 +69,37 @@ function getSlidesColumns({
/>
),
label: t("columns.slide-on-playlists"),
- },
- {
- key: "publishing",
- content: ({ published }) => ,
- label: t("columns.publishing"),
- },
- {
- key: "active",
+ });
+ }
+
+ if (!hideColumns?.publishingFrom) {
+ columns.push({
+ key: "publishing-from",
+ content: ({ published }) => ,
+ label: t("columns.publishing-from"),
+ });
+ }
+
+ if (!hideColumns?.publishingTo) {
+ columns.push({
+ key: "publishing-to",
+ content: ({ published }) => ,
+ label: t("columns.publishing-to"),
+ });
+ }
+
+ if (!hideColumns?.status) {
+ columns.push({
+ key: "status",
content: ({ published }) => ,
label: t("columns.status"),
- },
- ];
+ });
+ }
return columns;
}
-const SlideColumns = ColumnHoc(getSlidesColumns);
-const SelectSlideColumns = SelectColumnHoc(getSlidesColumns);
+const SlideColumns = ColumnHoc(getSlidesColumns, true);
+const SelectSlideColumns = SelectColumnHoc(getSlidesColumns, true);
export { SelectSlideColumns, SlideColumns };
diff --git a/src/components/util/date-value.jsx b/src/components/util/date-value.jsx
new file mode 100644
index 00000000..5f6b4ce8
--- /dev/null
+++ b/src/components/util/date-value.jsx
@@ -0,0 +1,24 @@
+import { React, useEffect } from "react";
+import PropTypes from "prop-types";
+import dayjs from "dayjs";
+import localeDa from "dayjs/locale/da";
+import localizedFormat from "dayjs/plugin/localizedFormat";
+
+/**
+ * @param {object} props The props.
+ * @param {string} props.date Date string to format.
+ * @returns {object} Formatted date
+ */
+function DateValue({ date }) {
+ useEffect(() => {
+ dayjs.extend(localizedFormat);
+ }, []);
+
+ return date ? dayjs(date).locale(localeDa).format("l LT") : "";
+}
+
+DateValue.propTypes = {
+ date: PropTypes.string,
+};
+
+export default DateValue;
diff --git a/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx b/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx
index 0c234473..e2d7ae46 100644
--- a/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx
+++ b/src/components/util/drag-and-drop-table/drag-and-drop-table.jsx
@@ -15,7 +15,7 @@ import "./drag-and-drop-table.scss";
* @param {Array} props.columns The columns for the table.
* @param {Array} props.data The data to display in the table.
* @param {string} props.name The id of the form element
- * @param {Function} props.onDropped Callback for when an items is dropped and
+ * @param {Function} props.onDropped Callback for when an item is dropped and
* the list is reordered.
* @param {Function} props.callback - The callback.
* @param {string} props.label - The label.
diff --git a/src/components/util/multi-and-table/select-slides-table.jsx b/src/components/util/multi-and-table/select-slides-table.jsx
index 7e89241c..0747e08c 100644
--- a/src/components/util/multi-and-table/select-slides-table.jsx
+++ b/src/components/util/multi-and-table/select-slides-table.jsx
@@ -1,6 +1,8 @@
import { React, useEffect, useState } from "react";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
+import { Alert, Button, Card } from "react-bootstrap";
+import dayjs from "dayjs";
import { SelectSlideColumns } from "../../slide/slides-columns";
import DragAndDropTable from "../drag-and-drop-table/drag-and-drop-table";
import SlidesDropdown from "../forms/multiselect-dropdown/slides/slides-dropdown";
@@ -42,6 +44,47 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
{ skip: !slideId }
);
+ const changeOrderByStatus = () => {
+ const expired = [];
+ const active = [];
+ const future = [];
+
+ const now = dayjs(new Date());
+
+ selectedData.forEach((entry) => {
+ const { published } = entry;
+ const from = published.from ? dayjs(published.from) : null;
+ const to = published.to ? dayjs(published.to) : null;
+
+ if (to !== null && to.isBefore(now)) {
+ expired.push(entry);
+ } else if (from !== null && from.isAfter(now)) {
+ future.push(entry);
+ } else {
+ active.push(entry);
+ }
+ });
+
+ setSelectedData([...expired, ...active, ...future]);
+ };
+
+ const changeOrderByExpirationDate = () => {
+ const newData = [...selectedData];
+
+ newData.sort((a, b) => {
+ if (a.published?.to === null) {
+ return 1;
+ }
+ if (b.published?.to === null) {
+ return -1;
+ }
+
+ return a.published.to > b.published?.to ? 1 : -1;
+ });
+
+ setSelectedData(newData);
+ };
+
useEffect(() => {
if (data) {
setTotalItems(data["hydra:totalItems"]);
@@ -110,6 +153,11 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
editTarget: "slide",
infoModalRedirect: "/playlist/edit",
infoModalTitle: t("info-modal.slide-on-playlists"),
+ hideColumns: {
+ createdBy: true,
+ template: true,
+ playlists: true,
+ },
});
return (
@@ -135,6 +183,20 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
callback={() => setPage(page + 1)}
/>
{t("edit-slides-help-text")}
+
+
+ {t("change-order-by-status-headline")}
+
+
+
+
+ {t("change-order-by-status-helptext")}
+
+
>
)}
diff --git a/src/components/util/publishing.jsx b/src/components/util/publishing.jsx
index f3f99ab1..6d678227 100644
--- a/src/components/util/publishing.jsx
+++ b/src/components/util/publishing.jsx
@@ -21,11 +21,11 @@ function Publishing({ published }) {
let publishedTo = null;
if (published.from) {
- publishedFrom = dayjs(published.from).locale(localeDa).format("LLL");
+ publishedFrom = dayjs(published.from).locale(localeDa).format("lll");
}
if (published.to) {
- publishedTo = dayjs(published.to).locale(localeDa).format("LLL");
+ publishedTo = dayjs(published.to).locale(localeDa).format("lll");
}
return (
diff --git a/src/components/util/publishingStatus.jsx b/src/components/util/publishingStatus.jsx
index b6d99fef..8eba5430 100644
--- a/src/components/util/publishingStatus.jsx
+++ b/src/components/util/publishingStatus.jsx
@@ -51,7 +51,6 @@ function PublishingStatus({ published }) {
return () => {};
}, [published]);
- // TODO: Fix to follow system colors.
return (
{publishedState === PUBLISHED_EXPIRED && (
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 33559409..7737fdd7 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -26,9 +26,12 @@
},
"slides-list": {
"columns": {
+ "name": "Titel",
+ "created-by": "Oprettet af",
"template": "Skabelon",
"slide-on-playlists": "Spillelister",
- "publishing": "Udgivelse",
+ "publishing-from": "Udgivelse fra",
+ "publishing-to": "Udgivelse til",
"status": "Status"
},
"info-modal": {
From 6995916987cf31ecba971edff8fcbc10ef4ae02e Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Mon, 1 Jul 2024 11:45:36 +0200
Subject: [PATCH 4/9] 1765: Set publishedFrom as now when creating new slides
---
src/components/slide/slide-create.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/slide/slide-create.jsx b/src/components/slide/slide-create.jsx
index 49e10aab..bb5a39d2 100644
--- a/src/components/slide/slide-create.jsx
+++ b/src/components/slide/slide-create.jsx
@@ -30,7 +30,7 @@ function SlideCreate() {
theme: themeInfo,
content: {},
media: [],
- published: { from: null, to: null },
+ published: { from: new Date(), to: null },
};
return ;
From cd3ebed658c8c285a29486d62ffa0065f359e937 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Mon, 1 Jul 2024 11:52:43 +0200
Subject: [PATCH 5/9] 1765: Added sorting
---
CHANGELOG.md | 4 +-
src/components/slide/slides-columns.jsx | 23 ++++++++++-
.../multi-and-table/select-slides-table.jsx | 41 +++++++++++--------
src/components/util/table/table-header.jsx | 2 +-
src/translations/da/common.json | 3 +-
5 files changed, 51 insertions(+), 22 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fda8c98f..59b89995 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,9 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
-- Added option to sort slides in playlist by published.
+- Changed playlist.slides list columns.
+- Set published.to to now when creating new slides.
+- Added option to sort slides in playlist by published.to and status.
- Changed from vite CJS to ESM.
- Removed array spread.
- Fixed HMR setup.
diff --git a/src/components/slide/slides-columns.jsx b/src/components/slide/slides-columns.jsx
index a7da0857..caec48c9 100644
--- a/src/components/slide/slides-columns.jsx
+++ b/src/components/slide/slides-columns.jsx
@@ -1,5 +1,6 @@
-import { React } from "react";
+import { React, useState } from "react";
import { useTranslation } from "react-i18next";
+import { Button } from "react-bootstrap";
import TemplateLabelInList from "../util/template-label-in-list";
import ListButton from "../util/list/list-button";
import Publishing from "../util/publishing.jsx";
@@ -17,6 +18,7 @@ import DateValue from "../util/date-value.jsx";
* @param {string} props.infoModalTitle - The info modal title.
* @param {string} props.dataKey The data key for mapping the data. the list button
* @param props.hideColumns
+ * @param props.sortColumns
* @returns {object} The columns for the slides lists.
*/
function getSlidesColumns({
@@ -25,6 +27,7 @@ function getSlidesColumns({
infoModalTitle,
dataKey,
hideColumns = {},
+ sortColumns = {},
}) {
const { t } = useTranslation("common", { keyPrefix: "slides-list" });
@@ -85,6 +88,15 @@ function getSlidesColumns({
key: "publishing-to",
content: ({ published }) => ,
label: t("columns.publishing-to"),
+ actions: sortColumns.publishedTo ? (
+
+ ) : null,
});
}
@@ -93,6 +105,15 @@ function getSlidesColumns({
key: "status",
content: ({ published }) => ,
label: t("columns.status"),
+ actions: sortColumns.status ? (
+
+ ) : null,
});
}
diff --git a/src/components/util/multi-and-table/select-slides-table.jsx b/src/components/util/multi-and-table/select-slides-table.jsx
index 0747e08c..34160601 100644
--- a/src/components/util/multi-and-table/select-slides-table.jsx
+++ b/src/components/util/multi-and-table/select-slides-table.jsx
@@ -1,7 +1,6 @@
import { React, useEffect, useState } from "react";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
-import { Alert, Button, Card } from "react-bootstrap";
import dayjs from "dayjs";
import { SelectSlideColumns } from "../../slide/slides-columns";
import DragAndDropTable from "../drag-and-drop-table/drag-and-drop-table";
@@ -12,6 +11,7 @@ import {
useGetV2PlaylistsByIdQuery,
} from "../../../redux/api/api.generated.ts";
import PlaylistGanttChart from "../../playlist/playlist-gantt-chart";
+import { displaySuccess } from "../list/toast-component/display-toast";
/**
* A multiselect and table for slides.
@@ -44,7 +44,7 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
{ skip: !slideId }
);
- const changeOrderByStatus = () => {
+ const sortByStatus = () => {
const expired = [];
const active = [];
const future = [];
@@ -65,10 +65,18 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
}
});
- setSelectedData([...expired, ...active, ...future]);
+ const newData = [...expired, ...active, ...future];
+ setSelectedData(newData);
+
+ const order = selectedData.map((entry) => entry["@id"]);
+ const newOrder = newData.map((entry) => entry["@id"]);
+
+ if (JSON.stringify(order) !== JSON.stringify(newOrder)) {
+ displaySuccess(t("data-changed"));
+ }
};
- const changeOrderByExpirationDate = () => {
+ const sortByPublishedTo = () => {
const newData = [...selectedData];
newData.sort((a, b) => {
@@ -83,6 +91,13 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
});
setSelectedData(newData);
+
+ const order = selectedData.map((entry) => entry["@id"]);
+ const newOrder = newData.map((entry) => entry["@id"]);
+
+ if (JSON.stringify(order) !== JSON.stringify(newOrder)) {
+ displaySuccess(t("data-changed"));
+ }
};
useEffect(() => {
@@ -158,6 +173,10 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
template: true,
playlists: true,
},
+ sortColumns: {
+ publishedTo: sortByPublishedTo,
+ status: sortByStatus,
+ },
});
return (
@@ -183,20 +202,6 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
callback={() => setPage(page + 1)}
/>
{t("edit-slides-help-text")}
-
-
- {t("change-order-by-status-headline")}
-
-
-
-
- {t("change-order-by-status-helptext")}
-
-
>
)}
diff --git a/src/components/util/table/table-header.jsx b/src/components/util/table/table-header.jsx
index 33ddfe13..9373cf1b 100644
--- a/src/components/util/table/table-header.jsx
+++ b/src/components/util/table/table-header.jsx
@@ -25,7 +25,7 @@ function TableHeader({ columns, draggable = false }) {
)}
{columns.map((column) => (
- {column.label} |
+ {column.label}{column.actions} |
))}
diff --git a/src/translations/da/common.json b/src/translations/da/common.json
index 7737fdd7..a6c43175 100644
--- a/src/translations/da/common.json
+++ b/src/translations/da/common.json
@@ -525,7 +525,8 @@
"remove-from-list": "Fjern fra liste",
"error-messages": {
"load-selected-slides-error": "Fejl da valgte slides skulle loades"
- }
+ },
+ "data-changed": "Rækkefølge ændret. Husk at gemme."
},
"select-screens-table": {
"columns": {
From 39e8e392f40650c3f42b786f4a06483652407f3d Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Tue, 2 Jul 2024 11:31:49 +0200
Subject: [PATCH 6/9] 1765: Minor adjustments
---
.../playlist/playlist-campaign-form.jsx | 2 +-
src/components/playlist/playlists-columns.jsx | 28 ++++++++++++-------
src/components/util/date-value.jsx | 10 ++-----
.../list/toast-component/display-toast.jsx | 7 +++++
.../multi-and-table/select-slides-table.jsx | 7 +++--
src/translations/da/common.json | 4 ++-
6 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/src/components/playlist/playlist-campaign-form.jsx b/src/components/playlist/playlist-campaign-form.jsx
index b30e3213..cbff6362 100644
--- a/src/components/playlist/playlist-campaign-form.jsx
+++ b/src/components/playlist/playlist-campaign-form.jsx
@@ -82,7 +82,7 @@ function PlaylistCampaignForm({
type="text"
label={t("playlist-campaign-form.playlist-description-label")}
placeholder={t(
- "playlist-campaign-form.playlist-description-placeholder"
+ "playlist-campaign-form.playlist-description-placeholder",
)}
value={playlist.description}
onChange={handleInput}
diff --git a/src/components/playlist/playlists-columns.jsx b/src/components/playlist/playlists-columns.jsx
index 6189db7f..cd71f724 100644
--- a/src/components/playlist/playlists-columns.jsx
+++ b/src/components/playlist/playlists-columns.jsx
@@ -5,6 +5,9 @@ import SelectColumnHoc from "../util/select-column-hoc";
import UserContext from "../../context/user-context";
import ListButton from "../util/list/list-button";
import Publishing from "../util/publishing.jsx";
+import DateValue from "../util/date-value.jsx";
+import { Button } from "react-bootstrap";
+import PublishingStatus from "../util/publishingStatus.jsx";
/**
* Columns for playlists lists.
@@ -28,16 +31,6 @@ function getPlaylistColumns({
});
const columns = [
- {
- path: "published",
- label: t("published"),
- // eslint-disable-next-line react/prop-types
- content: ({ publishedFrom, publishedTo, published }) => (
-
- ),
- },
{
key: "slides",
label: t("number-of-slides"),
@@ -61,6 +54,21 @@ function getPlaylistColumns({
/>
),
},
+ {
+ key: "publishing-from",
+ content: ({ published }) => ,
+ label: t("publishing-from"),
+ },
+ {
+ key: "publishing-to",
+ content: ({ published }) => ,
+ label: t("publishing-to"),
+ },
+ {
+ key: "status",
+ content: ({ published }) => ,
+ label: t("status"),
+ },
];
return columns;
diff --git a/src/components/util/date-value.jsx b/src/components/util/date-value.jsx
index 5f6b4ce8..eff66b73 100644
--- a/src/components/util/date-value.jsx
+++ b/src/components/util/date-value.jsx
@@ -1,8 +1,6 @@
-import { React, useEffect } from "react";
+import { React } from "react";
import PropTypes from "prop-types";
import dayjs from "dayjs";
-import localeDa from "dayjs/locale/da";
-import localizedFormat from "dayjs/plugin/localizedFormat";
/**
* @param {object} props The props.
@@ -10,11 +8,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat";
* @returns {object} Formatted date
*/
function DateValue({ date }) {
- useEffect(() => {
- dayjs.extend(localizedFormat);
- }, []);
-
- return date ? dayjs(date).locale(localeDa).format("l LT") : "";
+ return date ? dayjs(date).format("D/M/YYYY hh:mm") : "";
}
DateValue.propTypes = {
diff --git a/src/components/util/list/toast-component/display-toast.jsx b/src/components/util/list/toast-component/display-toast.jsx
index cf77c712..8493df50 100644
--- a/src/components/util/list/toast-component/display-toast.jsx
+++ b/src/components/util/list/toast-component/display-toast.jsx
@@ -10,6 +10,13 @@ export function displaySuccess(text) {
toast.success(displayText);
}
+/** @param {string} text The toast display text */
+export function displayWarning(text) {
+ const displayText = `${text} ${dayjs().format("HH:mm:ss")}`;
+
+ toast.warning(displayText);
+}
+
/**
* @param {string} errorString - The toast display text
* @param {object} error - The error
diff --git a/src/components/util/multi-and-table/select-slides-table.jsx b/src/components/util/multi-and-table/select-slides-table.jsx
index 34160601..15397d6a 100644
--- a/src/components/util/multi-and-table/select-slides-table.jsx
+++ b/src/components/util/multi-and-table/select-slides-table.jsx
@@ -11,7 +11,7 @@ import {
useGetV2PlaylistsByIdQuery,
} from "../../../redux/api/api.generated.ts";
import PlaylistGanttChart from "../../playlist/playlist-gantt-chart";
-import { displaySuccess } from "../list/toast-component/display-toast";
+import { displayWarning } from "../list/toast-component/display-toast";
/**
* A multiselect and table for slides.
@@ -72,7 +72,7 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
const newOrder = newData.map((entry) => entry["@id"]);
if (JSON.stringify(order) !== JSON.stringify(newOrder)) {
- displaySuccess(t("data-changed"));
+ displayWarning(t("data-changed"));
}
};
@@ -96,7 +96,7 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
const newOrder = newData.map((entry) => entry["@id"]);
if (JSON.stringify(order) !== JSON.stringify(newOrder)) {
- displaySuccess(t("data-changed"));
+ displayWarning(t("data-changed"));
}
};
@@ -192,6 +192,7 @@ function SelectSlidesTable({ handleChange, name, slideId = "" }) {
/>
{selectedData?.length > 0 && (
<>
+ Afspilningsrækkefølge
Date: Thu, 15 Aug 2024 17:07:14 +0200
Subject: [PATCH 7/9] 1859: Fixed hour format
---
src/components/util/date-value.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/util/date-value.jsx b/src/components/util/date-value.jsx
index eff66b73..aed9235f 100644
--- a/src/components/util/date-value.jsx
+++ b/src/components/util/date-value.jsx
@@ -8,7 +8,7 @@ import dayjs from "dayjs";
* @returns {object} Formatted date
*/
function DateValue({ date }) {
- return date ? dayjs(date).format("D/M/YYYY hh:mm") : "";
+ return date ? dayjs(date).format("D/M/YYYY HH:mm") : "";
}
DateValue.propTypes = {
From 5b2fad63d2ebe39aa7c0d701b662dbad49315ee1 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 15 Aug 2024 17:15:39 +0200
Subject: [PATCH 8/9] 1859: Clean up
---
src/components/playlist/playlist-campaign-form.jsx | 2 +-
src/components/slide/slides-columns.jsx | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/src/components/playlist/playlist-campaign-form.jsx b/src/components/playlist/playlist-campaign-form.jsx
index cbff6362..c2806682 100644
--- a/src/components/playlist/playlist-campaign-form.jsx
+++ b/src/components/playlist/playlist-campaign-form.jsx
@@ -1,5 +1,5 @@
import { React, useState } from "react";
-import { Alert, Button, Col, Form, Row } from "react-bootstrap";
+import { Button, Col, Form, Row } from "react-bootstrap";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
diff --git a/src/components/slide/slides-columns.jsx b/src/components/slide/slides-columns.jsx
index caec48c9..425c4fad 100644
--- a/src/components/slide/slides-columns.jsx
+++ b/src/components/slide/slides-columns.jsx
@@ -1,13 +1,12 @@
-import { React, useState } from "react";
+import { React } from "react";
import { useTranslation } from "react-i18next";
import { Button } from "react-bootstrap";
import TemplateLabelInList from "../util/template-label-in-list";
import ListButton from "../util/list/list-button";
-import Publishing from "../util/publishing.jsx";
import ColumnHoc from "../util/column-hoc";
import SelectColumnHoc from "../util/select-column-hoc";
-import PublishingStatus from "../util/publishingStatus.jsx";
-import DateValue from "../util/date-value.jsx";
+import PublishingStatus from "../util/publishingStatus";
+import DateValue from "../util/date-value";
/**
* Columns for slides lists.
@@ -17,8 +16,8 @@ import DateValue from "../util/date-value.jsx";
* @param {string} props.infoModalRedirect - The url for redirecting in the info modal.
* @param {string} props.infoModalTitle - The info modal title.
* @param {string} props.dataKey The data key for mapping the data. the list button
- * @param props.hideColumns
- * @param props.sortColumns
+ * @param {object} props.hideColumns Columns to hide.
+ * @param {object} props.sortColumns Columns to sort.
* @returns {object} The columns for the slides lists.
*/
function getSlidesColumns({
From f41da9105e5efcc26307f784d1338114a177f476 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Fri, 16 Aug 2024 10:13:08 +0200
Subject: [PATCH 9/9] 1859: Fixed tests after changes in tables
---
e2e/campaign.spec.js | 2 +-
e2e/playlist.spec.js | 3 ++-
e2e/slides.spec.js | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/e2e/campaign.spec.js b/e2e/campaign.spec.js
index 5b1c7fef..3cb54cf9 100644
--- a/e2e/campaign.spec.js
+++ b/e2e/campaign.spec.js
@@ -336,7 +336,7 @@ test.describe("Campaign pages work", () => {
.click();
await expect(
page.locator("#slides-section").locator("tbody").locator("tr td")
- ).toHaveCount(7);
+ ).toHaveCount(6);
// Remove slide
await page
diff --git a/e2e/playlist.spec.js b/e2e/playlist.spec.js
index 5590ac22..465a1e94 100644
--- a/e2e/playlist.spec.js
+++ b/e2e/playlist.spec.js
@@ -105,6 +105,7 @@ test.describe("Playlist create tests", () => {
await expect(page.locator("#cancel_playlist")).not.toBeVisible();
});
});
+
test.describe("Playlist list tests", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/admin/playlist/list");
@@ -238,6 +239,6 @@ test.describe("Playlist list tests", () => {
test("The correct amount of column headers loaded (playlist list)", async ({
page,
}) => {
- await expect(page.locator("thead").locator("th")).toHaveCount(6);
+ await expect(page.locator("thead").locator("th")).toHaveCount(8);
});
});
diff --git a/e2e/slides.spec.js b/e2e/slides.spec.js
index 9cc0de47..7895caeb 100644
--- a/e2e/slides.spec.js
+++ b/e2e/slides.spec.js
@@ -491,7 +491,7 @@ test.describe("Slides list works", () => {
});
test("The correct amount of column headers loaded", async ({ page }) => {
- await expect(page.locator("thead").locator("th")).toHaveCount(7);
+ await expect(page.locator("thead").locator("th")).toHaveCount(9);
});
test("It removes all selected", async ({ page }) => {
|