@rh-support/manage 2.1.97 → 2.1.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { Trans } from 'react-i18next';
3
3
  export default function ExpiredContentHeader() {
4
4
  return (React.createElement("header", null,
5
5
  React.createElement("h2", null,
6
- React.createElement(Trans, null, "Outdated Content")),
6
+ React.createElement(Trans, null, "Expired Content")),
7
7
  React.createElement("p", { className: "pf-v5-u-mt-md pf-v5-u-mb-sm" },
8
8
  React.createElement(Trans, null))));
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ExpiredContentSingleItemView.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentSingleItemView.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAI7D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAIjG,UAAU,MAAM;IACZ,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAAC,EACjD,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,GACb,EAAE,MAAM,qBAmNR"}
1
+ {"version":3,"file":"ExpiredContentSingleItemView.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentSingleItemView.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAIhF,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAIjG,UAAU,MAAM;IACZ,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAAC,EACjD,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,GACb,EAAE,MAAM,qBAoQR"}
@@ -9,11 +9,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { Button, DatePicker, Flex, FlexItem, FormGroup, TextInput, ValidatedOptions } from '@patternfly/react-core';
11
11
  import { TagsSelector, ToastNotification } from '@rh-support/components';
12
- import { getDrupalResIdIfTypeFromUrl, getText, isValidDate, isValidUrl } from '@rh-support/utils';
12
+ import { getDrupalResIdIfTypeFromUrl, getText, isFutureDate, isValidDate, isValidUrl } from '@rh-support/utils';
13
13
  import { isEqual } from 'lodash';
14
14
  import differenceBy from 'lodash/differenceBy';
15
15
  import isEmpty from 'lodash/isEmpty';
16
- import React, { useContext, useMemo, useState } from 'react';
16
+ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
17
17
  import { Trans, useTranslation } from 'react-i18next';
18
18
  import { TagManagementStateContext } from '../../context/TagManagementContextProvider';
19
19
  import { getTopContentUrl } from '../../reducers/TopContentHelpers';
