Skip to content

Commit 7479d70

Browse files
authored
Merge pull request #276 from os2display/feature/colibo-feed
Added colibo feed type
2 parents e1cb150 + aa843d8 commit 7479d70

File tree

8 files changed

+201
-26
lines changed

8 files changed

+201
-26
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
- [#276](https://github.com/os2display/display-admin-client/pull/276)
8+
- Added Colibo feed type form.
9+
- Fixed feed type selector when unsupported type.
10+
711
## [2.4.0] - 2025-03-31
812

913
- [#281](https://github.com/os2display/display-admin-client/pull/281)

src/components/feed-sources/feed-source-form.jsx

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { React } from "react";
2-
import { Button, Row, Col } from "react-bootstrap";
2+
import { Alert, Button, Row, Col } from "react-bootstrap";
33
import { useTranslation } from "react-i18next";
44
import { useNavigate } from "react-router-dom";
55
import PropTypes from "prop-types";
@@ -12,6 +12,7 @@ import FormInput from "../util/forms/form-input";
1212
import CalendarApiFeedType from "./templates/calendar-api-feed-type";
1313
import NotifiedFeedType from "./templates/notified-feed-type";
1414
import EventDatabaseApiFeedType from "./templates/event-database-feed-type";
15+
import ColiboFeedType from "./templates/colibo-feed-type";
1516
import StickyFooter from "../util/sticky-footer";
1617
import EventDatabaseApiV2FeedType from "./templates/event-database-v2-feed-type";
1718

@@ -22,7 +23,6 @@ import EventDatabaseApiV2FeedType from "./templates/event-database-v2-feed-type"
2223
* @param {object} props.feedSource The feed-source object to modify in the form.
2324
* @param {Function} props.handleInput Handles form input.
2425
* @param {Function} props.handleSubmit Handles form submit.
25-
* @param {Function} props.handleSaveNoClose Handles form submit with close.
2626
* @param {string} props.headerText Headline text.
2727
* @param {boolean} [props.isLoading] Indicator of whether the form is loading.
2828
* Default is `false`
@@ -32,6 +32,7 @@ import EventDatabaseApiV2FeedType from "./templates/event-database-v2-feed-type"
3232
* @param {string} props.mode The mode
3333
* @param {Function} props.onFeedTypeChange Callback on feed type change.
3434
* @param {Function} props.handleSecretInput Callback on secret input change.
35+
* @param {Function} props.handleSaveNoClose Handles save but stays on page.
3536
* @returns {object} The feed-source form.
3637
*/
3738
function FeedSourceForm({
@@ -50,6 +51,10 @@ function FeedSourceForm({
5051
const { t } = useTranslation("common", { keyPrefix: "feed-source-form" });
5152
const navigate = useNavigate();
5253

54+
const typeInOptions =
55+
!feedSource?.feedType ||
56+
feedSourceTypeOptions.find((el) => el.value === feedSource.feedType);
57+
5358
return (
5459
<>
5560
<Form>
@@ -77,15 +82,33 @@ function FeedSourceForm({
7782
value={feedSource.description}
7883
onChange={handleInput}
7984
/>
80-
<FormSelect
81-
name="feedType"
82-
formGroupClasses="mb-2"
83-
label={t("feed-source-feed-type-label")}
84-
value={feedSource.feedType}
85-
onChange={onFeedTypeChange}
86-
disabled={mode === "PUT"}
87-
options={feedSourceTypeOptions}
88-
/>
85+
{typeInOptions && (
86+
<FormSelect
87+
name="feedType"
88+
formGroupClasses="mb-2"
89+
label={t("feed-source-feed-type-label")}
90+
value={feedSource.feedType}
91+
onChange={onFeedTypeChange}
92+
disabled={mode === "PUT"}
93+
options={feedSourceTypeOptions}
94+
/>
95+
)}
96+
{!typeInOptions && (
97+
<>
98+
<FormInput
99+
name="title"
100+
formGroupClasses="mb-2"
101+
type="text"
102+
disabled
103+
label={t("feed-source-feed-type-label")}
104+
value={feedSource.feedType}
105+
onChange={() => {}}
106+
/>
107+
<Alert className="mt-4" variant="warning">
108+
{t("feed-type-not-supported")}
109+
</Alert>
110+
</>
111+
)}
89112

90113
{feedSource?.feedType === "App\\Feed\\CalendarApiFeedType" && (
91114
<CalendarApiFeedType
@@ -95,6 +118,14 @@ function FeedSourceForm({
95118
feedSourceId={feedSource["@id"]}
96119
/>
97120
)}
121+
{feedSource?.feedType === "App\\Feed\\ColiboFeedType" && (
122+
<ColiboFeedType
123+
handleInput={handleSecretInput}
124+
formStateObject={feedSource.secrets}
125+
mode={mode}
126+
feedSourceId={feedSource["@id"]}
127+
/>
128+
)}
98129
{feedSource?.feedType ===
99130
"App\\Feed\\EventDatabaseApiFeedType" && (
100131
<EventDatabaseApiFeedType

src/components/feed-sources/feed-source-manager.jsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,29 @@ function FeedSourceManager({
6161
] = usePutV2FeedSourcesByIdMutation();
6262

6363
const feedSourceTypeOptions = [
64+
{
65+
value: "App\\Feed\\CalendarApiFeedType",
66+
title: t("dynamic-fields.calendar-api-feed-type.title"),
67+
key: "0",
68+
secretsDefault: {
69+
locations: [],
70+
},
71+
},
72+
{
73+
value: "App\\Feed\\ColiboFeedType",
74+
title: t("colibo-feed-type.title"),
75+
key: "1",
76+
secretsDefault: {
77+
api_base_uri: "",
78+
client_id: "",
79+
client_secret: "",
80+
recipients: [],
81+
},
82+
},
6483
{
6584
value: "App\\Feed\\EventDatabaseApiFeedType",
6685
title: t("dynamic-fields.event-database-api-feed-type.title"),
67-
key: "1",
86+
key: "2",
6887
secretsDefault: {
6988
host: "",
7089
},
@@ -81,19 +100,11 @@ function FeedSourceManager({
81100
{
82101
value: "App\\Feed\\NotifiedFeedType",
83102
title: t("dynamic-fields.notified-feed-type.title"),
84-
key: "2",
103+
key: "3",
85104
secretsDefault: {
86105
token: "",
87106
},
88107
},
89-
{
90-
value: "App\\Feed\\CalendarApiFeedType",
91-
title: t("dynamic-fields.calendar-api-feed-type.title"),
92-
key: "0",
93-
secretsDefault: {
94-
locations: [],
95-
},
96-
},
97108
{
98109
value: "App\\Feed\\RssFeedType",
99110
title: t("dynamic-fields.rss-feed-type.title"),
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { React, useEffect, useState } from "react";
2+
import PropTypes from "prop-types";
3+
import { useTranslation } from "react-i18next";
4+
import { Alert } from "react-bootstrap";
5+
import MultiselectFromEndpoint from "../../slide/content/multiselect-from-endpoint";
6+
import ConfigLoader from "../../../config-loader";
7+
import FormInput from "../../util/forms/form-input";
8+
9+
const ColiboFeedType = ({
10+
feedSourceId,
11+
handleInput,
12+
formStateObject,
13+
mode,
14+
}) => {
15+
const { t } = useTranslation("common", {
16+
keyPrefix: "colibo-feed-type",
17+
});
18+
19+
const [optionsEndpoint, setOptionsEndpoint] = useState(null);
20+
21+
useEffect(() => {
22+
if (feedSourceId && feedSourceId !== "") {
23+
ConfigLoader.loadConfig().then((config) => {
24+
let endpoint = config.api;
25+
endpoint = endpoint.replace(/\/$/, "");
26+
endpoint += feedSourceId;
27+
endpoint += "/config/recipients";
28+
29+
setOptionsEndpoint(endpoint);
30+
});
31+
}
32+
}, [feedSourceId]);
33+
34+
return (
35+
<>
36+
{!feedSourceId && (
37+
<Alert className="mt-4" variant="warning">
38+
{t("save-before-recipients-can-be-set")}
39+
</Alert>
40+
)}
41+
42+
<FormInput
43+
name="api_base_uri"
44+
type="text"
45+
label={t("api-base-uri")}
46+
className="mb-2"
47+
onChange={handleInput}
48+
placeholder={
49+
mode === "PUT" ? t("redacted-value-input-placeholder") : ""
50+
}
51+
value={formStateObject?.api_base_uri}
52+
/>
53+
54+
<FormInput
55+
name="client_id"
56+
type="text"
57+
className="mb-2"
58+
label={t("client-id")}
59+
onChange={handleInput}
60+
placeholder={
61+
mode === "PUT" ? t("redacted-value-input-placeholder") : ""
62+
}
63+
value={formStateObject?.client_id}
64+
/>
65+
66+
<FormInput
67+
name="client_secret"
68+
type="text"
69+
label={t("client-secret")}
70+
onChange={handleInput}
71+
placeholder={
72+
mode === "PUT" ? t("redacted-value-input-placeholder") : ""
73+
}
74+
value={formStateObject?.client_secret}
75+
/>
76+
77+
<Alert className="mt-4" variant="info">
78+
{t("values-info")}
79+
</Alert>
80+
81+
{optionsEndpoint && (
82+
<MultiselectFromEndpoint
83+
onChange={handleInput}
84+
name="allowed_recipients"
85+
disableSearch={false}
86+
label={t("allowed-recipients")}
87+
value={formStateObject.allowed_recipients ?? []}
88+
optionsEndpoint={optionsEndpoint}
89+
helpText={t("allowed-recipients-help")}
90+
/>
91+
)}
92+
</>
93+
);
94+
};
95+
96+
ColiboFeedType.propTypes = {
97+
handleInput: PropTypes.func,
98+
formStateObject: PropTypes.shape({
99+
api_base_uri: PropTypes.string,
100+
client_id: PropTypes.string,
101+
client_secret: PropTypes.string,
102+
allowed_recipients: PropTypes.arrayOf(PropTypes.string),
103+
}),
104+
feedSourceId: PropTypes.string,
105+
mode: PropTypes.string,
106+
};
107+
108+
export default ColiboFeedType;

src/components/slide/content/content-form.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function ContentForm({
7272
}
7373

7474
returnElement = (
75-
<div key={formData.key}>
75+
<div key={formData.key} className={formData.formGroupClasses}>
7676
{formData?.label && (
7777
<label htmlFor={formData.name} className="form-label">
7878
{formData.label}
@@ -123,7 +123,7 @@ function ContentForm({
123123
errors={formData.required ? errors : null}
124124
label={formData.label}
125125
helpText={formData.helpText}
126-
value={formStateObject[formData.name]}
126+
value={formStateObject[formData.name] ?? formData?.defaultValue}
127127
onChange={onChange}
128128
formGroupClasses={formData.formGroupClasses}
129129
/>

src/components/slide/content/feed-selector.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ function FeedSelector({
134134
value={getValueFromConfiguration(element.name)}
135135
label={element.label}
136136
optionsEndpoint={element.endpoint}
137-
singleSelect={formElement.singleSelect ?? false}
137+
disableSearch={element.disableSearch ?? false}
138+
singleSelect={element.singleSelect ?? false}
139+
helpText={element.helpText ?? null}
138140
/>
139141
);
140142
}

src/components/slide/content/multiselect-from-endpoint.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { displayError } from "../../util/list/toast-component/display-toast";
1616
* @param {string} props.optionsEndpoint - Endpoint from which to fetch the options.
1717
* @param {boolean} props.singleSelect - Allow only to select one option.
1818
* @param {boolean} props.disableSearch - Disable search. Defaults to true.
19+
* @param {string | null} props.helpText - Help text.
1920
* @returns {object} - The FeedSelector component.
2021
*/
2122
function MultiselectFromEndpoint({
@@ -26,6 +27,7 @@ function MultiselectFromEndpoint({
2627
value = [],
2728
disableSearch = true,
2829
singleSelect = false,
30+
helpText = null,
2931
}) {
3032
const { t } = useTranslation("common");
3133
const [options, setOptions] = useState(null);
@@ -98,6 +100,7 @@ function MultiselectFromEndpoint({
98100
}}
99101
filterCallback={() => {}}
100102
label={label ?? t("multiselect.select")}
103+
helpText={helpText}
101104
/>
102105
)}
103106
</>
@@ -112,6 +115,7 @@ MultiselectFromEndpoint.propTypes = {
112115
optionsEndpoint: PropTypes.string.isRequired,
113116
singleSelect: PropTypes.bool,
114117
disableSearch: PropTypes.bool,
118+
helpText: PropTypes.string,
115119
};
116120

117121
export default MultiselectFromEndpoint;

src/translations/da/common.json

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@
282282
"save-feed-source-error": "Der skete en fejl da feed source skulle gemmes:",
283283
"load-feed-source-error": "Der skete en fejl da feed source med følgende id: {{id}} skulle hentes:"
284284
},
285+
"colibo-feed-type": {
286+
"title": "Colibo"
287+
},
285288
"dynamic-fields": {
286289
"event-database-api-feed-type": {
287290
"title": "Eventdatabase API",
@@ -294,13 +297,13 @@
294297
"redacted-value-input-placeholder": "Skjult værdi"
295298
},
296299
"calendar-api-feed-type": {
297-
"title": "Kalender feed",
300+
"title": "Kalender",
298301
"locations": "Lokationer",
299302
"redacted-value-input-placeholder": "Skjult værdi",
300303
"save-before-locations-can-be-set": "Bemærk! Datakilden skal gemmes før der kan tilkobles lokationer. Gem og åbn datakilden igen."
301304
},
302305
"rss-feed-type": {
303-
"title": "RSS feed"
306+
"title": "RSS"
304307
}
305308
},
306309
"event-database-api-v2-feed-type": {
@@ -311,6 +314,7 @@
311314
"feed-source-name-label": "Navn",
312315
"feed-source-description-label": "Beskrivelse",
313316
"feed-source-feed-type-label": "Type",
317+
"feed-type-not-supported": "Typen understøttes ikke af administrationen.",
314318
"save-button": "Gem datakilde og luk",
315319
"save-without-close-button": "Gem datakilde",
316320
"cancel-button": "Annuller"
@@ -1138,6 +1142,17 @@
11381142
"future": "Fremtidig",
11391143
"expired": "Udløbet"
11401144
},
1145+
"colibo-feed-type": {
1146+
"title": "Colibo feed",
1147+
"api-base-uri": "API Base URI",
1148+
"client-id": "Client ID",
1149+
"client-secret": "Client Secret",
1150+
"values-info": "Værdierne Client ID og Client Secret findes ved at oprette en API klient i \"Systemadministration\" -> \"API adgangshåndtering\" i Colibo intranet.",
1151+
"allowed-recipients": "Tilladte modtagergrupper",
1152+
"redacted-value-input-placeholder": "Skjult værdi",
1153+
"save-before-recipients-can-be-set": "Bemærk! Datakilden skal gemmes før der kan tilkobles tilladte modtagergrupper. Gem og åbn datakilden igen.",
1154+
"allowed-recipients-help": "Det er kun disse modtagergrupper, der vil være tilgængelige, når man opretter et slide, der bruger datakilden."
1155+
},
11411156
"event-database-api-v2-feed-type": {
11421157
"title": "Event databasen v.2",
11431158
"host": "Host",

0 commit comments

Comments
 (0)