@@ -23,15 +23,19 @@ export default function ExpiredContentSingleItemView({ category, content, onCanc
23
23
  const { t } = useTranslation();
24
24
  const tagManagementEditState = useContext(TagManagementStateContext);
25
25
  const { tags: tagOptions } = tagManagementEditState;
26
+ const ref = useRef(null);
26
27
  const [isFetchingSolrSearch, setIsFetchingSolrSearch] = useState(false);
27
28
  const [localContentUrl, setLocalContentUrl] = useState(content.contentUrl);
28
29
  const [localContentTitle, setLocalContentTitle] = useState(content.contentTitle);
29
30
  const [localSelectedTags, setLocalSelectedTags] = useState(content.tags || []);
30
31
  const [localExpiryDate, setLocalExpiryDate] = useState((content === null || content === void 0 ? void 0 : content.expiryDate) || '');
32
+ const [shouldShowExpDateErr, setShouldShowExpDateErr] = useState(false);
33
+ const [datePickerFocused, setDatePickerFocused] = useState(false);
31
34
  const [contentTitleIsValid, setContentTitleIsValid] = useState(true);
32
35
  const [contentUrlIsValid, setContentUrlIsValid] = useState(true);
33
36
  const oldTagsIds = useMemo(() => { var _a; return ((_a = content === null || content === void 0 ? void 0 : content.tags) === null || _a === void 0 ? void 0 : _a.map((t) => t.id)) || []; }, [content === null || content === void 0 ? void 0 : content.tags]);
34
37
  const localTagsIds = useMemo(() => localSelectedTags === null || localSelectedTags === void 0 ? void 0 : localSelectedTags.map((t) => t.id), [localSelectedTags]);
38
+ const expiryDateErrMsg = isFutureDate(localExpiryDate) ? '' : t('Invalid expiry date');
35
39
  const onSubmit = (e) => e.preventDefault();
36
40
  const updateContentTitleFromUrl = (contentUrl) => __awaiter(this, void 0, void 0, function* () {
37
41
  var _c, _d;
@@ -108,27 +112,60 @@ export default function ExpiredContentSingleItemView({ category, content, onCanc
108
112
  localContentTitle === content.contentTitle &&
109
113
  isEqual(localTagsIds, oldTagsIds) &&
110
114
  isEqual(localExpiryDate.split('T')[0], ((_b = content.expiryDate) === null || _b === void 0 ? void 0 : _b.split('T')[0]) || ''));
111
- return (React.createElement("form", { noValidate: true, onSubmit: onSubmit, className: "card card-light push-bottom" },
115
+ useEffect(() => {
116
+ var _a, _b;
117
+ const datePickerElement = (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.querySelector('#content-expiry-date input');
118
+ const tagsSelectorElement = (_b = ref === null || ref === void 0 ? void 0 : ref.current) === null || _b === void 0 ? void 0 : _b.querySelector('#expired-content-tag');
119
+ const handleFocusOnDatePicker = () => {
120
+ setDatePickerFocused(true);
121
+ };
122
+ const handleTagSelectorClick = () => {
123
+ !shouldShowExpDateErr && setShouldShowExpDateErr(true);
124
+ };
125
+ if (datePickerElement) {
126
+ datePickerElement.addEventListener('focusin', handleFocusOnDatePicker);
127
+ }
128
+ if (tagsSelectorElement) {
129
+ tagsSelectorElement.addEventListener('click', handleTagSelectorClick);
130
+ }
131
+ return () => {
132
+ if (datePickerElement) {
133
+ datePickerElement.removeEventListener('focusin', handleFocusOnDatePicker);
134
+ }
135
+ if (tagsSelectorElement) {
136
+ tagsSelectorElement.removeEventListener('click', handleTagSelectorClick);
137
+ }
138
+ };
139
+ // eslint-disable-next-line react-hooks/exhaustive-deps
140
+ }, []);
141
+ return (React.createElement("form", { noValidate: true, onSubmit: onSubmit, className: "card card-light push-bottom", ref: ref },
112
142
  React.createElement("div", { className: "form-group" },
113
143
  React.createElement("label", { htmlFor: localContentTitle },
114
144
  "Heading",
115
145
  ' ',
116
146
  React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
117
- React.createElement(TextInput, { isRequired: true, type: "text", maxLength: 254, required: true, value: localContentTitle, isDisabled: isFetchingSolrSearch, "aria-label": t('Copy and paste the heading for consistency'), placeholder: t('Copy and paste the heading for consistency'), onChange: (e, v) => onContentTitleChange(v, e), validated: contentTitleIsValid ? ValidatedOptions.default : ValidatedOptions.error })),
147
+ React.createElement(TextInput, { isRequired: true, type: "text", maxLength: 254, required: true, value: localContentTitle, isDisabled: isFetchingSolrSearch, "aria-label": t('Copy and paste the heading for consistency'), placeholder: t('Copy and paste the heading for consistency'), onFocus: () => setShouldShowExpDateErr(true), onChange: (e, v) => {
148
+ onContentTitleChange(v, e);
149
+ !shouldShowExpDateErr && setShouldShowExpDateErr(true);
150
+ }, validated: contentTitleIsValid ? ValidatedOptions.default : ValidatedOptions.error })),
118
151
  React.createElement("div", { className: "form-group" },
119
152
  React.createElement("label", { htmlFor: localContentUrl },
120
153
  "Link to content",
121
154
  ' ',
122
155
  React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
123
- React.createElement(TextInput, { type: "url", maxLength: 254, isRequired: true, pattern: "^(http(s)?:\\/\\/)+[\\w\\-\\._~:\\/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", value: getTopContentUrl(localContentUrl), "aria-label": t('Entering a solution or article link first will automatically generate the heading for you'), placeholder: t('Entering a solution or article link first will automatically generate the heading for you'), onChange: (evt, val) => onContentUrlChange(val, evt), validated: contentUrlIsValid ? ValidatedOptions.default : ValidatedOptions.error })),
156
+ React.createElement(TextInput, { type: "url", maxLength: 254, isRequired: true, pattern: "^(http(s)?:\\/\\/)+[\\w\\-\\._~:\\/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", value: getTopContentUrl(localContentUrl), "aria-label": t('Entering a solution or article link first will automatically generate the heading for you'), placeholder: t('Entering a solution or article link first will automatically generate the heading for you'), onFocus: () => setShouldShowExpDateErr(true), onChange: (evt, val) => {
157
+ onContentUrlChange(val, evt);
158
+ !shouldShowExpDateErr && setShouldShowExpDateErr(true);
159
+ }, validated: contentUrlIsValid ? ValidatedOptions.default : ValidatedOptions.error })),
124
160
  React.createElement(Flex, { className: "pf-v5-u-my-lg" },
125
161
  React.createElement(FlexItem, { flex: { default: 'flex_1' } },
126
162
  React.createElement(FormGroup, { label: t('Tags') },
127
163
  React.createElement("div", { className: "pf-v5-c-form-control" },
128
- React.createElement(TagsSelector, { tagOptions: tagOptions, onChange: handleLocalTagChange, selectedTags: localSelectedTags, placeholder: t('Select tags to improve discoverability') })))),
164
+ React.createElement(TagsSelector, { tagOptions: tagOptions, onChange: handleLocalTagChange, selectedTags: localSelectedTags, placeholder: t('Select tags to improve discoverability'), id: "expired-content-tag" })))),
129
165
  React.createElement(FlexItem, null,
130
166
  React.createElement(FormGroup, { label: t('Expiry date') },
131
- React.createElement(DatePicker, { onBlur: onExpiryDateChange, onChange: onExpiryDateChange, value: !isEmpty(localExpiryDate) ? localExpiryDate.split('T')[0] : '', validators: [expiryDateValidator] })))),
167
+ React.createElement(DatePicker, { onBlur: onExpiryDateChange, onChange: onExpiryDateChange, value: !isEmpty(localExpiryDate) ? localExpiryDate.split('T')[0] : '', validators: [expiryDateValidator], id: "content-expiry-date", invalidFormatText: t('Invalid date format') }),
168
+ shouldShowExpDateErr && !datePickerFocused && (React.createElement("p", { className: "form-instructions form-invalid pf-v5-u-font-size-sm pf-v5-u-danger-color-200 pf-v5-u-my-0" }, expiryDateErrMsg))))),
132
169
  React.createElement("span", { className: "top-content-single-item-footer" },
133
170
  React.createElement("span", null,
134
171
  React.createElement(Button, { variant: "primary", onClick: onContentSave, isDisabled: isSaveButtonDisabled || isSaving, isLoading: isSaving },
@@ -1 +1 @@
1
- {"version":3,"file":"TopContentSingleItem.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAiB,aAAa,EAAE,MAAM,0CAA0C,CAAC;AA8BtG,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAM7D,OAAO,EAIH,oBAAoB,EAOvB,MAAM,wCAAwC,CAAC;AAIhD,UAAU,MAAM;IACZ,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,sBAAsB,CAAC,GAAG,KAAA,OASzC;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,6CA2B/C;AAED,eAAO,MAAM,oBAAoB,kDAAmD,MAAM,sBA+ezF,CAAC"}
1
+ {"version":3,"file":"TopContentSingleItem.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAiB,aAAa,EAAE,MAAM,0CAA0C,CAAC;AA8BtG,OAAO,KAA2D,MAAM,OAAO,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAM7D,OAAO,EAIH,oBAAoB,EAOvB,MAAM,wCAAwC,CAAC;AAIhD,UAAU,MAAM;IACZ,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,sBAAsB,CAAC,GAAG,KAAA,OASzC;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,6CA2B/C;AAED,eAAO,MAAM,oBAAoB,kDAAmD,MAAM,sBAmiBzF,CAAC"}
@@ -18,7 +18,7 @@ import { differenceBy, isEqual } from 'lodash';
18
18
  import cloneDeep from 'lodash/cloneDeep';
19
19
  import findIndex from 'lodash/findIndex';
20
20
  import isEmpty from 'lodash/isEmpty';
21
- import React, { useContext, useEffect, useMemo, useState } from 'react';
21
+ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
22
22
  import { Trans, useTranslation } from 'react-i18next';
23
23
  import { TagManagementStateContext } from '../../../../context/TagManagementContextProvider';
24
24
  import { useTopContentContext, useTopContentDispatchContext } from '../../../../context/TopContentProvider';
@@ -77,6 +77,7 @@ export const TopContentSingleItem = ({ isArrangingContent, category, snapshot, i
77
77
  const { topContentEditState, isCatOnlyForMajorVersion, selectedProduct, selectedVersion, contentUrls, filteredTags, } = useTopContentContext();
78
78
  const tagManagementEditState = useContext(TagManagementStateContext);
79
79
  const { tags: tagOptions } = tagManagementEditState;
80
+ const ref = useRef(null);
80
81
  const topContentDispatch = useTopContentDispatchContext();
81
82
  const [localContentUrl, setLocalContentUrl] = useState(content.contentUrl);
82
83
  const [localContentTitle, setLocalContentTitle] = useState(content.contentTitle);
@@ -88,10 +89,13 @@ export const TopContentSingleItem = ({ isArrangingContent, category, snapshot, i
88
89
  const [showDuplicateError, setShowDuplicateError] = useState(false);
89
90
  const [duplicatUrlErrorArray, setDuplicatUrlErrorArray] = useState([]);
90
91
  const [isSaving, setIsSaving] = useState(false);
92
+ const [shouldShowExpDateErr, setShouldShowExpDateErr] = useState(false);
93
+ const [datePickerFocused, setDatePickerFocused] = useState(false);
91
94
  const duplicateTitleCategoryIndex = findIndex(category.content, (c) => c.contentTitle === localContentTitle.trim());
92
95
  const isDuplicateTitle = duplicateTitleCategoryIndex !== -1 && duplicateTitleCategoryIndex !== i && !isEmpty(localContentTitle.trim());
93
96
  const oldTagsIds = useMemo(() => { var _a; return ((_a = content === null || content === void 0 ? void 0 : content.tags) === null || _a === void 0 ? void 0 : _a.map((t) => t.id)) || []; }, [content === null || content === void 0 ? void 0 : content.tags]);
94
97
  const localTagsIds = useMemo(() => localSelectedTags === null || localSelectedTags === void 0 ? void 0 : localSelectedTags.map((t) => t.id), [localSelectedTags]);
98
+ const expiryDateErrMsg = isEmpty(localExpiryDate) || isFutureDate(localExpiryDate) ? '' : t('Invalid expiry date');
95
99
  const onContentTitleChange = (contentTitle, event) => {
96
100
  const contentTitleIsValid = event.target.validity.valid;
97
101
  setContentTitleIsValid(contentTitleIsValid);
@@ -293,6 +297,34 @@ export const TopContentSingleItem = ({ isArrangingContent, category, snapshot, i
293
297
  setLocalSelectedTags(content.tags || []);
294
298
  setLocalExpiryDate((_a = content.expiryDate) !== null && _a !== void 0 ? _a : '');
295
299
  }, [content]);
300
+ useEffect(() => {
301
+ var _a, _b;
302
+ const datePickerElement = (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.querySelector('#content-expiry-date input');
303
+ const tagsSelectorElement = (_b = ref === null || ref === void 0 ? void 0 : ref.current) === null || _b === void 0 ? void 0 : _b.querySelector('#top-content-tag');
304
+ const handleFocusOnDatePicker = () => {
305
+ setDatePickerFocused(true);
306
+ };
307
+ const handleTagSelectorClick = () => {
308
+ !shouldShowExpDateErr && setShouldShowExpDateErr(true);
309
+ };
310
+ if (datePickerElement) {
311
+ datePickerElement.addEventListener('focusin', handleFocusOnDatePicker);
312
+ }
313
+ if (tagsSelectorElement) {
314
+ tagsSelectorElement.addEventListener('click', handleTagSelectorClick);
315
+ }
316
+ return () => {
317
+ if (datePickerElement) {
318
+ datePickerElement.removeEventListener('focusin', handleFocusOnDatePicker);
319
+ }
320
+ if (tagsSelectorElement) {
321
+ tagsSelectorElement.removeEventListener('click', handleTagSelectorClick);
322
+ }
323
+ setDatePickerFocused(false);
324
+ setShouldShowExpDateErr(false);
325
+ };
326
+ // eslint-disable-next-line react-hooks/exhaustive-deps
327
+ }, [isPreview]);
296
328
  // To check if input has spaces
297
329
  const doesInputHasSpaces = isEmpty(localContentTitle.trim());
298
330
  // To disable save button if empty depending on spaces
@@ -326,14 +358,17 @@ export const TopContentSingleItem = ({ isArrangingContent, category, snapshot, i
326
358
  (content.tags || []).map((tag) => (React.createElement(Label, { isCompact: true, className: "pf-v5-u-mr-xs pf-v5-u-mt-sm", key: tag.id, color: filteredTags.some((t) => t.id === tag.id) ? 'gold' : 'grey' }, tag.tagName))),
327
359
  !isEmpty((_c = content.expiryDate) !== null && _c !== void 0 ? _c : '') && !isFutureDate(content.expiryDate) && (React.createElement(Label, { isCompact: true, className: "pf-v5-u-mr-xs pf-v5-u-mt-sm", color: "red" },
328
360
  React.createElement(Trans, null, "Outdated Content")))))),
329
- (!isPreview || content.mode === ContentMode.ADD || content.mode === ContentMode.NEW_SECTION_CONTENT) && (React.createElement("form", { noValidate: true, onSubmit: onSubmit, className: "card card-light push-bottom" },
361
+ (!isPreview || content.mode === ContentMode.ADD || content.mode === ContentMode.NEW_SECTION_CONTENT) && (React.createElement("form", { noValidate: true, onSubmit: onSubmit, className: "card card-light push-bottom", ref: ref },
330
362
  content.mode === ContentMode.NEW_SECTION_CONTENT && (React.createElement(AddNewCategoryDropDown, { onCategoryChange: onAddedNewCategoryChange })),
331
363
  React.createElement("div", { className: "form-group" },
332
364
  React.createElement("label", { htmlFor: localContentTitle },
333
365
  "Heading",
334
366
  ' ',
335
367
  React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
336
- React.createElement(TextInput, { isRequired: true, type: "text", maxLength: 254, required: true, value: localContentTitle, isDisabled: isFetchingSolrSearch, "aria-label": t('Copy and paste the heading for consistency'), placeholder: t('Copy and paste the heading for consistency'), onChange: (e, v) => onContentTitleChange(v, e), validated: contentTitleIsValid && !isDuplicateTitle
368
+ React.createElement(TextInput, { isRequired: true, type: "text", maxLength: 254, required: true, value: localContentTitle, isDisabled: isFetchingSolrSearch, "aria-label": t('Copy and paste the heading for consistency'), placeholder: t('Copy and paste the heading for consistency'), onFocus: () => setShouldShowExpDateErr(true), onChange: (e, v) => {
369
+ onContentTitleChange(v, e);
370
+ !shouldShowExpDateErr && setShouldShowExpDateErr(true);
371
+ }, validated: contentTitleIsValid && !isDuplicateTitle
337
372
  ? ValidatedOptions.default
338
373
  : ValidatedOptions.error }),
339
374
  isDuplicateTitle && (React.createElement("p", { className: "form-instructions form-invalid " },
@@ -345,7 +380,10 @@ export const TopContentSingleItem = ({ isArrangingContent, category, snapshot, i
345
380
  "Link to content",
346
381
  ' ',
347
382
  React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
348
- React.createElement(TextInput, { type: "url", maxLength: 254, isRequired: true, pattern: "^(http(s)?:\\/\\/)+[\\w\\-\\._~:\\/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", value: getTopContentUrl(localContentUrl), "aria-label": t('Entering a solution or article link first will automatically generate the heading for you'), placeholder: t('Entering a solution or article link first will automatically generate the heading for you'), onChange: (evt, val) => onContentUrlChange(val, evt), validated: contentUrlIsValid ? ValidatedOptions.default : ValidatedOptions.error }),
383
+ React.createElement(TextInput, { type: "url", maxLength: 254, isRequired: true, pattern: "^(http(s)?:\\/\\/)+[\\w\\-\\._~:\\/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", value: getTopContentUrl(localContentUrl), "aria-label": t('Entering a solution or article link first will automatically generate the heading for you'), placeholder: t('Entering a solution or article link first will automatically generate the heading for you'), onFocus: () => setShouldShowExpDateErr(true), onChange: (evt, val) => {
384
+ onContentUrlChange(val, evt);
385
+ !shouldShowExpDateErr && setShouldShowExpDateErr(true);
386
+ }, validated: contentUrlIsValid ? ValidatedOptions.default : ValidatedOptions.error }),
349
387
  showDuplicateError && (React.createElement("p", { className: "form-instructions form-invalid" },
350
388
  React.createElement(ExclamationCircleIcon, { color: "#c9190b", className: "pf-v5-u-mr-sm" }),
351
389
  " Duplicate url. This url is already added in ",
@@ -355,10 +393,11 @@ export const TopContentSingleItem = ({ isArrangingContent, category, snapshot, i
355
393
  React.createElement(FlexItem, { flex: { default: 'flex_1' } },
356
394
  React.createElement(FormGroup, { label: t('Tags') },
357
395
  React.createElement("div", { className: "pf-v5-c-form-control" },
358
- React.createElement(TagsSelector, { tagOptions: tagOptions, onChange: handleLocalTagChange, selectedTags: localSelectedTags, placeholder: t('Select tags to improve discoverability') })))),
396
+ React.createElement(TagsSelector, { tagOptions: tagOptions, onChange: handleLocalTagChange, selectedTags: localSelectedTags, placeholder: t('Select tags to improve discoverability'), id: "top-content-tag" })))),
359
397
  React.createElement(FlexItem, null,
360
398
  React.createElement(FormGroup, { label: t('Expiry date') },
361
- React.createElement(DatePicker, { onBlur: onExpiryDateChange, onChange: onExpiryDateChange, value: !isEmpty(localExpiryDate) ? localExpiryDate.split('T')[0] : '', validators: [expiryDateValidator] })))),
399
+ React.createElement(DatePicker, { onBlur: onExpiryDateChange, onChange: onExpiryDateChange, value: !isEmpty(localExpiryDate) ? localExpiryDate.split('T')[0] : '', validators: [expiryDateValidator], id: "content-expiry-date", invalidFormatText: t('Invalid date format') }),
400
+ shouldShowExpDateErr && !datePickerFocused && (React.createElement("p", { className: "form-instructions form-invalid pf-v5-u-font-size-sm pf-v5-u-danger-color-200 pf-v5-u-my-0" }, expiryDateErrMsg))))),
362
401
  React.createElement("span", { className: "top-content-single-item-footer" },
363
402
  React.createElement("span", null,
364
403
  React.createElement(Button, { variant: "primary", onClick: onSave, isDisabled: isSaveButtonDisabled || isSaving, isLoading: isSaving },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rh-support/manage",
3
- "version": "2.1.97",
3
+ "version": "2.1.98",
4
4
  "description": "Customer Support Manage App",
5
5
  "author": "Jordan Eudy <jeudy100@gmail.com>",
6
6
  "license": "ISC",
@@ -79,9 +79,9 @@
79
79
  "@patternfly/patternfly": "5.1.0",
80
80
  "@patternfly/react-core": "5.1.1",
81
81
  "@patternfly/react-table": "5.1.1",
82
- "@rh-support/components": "2.1.74",
82
+ "@rh-support/components": "2.1.75",
83
83
  "@rh-support/configs": "2.0.20",
84
- "@rh-support/react-context": "2.1.83",
84
+ "@rh-support/react-context": "2.1.84",
85
85
  "@rh-support/types": "2.0.4",
86
86
  "@rh-support/user-permissions": "2.1.49",
87
87
  "@rh-support/utils": "2.1.38",
@@ -102,5 +102,5 @@
102
102
  "defaults and supports es6-module",
103
103
  "maintained node versions"
104
104
  ],
105
- "gitHead": "3097e71a53e46ed7d352a45068ae98657b59bf30"
105
+ "gitHead": "12904e607b35269b1d12cb8bd501200d8308bdaa"
106
106
  }