@topconsultnpm/sdkui-react-beta 6.7.21 → 6.7.23

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.
@@ -4,6 +4,7 @@ interface ITMListViewHeader {
4
4
  headerTitle?: string;
5
5
  firstCounter?: React.ReactNode;
6
6
  secondCounter?: React.ReactNode;
7
+ titleColor?: string;
7
8
  }
8
9
  interface ListProps<T> {
9
10
  dataSource?: T[];
@@ -7,6 +7,7 @@ import { IconApply, IconCloseCircle, IconColumns, IconDown, IconHide, IconShow,
7
7
  import { TMSearchBar } from '../sidebar/TMHeader';
8
8
  import TMTooltip from './TMTooltip';
9
9
  import { SDKUI_Localizator } from '../../helper';
10
+ import { TMColors } from '../../utils/theme';
10
11
  const StyledListItem = styled.div ` width: 100%; height: max-content; border-bottom: 1px solid #e5e5e5; background-color: ${props => props.$isSelected ? props.$color ? `${props.$color}99` : '#00000030' : 'transparent'} ; color: ${props => props.$isSelected ? props.$color ? 'white' : '#000000' : '#000000'} ; &:hover{ background-color: ${props => props.$color ? props.$isSelected ? `${props.$color}99` : `${props.$color}40` : props.$isSelected ? '#00000030' : '#00000010'};} `;
11
12
  const StyledListViewContainer = styled.div ` position: relative; display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; width: 100%; height: 100%; `;
12
13
  const StyledSearchContainer = styled.div ` width: 100%; height: max-content; padding: 5px; border-bottom: 1px solid #e5e5e5; display: flex; align-items: center; gap: 10px; `;
@@ -330,5 +331,5 @@ const TMListView = ({ customGroupingHeaders, headerBackGroundColor, header, show
330
331
  };
331
332
  export default TMListView;
332
333
  export const CustomListViewHeader = (props) => {
333
- return (_jsxs("div", { style: { display: 'flex', alignItems: 'center', padding: '0 5px', gap: 5 }, children: [props.headerIcon, _jsx("p", { children: props.headerTitle }), props.firstCounter, props.secondCounter] }));
334
+ return (_jsxs("div", { style: { display: 'flex', alignItems: 'center', padding: '0 5px', gap: 5 }, children: [props.headerIcon, _jsx("p", { style: { fontWeight: 'bold', color: props.titleColor ? props.titleColor : TMColors.text_normal }, children: props.headerTitle }), props.firstCounter, props.secondCounter] }));
334
335
  };
@@ -146,13 +146,13 @@ const TMLoginForm = (props) => {
146
146
  }
147
147
  }, []);
148
148
  useEffect(() => {
149
- const loginWidthEnterKey = (e) => { if (loginValidationItems.length === 0) {
149
+ const loginWidthEnterKey = (e) => { if (loginValidationItems.length === 0 && !popupSaveLoginInfoVisible) {
150
150
  if (e.key === 'Enter')
151
151
  login();
152
152
  } };
153
153
  window.addEventListener('keyup', loginWidthEnterKey);
154
154
  return () => window.removeEventListener('keyup', loginWidthEnterKey);
155
- }, [loginValidationItems]);
155
+ }, [loginValidationItems, popupSaveLoginInfoVisible]);
156
156
  // useEffect(() => { setEndpoint(props.endpoints[0]) }, [endpoints])
157
157
  useEffect(() => { setEndpoint(props.endpoints.find(ep => ep.isDefault)); }, [endpoints]);
158
158
  useEffect(() => { setTmServer(new TopMediaServer(endpoint?.URL)); }, [endpoint]);
@@ -844,7 +844,7 @@ const TMLoginForm = (props) => {
844
844
  _jsxs(_Fragment, { children: [_jsx(TMTextBox, { label: SDKUI_Localizator.Domain, icon: _jsx(IconWeb, {}), value: domainAlternative, onValueChanged: (e) => setDomainArternative(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'domain_alt') }), _jsx(TMTextBox, { validationItems: loginValidationItems.filter(item => item.PropertyName === 'username'), label: SDKUI_Localizator.UserName, icon: _jsx(IconUser, {}), value: username, onValueChanged: (e) => setUsername(e.target.value) }), _jsx(TMTextBox, { validationItems: loginValidationItems.filter(item => item.PropertyName === 'password'), type: "password", label: SDKUI_Localizator.Password, icon: _jsx(IconPassword, {}), value: password, onValueChanged: (e) => setPassword(e.target.value) })] })
845
845
  :
846
846
  _jsxs(_Fragment, { children: [_jsx(TMTextBox, { validationItems: loginValidationItems.filter(item => item.PropertyName === 'username'), label: SDKUI_Localizator.UserName, icon: _jsx(IconUser, {}), value: username, onValueChanged: (e) => setUsername(e.target.value) }), _jsx(TMLayoutItem, { children: _jsx(TMTextBox, { validationItems: loginValidationItems.filter(item => item.PropertyName === 'password'), type: "password", label: SDKUI_Localizator.Password, icon: _jsx(IconPassword, {}), value: password, onValueChanged: (e) => setPassword(e.target.value) }) })] }) }), authMode === AuthenticationModes.TopMediaOnBehalfOf && _jsx(TMLayoutItem, { children: _jsxs(TMLayoutContainer, { direction: "horizontal", children: [_jsx(TMLayoutItem, { children: _jsxs(TMLayoutContainer, { children: [_jsx(TMLayoutItem, { children: _jsx(TMTextBox, { validationItems: loginValidationItems.filter(item => item.PropertyName === 'username'), label: SDKUI_Localizator.UserName, icon: _jsx(IconUser, {}), value: username, onValueChanged: (e) => setUsername(e.target.value) }) }), _jsx(TMLayoutItem, { children: _jsx(TMTextBox, { validationItems: loginValidationItems.filter(item => item.PropertyName === 'password'), type: "password", label: SDKUI_Localizator.Password, icon: _jsx(IconPassword, {}), value: password, onValueChanged: (e) => setPassword(e.target.value) }) })] }) }), _jsx(TMLayoutItem, { children: _jsxs(TMLayoutContainer, { children: [_jsx(TMLayoutItem, { children: _jsx(TMTextBox, { label: SDKUI_Localizator.Domain, icon: _jsx(IconWeb, {}), value: domain, onValueChanged: (e) => setDomain(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'domain') }) }), _jsx(TMLayoutItem, { children: _jsx(TMTextBox, { label: SDKUI_Localizator.UserName, icon: _jsx(IconUser, {}), value: onBehalfUsername, onValueChanged: (e) => setOnBeHalfUsername(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'onBeHalfUsername') }) })] }) })] }) }), authMode !== AuthenticationModes.TopMediaOnBehalfOf ? _jsx(TMLayoutItem, { children: _jsx(TMDropDown, { dataSource: cultureIDsDataSource, icon: _jsx(IconLanguage, {}), label: SDKUI_Localizator.CultureID, onValueChanged: (e) => props.onChangeLanguage && props.onChangeLanguage(e.target.value), value: props.cultureID, validationItems: loginValidationItems.filter(item => item.PropertyName === 'cultureId') }) }) :
847
- _jsxs(TMLayoutContainer, { direction: "horizontal", children: [_jsx(TMLayoutItem, { children: _jsx(TMDropDown, { dataSource: cultureIDsDataSource, icon: _jsx(IconLanguage, {}), label: SDKUI_Localizator.CultureID, onValueChanged: (e) => props.onChangeLanguage && props.onChangeLanguage(e.target.value), value: props.cultureID, validationItems: loginValidationItems.filter(item => item.PropertyName === 'cultureId') }) }), _jsx(TMLayoutItem, { children: _jsx(TMTextBox, { type: "password", label: SDKUI_Localizator.Password, icon: _jsx(IconPassword, {}), value: onBeHalfPassword, onValueChanged: (e) => setOnBeHalfPassword(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'onBeHalfPassword') }) })] }), props.saveLoginHistoryToLocalStorage && _jsxs(TMLayoutItem, { children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', marginTop: 12 }, children: [_jsx("i", { style: { fontSize: 20 }, className: "dx-icon-save" }), _jsx(TMCheckBox, { elementStyle: { marginLeft: 5 }, labelPosition: "left", label: SDKUI_Localizator.RememberCredentials, value: saveLoginInfo, onValueChanged: () => { setSaveLoginInfo(prevSaveLoginInfo => !prevSaveLoginInfo); }, isModifiedWhen: saveLoginInfo })] }), saveLoginInfo && _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.EnterNameForAccess, icon: _jsx("i", { style: { fontSize: 20 }, className: "dx-icon-save" }), value: saveLoginInfoName, onValueChanged: (e) => setSaveLoginInfoName(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'saveLoginName') })] })] }) }) }) }), _jsxs(TMLayoutItem, { height: "fit-content", width: "fit-content", children: [props.saveLoginHistoryToLocalStorage && _jsx("p", { onClick: showPopupSaveLoginInfo, onKeyDown: (e) => { }, style: { marginTop: '10px', userSelect: 'none', cursor: 'pointer', color: TMColors.primary, textAlign: 'center', fontSize: '0.9rem' }, children: SDKUI_Localizator.SwitchUser }), authMode === AuthenticationModes.TopMedia && _jsxs("div", { children: [_jsx("p", { onClick: () => isPasswordChangeEnable() && setTogglePages({ recovery: false, change: true, archive: false, endpoint: false }), tabIndex: isPasswordChangeEnable() ? 0 : undefined, onKeyDown: (e) => e.code === 'Space' && setTogglePages({ recovery: false, change: true, archive: false, endpoint: false }), style: { marginTop: '10px', userSelect: 'none', cursor: isPasswordChangeEnable() ? 'pointer' : 'default', color: isPasswordChangeEnable() ? TMColors.primary : 'rgb(180,180,180)', textAlign: 'center', fontSize: '0.9rem' }, children: SDKUI_Localizator.ChangePassword }), _jsx("p", { tabIndex: isPasswordChangeEnable() ? 0 : undefined, onKeyDown: (e) => e.code === 'Space' && showRecoveryPassword(), onClick: () => isPasswordChangeEnable() && showRecoveryPassword(), style: { userSelect: 'none', marginTop: '10px', cursor: isPasswordChangeEnable() ? 'pointer' : 'default', color: isPasswordChangeEnable() ? TMColors.primary : 'rgb(180,180,180)', fontSize: '0.9rem' }, children: SDKUI_Localizator.ForgetPassword })] })] }), _jsx(TMLayoutItem, { height: "fit-content", children: _jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px 0' }, children: _jsx(TMButton, { width: calcResponsiveSizes(deviceType, '150px', '150px', '250px'), height: calcResponsiveSizes(deviceType, '30px', '40px', '40px'), fontSize: "1.1rem", caption: "Login", disabled: loginValidationItems.length > 0, onClick: login, showTooltip: false }) }) })] }) })] })] }), _jsx(TMLoginPopupSaveLoginInfo, { visible: popupSaveLoginInfoVisible, hidePopup: hidePopupSaveLoginInfo, loginHistory: loginHistory, setLoginHistory: setLoginHistory, setEndpoint: setEndpoint, setArchive: setArchive, setAuthMode: setAuthMode, setUsername: setUsername, setPassword: setPassword, setDomain: setDomain, setDomainArternative: setDomainArternative, setOnBeHalfUsername: setOnBeHalfUsername, setOnBeHalfPassword: setOnBeHalfPassword, onChangeLanguage: onChangeLanguage })] }));
847
+ _jsxs(TMLayoutContainer, { direction: "horizontal", children: [_jsx(TMLayoutItem, { children: _jsx(TMDropDown, { dataSource: cultureIDsDataSource, icon: _jsx(IconLanguage, {}), label: SDKUI_Localizator.CultureID, onValueChanged: (e) => props.onChangeLanguage && props.onChangeLanguage(e.target.value), value: props.cultureID, validationItems: loginValidationItems.filter(item => item.PropertyName === 'cultureId') }) }), _jsx(TMLayoutItem, { children: _jsx(TMTextBox, { type: "password", label: SDKUI_Localizator.Password, icon: _jsx(IconPassword, {}), value: onBeHalfPassword, onValueChanged: (e) => setOnBeHalfPassword(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'onBeHalfPassword') }) })] }), props.saveLoginHistoryToLocalStorage && _jsxs(TMLayoutItem, { children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', marginTop: 12 }, children: [_jsx("i", { style: { fontSize: 20 }, className: "dx-icon-save" }), _jsx(TMCheckBox, { elementStyle: { marginLeft: 5 }, labelPosition: "left", label: SDKUI_Localizator.RememberCredentials, value: saveLoginInfo, onValueChanged: () => { setSaveLoginInfo(prevSaveLoginInfo => !prevSaveLoginInfo); }, isModifiedWhen: saveLoginInfo })] }), saveLoginInfo && _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.EnterNameForAccess, icon: _jsx("i", { style: { fontSize: 20 }, className: "dx-icon-save" }), value: saveLoginInfoName, onValueChanged: (e) => setSaveLoginInfoName(e.target.value), validationItems: loginValidationItems.filter(item => item.PropertyName === 'saveLoginName') })] })] }) }) }) }), _jsxs(TMLayoutItem, { height: "fit-content", width: "fit-content", children: [props.saveLoginHistoryToLocalStorage && _jsx("p", { onClick: showPopupSaveLoginInfo, onKeyDown: (e) => { }, style: { marginTop: '10px', userSelect: 'none', cursor: 'pointer', color: TMColors.primary, textAlign: 'center', fontSize: '0.9rem' }, children: SDKUI_Localizator.SwitchUser }), authMode === AuthenticationModes.TopMedia && _jsxs("div", { children: [_jsx("p", { onClick: () => isPasswordChangeEnable() && setTogglePages({ recovery: false, change: true, archive: false, endpoint: false }), tabIndex: isPasswordChangeEnable() ? 0 : undefined, onKeyDown: (e) => e.code === 'Space' && setTogglePages({ recovery: false, change: true, archive: false, endpoint: false }), style: { marginTop: '10px', userSelect: 'none', cursor: isPasswordChangeEnable() ? 'pointer' : 'default', color: isPasswordChangeEnable() ? TMColors.primary : 'rgb(180,180,180)', textAlign: 'center', fontSize: '0.9rem' }, children: SDKUI_Localizator.ChangePassword }), _jsx("p", { tabIndex: isPasswordChangeEnable() ? 0 : undefined, onKeyDown: (e) => e.code === 'Space' && showRecoveryPassword(), onClick: () => isPasswordChangeEnable() && showRecoveryPassword(), style: { userSelect: 'none', marginTop: '10px', cursor: isPasswordChangeEnable() ? 'pointer' : 'default', color: isPasswordChangeEnable() ? TMColors.primary : 'rgb(180,180,180)', fontSize: '0.9rem' }, children: SDKUI_Localizator.ForgetPassword })] })] }), _jsx(TMLayoutItem, { height: "fit-content", children: _jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px 0' }, children: _jsx(TMButton, { width: calcResponsiveSizes(deviceType, '150px', '150px', '250px'), height: calcResponsiveSizes(deviceType, '30px', '40px', '40px'), fontSize: "1.1rem", caption: "Login", disabled: loginValidationItems.length > 0, onClick: login, showTooltip: false }) }) })] }) })] })] }), _jsx(TMLoginPopupSaveLoginInfo, { visible: popupSaveLoginInfoVisible, hidePopup: hidePopupSaveLoginInfo, setLoginHistory: setLoginHistory, setEndpoint: setEndpoint, setArchive: setArchive, setAuthMode: setAuthMode, setUsername: setUsername, setPassword: setPassword, setDomain: setDomain, setDomainArternative: setDomainArternative, setOnBeHalfUsername: setOnBeHalfUsername, setOnBeHalfPassword: setOnBeHalfPassword, onChangeLanguage: onChangeLanguage })] }));
848
848
  };
849
849
  const TMPasswordManager = ({ validationItems = [], operation = 'change' }) => {
850
850
  const passwordStrength = () => {
@@ -2,7 +2,6 @@ import React from "react";
2
2
  import { ITMLoginHistory, TMEndpointsType } from "./TMLoginForm";
3
3
  import { ArchiveDescriptor, AuthenticationModes, CultureIDs } from "@topconsultnpm/sdk-ts-beta";
4
4
  interface TMLoginPopupSaveLoginInfoProps {
5
- loginHistory: Array<ITMLoginHistory>;
6
5
  setLoginHistory: React.Dispatch<React.SetStateAction<Array<ITMLoginHistory>>>;
7
6
  visible: boolean;
8
7
  hidePopup: () => void;
@@ -19,3 +18,12 @@ interface TMLoginPopupSaveLoginInfoProps {
19
18
  }
20
19
  declare const TMLoginPopupSaveLoginInfo: (props: TMLoginPopupSaveLoginInfoProps) => import("react/jsx-runtime").JSX.Element;
21
20
  export default TMLoginPopupSaveLoginInfo;
21
+ interface TMLoginItemTemplateProps {
22
+ data: ITMLoginHistory;
23
+ reloadHistoryState: () => void;
24
+ fillLoginForm: (data: ITMLoginHistory) => void;
25
+ deleteItemFromLocalStorage: (name: string) => void;
26
+ setSelectedItems: React.Dispatch<React.SetStateAction<ITMLoginHistory[]>>;
27
+ setSearchText: React.Dispatch<React.SetStateAction<string>>;
28
+ }
29
+ export declare const TMLoginItemTemplate: React.FC<TMLoginItemTemplateProps>;
@@ -1,69 +1,82 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
- import { Accordion, LoadIndicator, Popup, ScrollView } from "devextreme-react";
3
+ import { Accordion, LoadIndicator, Popup } from "devextreme-react";
4
4
  import { cultureIDsDataSource, LOGIN_HISTORY_KEY, } from "./TMLoginForm";
5
- import { LocalStorageService } from "@topconsultnpm/sdk-ts-beta";
5
+ import { LocalStorageService, ResultTypes, SDK_Localizator, ValidationItem } from "@topconsultnpm/sdk-ts-beta";
6
6
  import { Item } from "devextreme-react/cjs/accordion";
7
7
  import { SDKUI_Localizator } from "../../helper/SDKUI_Localizator";
8
8
  import { ButtonNames, TMExceptionBoxManager, TMMessageBoxManager } from "../base/TMPopUp";
9
9
  import TMTooltip from "../base/TMTooltip";
10
10
  import TMTextBox from "../editors/TMTextBox";
11
+ import { TMSearchBar } from "../sidebar/TMHeader";
11
12
  const TMLoginPopupSaveLoginInfo = (props) => {
12
- const { loginHistory, setLoginHistory, visible, hidePopup, setEndpoint, setArchive, setAuthMode, setUsername, setPassword, setDomain, setDomainArternative, setOnBeHalfUsername, setOnBeHalfPassword, onChangeLanguage } = props;
13
- const [loginHistoryData, setLoginHistoryData] = useState(loginHistory);
13
+ const { setLoginHistory, visible, hidePopup, setEndpoint, setArchive, setAuthMode, setUsername, setPassword, setDomain, setDomainArternative, setOnBeHalfUsername, setOnBeHalfPassword, onChangeLanguage } = props;
14
+ // State to manage loading status
14
15
  const [loading, setLoading] = useState(false);
16
+ // State to store the search input text
15
17
  const [searchText, setSearchText] = useState('');
18
+ // State to store selected items of type ITMLoginHistory
19
+ const [selectedItems, setSelectedItems] = useState([]);
20
+ // Retrieve the login history from local storage, sort by 'name', and return the sorted array (or an empty array if not found)
21
+ const getSortedLoginHistory = () => {
22
+ const loginHistory = LocalStorageService.getItem(LOGIN_HISTORY_KEY);
23
+ return loginHistory?.sort((a, b) => a.name.localeCompare(b.name)) || [];
24
+ };
25
+ // State to store both the full login history and the filtered search history
26
+ const [historyState, setHistoryState] = useState({
27
+ loginHistory: getSortedLoginHistory(),
28
+ searchedLoginHistory: getSortedLoginHistory(),
29
+ });
30
+ // Handle search input changes with a debounce effect, updating the searched login history after a delay
16
31
  useEffect(() => {
17
32
  let timeoutId;
18
33
  if (searchText.length > 0) {
19
34
  setLoading(true);
20
35
  timeoutId = setTimeout(() => {
21
- setLoginHistoryData(loginHistory.filter(data => data.name.toLowerCase().includes(searchText.toLowerCase())));
36
+ setHistoryState(prevState => ({
37
+ ...prevState,
38
+ searchedLoginHistory: historyState.loginHistory.filter(data => data.name.toLowerCase().includes(searchText.toLowerCase()))
39
+ }));
22
40
  setLoading(false);
23
41
  }, 300);
24
42
  }
25
43
  else {
26
- setLoginHistoryData(loginHistory);
44
+ setHistoryState(prevState => ({ ...prevState, loginHistory: historyState.loginHistory, searchedLoginHistory: historyState.loginHistory }));
27
45
  setLoading(false);
28
46
  }
29
47
  return () => {
30
48
  clearTimeout(timeoutId);
31
49
  };
32
50
  }, [searchText]);
33
- // Function to generate a hash from a string (text)
34
- const stringToHash = (str) => {
35
- let hash = 0;
36
- for (let i = 0; i < str.length; i++) {
37
- hash = (hash << 5) - hash + str.charCodeAt(i);
38
- hash = hash & hash; // Convert to 32bit integer
39
- }
40
- return hash;
51
+ // Function to reload and update state
52
+ const reloadHistoryState = () => {
53
+ const updatedLoginHistory = getSortedLoginHistory();
54
+ setHistoryState({
55
+ loginHistory: updatedLoginHistory,
56
+ searchedLoginHistory: updatedLoginHistory,
57
+ });
41
58
  };
42
- const getRandomColorFromText = (text) => {
43
- const hash = stringToHash(text);
44
- // Map the hash to a color, using the hash value for RGB
45
- const r = (hash & 0xFF0000) >> 16; // Red (8 bits)
46
- const g = (hash & 0x00FF00) >> 8; // Green (8 bits)
47
- const b = hash & 0x0000FF; // Blue (8 bits)
48
- // Ensure the RGB values are within the valid range (0-255)
49
- return `rgb(${r % 256}, ${g % 256}, ${b % 256})`;
59
+ // Update selected items with the last added item from the event (or an empty array if none were added)
60
+ const onSelectionChanged = (e) => {
61
+ const newItems = e.addedItems.length ? [e.addedItems[e.addedItems.length - 1]] : [];
62
+ setSelectedItems(newItems);
50
63
  };
51
- // Function to calculate luminance from a hex color
52
- const getLuminance = (color) => {
53
- // Using slice() instead of substr()
54
- let r = parseInt(color.slice(1, 3), 16) / 255; // slice(1, 3) extracts the hex digits for red
55
- let g = parseInt(color.slice(3, 5), 16) / 255; // slice(3, 5) extracts the hex digits for green
56
- let b = parseInt(color.slice(5, 7), 16) / 255; // slice(5, 7) extracts the hex digits for blue
57
- // Apply the luminance formula
58
- const a = [r, g, b].map(c => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
59
- const luminance = 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
60
- return luminance;
61
- };
62
- // Function to determine text color based on background luminance
63
- const getTextColor = (backgroundColor) => {
64
- return getLuminance(backgroundColor) > 0.5 ? 'black' : 'white';
64
+ // Populate the login form fields with data from the selected login history item
65
+ const fillLoginForm = (data) => {
66
+ setEndpoint(data.endpoint);
67
+ setArchive(data.archive);
68
+ setUsername(data.username);
69
+ setPassword("");
70
+ setAuthMode(data.authenticationMode);
71
+ setDomain(data.domain);
72
+ setDomainArternative(data.domainAlternative);
73
+ setOnBeHalfUsername(data.onBehalfUsername);
74
+ setOnBeHalfPassword("");
75
+ if (onChangeLanguage)
76
+ onChangeLanguage(data.language);
77
+ hidePopup();
65
78
  };
66
- const titleRender = () => (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }, children: [_jsx("h3", { children: SDKUI_Localizator.SwitchUser }), _jsx("button", { style: { background: 'none', border: 'none', fontSize: '16px', cursor: 'pointer' }, onClick: hidePopup, children: _jsx("i", { style: { fontSize: 20 }, className: "dx-icon-remove" }) })] }));
79
+ // Display a confirmation dialog for deleting an item from local storage and handle the deletion on confirmation
67
80
  const deleteItemFromLocalStorage = (name) => {
68
81
  const msg = SDKUI_Localizator.Delete_ConfirmFor1.replaceParams(name);
69
82
  TMMessageBoxManager.show({
@@ -74,7 +87,8 @@ const TMLoginPopupSaveLoginInfo = (props) => {
74
87
  try {
75
88
  LocalStorageService.deleteItemByField(LOGIN_HISTORY_KEY, "name", name);
76
89
  setLoginHistory(LocalStorageService.getItem(LOGIN_HISTORY_KEY) ?? []);
77
- setLoginHistoryData(LocalStorageService.getItem(LOGIN_HISTORY_KEY) ?? []);
90
+ reloadHistoryState();
91
+ setSelectedItems([]);
78
92
  }
79
93
  catch (e) {
80
94
  TMExceptionBoxManager.show({ exception: e });
@@ -82,33 +96,101 @@ const TMLoginPopupSaveLoginInfo = (props) => {
82
96
  }
83
97
  });
84
98
  };
85
- const fillLoginForm = (data) => {
86
- setEndpoint(data.endpoint);
87
- setArchive(data.archive);
88
- setUsername(data.username);
89
- setPassword("");
90
- setAuthMode(data.authenticationMode);
91
- setDomain(data.domain);
92
- setDomainArternative(data.domainAlternative);
93
- setOnBeHalfUsername(data.onBehalfUsername);
94
- setOnBeHalfPassword("");
95
- if (onChangeLanguage)
96
- onChangeLanguage(data.language);
99
+ // Clear the search text and close the popup
100
+ const closePopup = () => {
101
+ setSearchText('');
97
102
  hidePopup();
98
103
  };
99
- const itemTemplate = (data) => {
100
- // Generate a random background color for the circle
101
- const randomBGColor = getRandomColorFromText(data.name);
102
- // Determine the text color (black or white) based on background color luminance
103
- const textColor = getTextColor(randomBGColor);
104
- return _jsx(ScrollView, { direction: "horizontal", showScrollbar: "always", style: { width: '100%' }, useNative: true, children: _jsxs("div", { style: { display: 'flex', background: '#fff', boxShadow: '0 4px 20px rgba(0, 0, 0, 0.1)', overflow: 'hidden', width: '100%', justifyContent: 'center', alignItems: 'center' }, children: [_jsx(TMTooltip, { content: data.name, children: _jsx("div", { style: { background: randomBGColor, color: textColor, display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '70px', maxHeight: '70px', borderRadius: '50%', fontWeight: 'bold', margin: '20px', textAlign: 'center' }, children: data.name.slice(0, 3).toUpperCase() }) }), _jsxs("div", { style: { padding: '5px', flex: 1 }, children: [_jsxs("div", { style: { marginBottom: '12px', fontSize: '1em', color: '#555' }, children: [SDKUI_Localizator.Name, ": ", _jsxs("span", { style: { fontWeight: 'bold', color: '#333' }, children: [" ", data.name] })] }), _jsxs("div", { style: { marginBottom: '12px', fontSize: '1em', color: '#555' }, children: [SDKUI_Localizator.Endpoint, ": ", _jsxs("span", { style: { fontWeight: 'bold', color: '#333' }, children: [" ", data.endpoint?.Description ?? '', "/", data.username] }), " "] }), _jsxs("div", { style: { marginBottom: '12px', fontSize: '1em', color: '#555' }, children: [SDKUI_Localizator.ArchiveID, ": ", _jsxs("span", { style: { fontWeight: 'bold', color: '#333' }, children: [" ", data.archive?.description ?? ''] })] }), _jsxs("div", { style: { marginBottom: '12px', fontSize: '1em', color: '#555' }, children: [SDKUI_Localizator.AuthMode, ":", _jsxs("span", { style: { fontWeight: 'bold', color: '#333' }, children: [" ", data.authenticationMode] })] }), _jsxs("div", { style: { marginBottom: '12px', fontSize: '1em', color: '#555' }, children: [SDKUI_Localizator.CultureID, ":", _jsxs("span", { style: { fontWeight: 'bold', color: '#333' }, children: [" ", cultureIDsDataSource.find(item => item.value === data.language)?.display ?? ''] })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }, children: [_jsx(TMTooltip, { content: "Login", children: _jsx("div", { onClick: () => { fillLoginForm(data); }, style: { backgroundColor: randomBGColor, color: textColor, display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '50px', maxHeight: '50px', borderRadius: '50%', fontWeight: 'bold', marginRight: '10px', textAlign: 'center' }, children: _jsx("i", { className: "dx-icon-login", style: { fontSize: '1.5em', color: textColor, cursor: 'pointer' } }) }) }), _jsx(TMTooltip, { content: SDKUI_Localizator.Delete, children: _jsx("div", { onClick: () => { deleteItemFromLocalStorage(data.name); }, style: { backgroundColor: "#ff4d4f", display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '50px', maxHeight: '50px', borderRadius: '50%', fontWeight: 'bold', textAlign: 'center' }, children: _jsx("i", { className: "dx-icon-trash", style: { fontSize: '1.5em', color: getTextColor("#ff4d4f"), cursor: 'pointer' } }) }) })] })] })] }) });
104
+ // Render a title with a "Switch User" label and a close button styled as an icon
105
+ const titleRender = () => (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }, children: [_jsx("h3", { children: SDKUI_Localizator.SwitchUser }), _jsx("button", { style: { background: 'none', border: 'none', fontSize: '16px', cursor: 'pointer' }, onClick: hidePopup, children: _jsx("i", { style: { fontSize: 20 }, className: "dx-icon-remove" }) })] }));
106
+ // Render a styled title with its ID and title content, using flex layout
107
+ const itemTitleRender = (titleObj, id) => {
108
+ return _jsxs("div", { style: { display: "flex", gap: "20px", fontFamily: "Arial, sans-serif" }, children: [_jsx("div", { style: { padding: "10px", border: "1px solid #ddd", borderRadius: "10px", }, children: id }), _jsx("div", { style: { padding: "10px", fontWeight: "bold", border: "1px solid #ddd", borderRadius: "10px", }, children: titleObj.title })] });
105
109
  };
106
- const onSearchValueChanged = (e) => {
107
- if (e === undefined)
108
- return;
109
- setSearchText(e.target.value);
110
+ // Conditionally render popup content based on loading state, available login history, or display login items in an accordion
111
+ const renderPopupContent = () => {
112
+ if (loading) {
113
+ return (_jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", width: "100%" }, children: _jsx(LoadIndicator, {}) }));
114
+ }
115
+ if (historyState.searchedLoginHistory.length === 0) {
116
+ return (_jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", textAlign: "center", padding: "20px" }, children: SDKUI_Localizator.NoCredentialsSaved }));
117
+ }
118
+ return (_jsx("div", { style: { overflowY: "auto", maxHeight: "calc(100% - 60px)", padding: "10px" }, children: _jsx(Accordion, { selectedItems: selectedItems, onSelectionChanged: onSelectionChanged, collapsible: true, multiple: false, animationDuration: 300, noDataText: SDKUI_Localizator.NoCredentialsSaved, style: { border: "1px solid #ddd", borderRadius: "6px", boxShadow: "0 2px 6px rgba(0, 0, 0, 0.1)" }, children: historyState.searchedLoginHistory.map((data, index) => (_jsx(Item, { titleRender: (titleObj) => itemTitleRender(titleObj, index), title: data.name, children: _jsx(TMLoginItemTemplate, { data: data, reloadHistoryState: reloadHistoryState, fillLoginForm: fillLoginForm, deleteItemFromLocalStorage: deleteItemFromLocalStorage, setSelectedItems: setSelectedItems, setSearchText: setSearchText }) }, data.id))) }) }));
110
119
  };
111
- return _jsxs(Popup, { width: "90%", height: "80%", maxWidth: 600, visible: visible, onHiding: hidePopup, title: SDKUI_Localizator.SwitchUser, titleRender: titleRender, hideOnOutsideClick: false, showTitle: true, resizeEnabled: true, dragEnabled: true, showCloseButton: true, children: [_jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", width: "100%", marginBottom: "10px" }, children: _jsx(TMTextBox, { width: "160px", value: searchText, onValueChanged: onSearchValueChanged, label: SDKUI_Localizator.Search, placeHolder: SDKUI_Localizator.Search + "...", borderRadius: "6px" }) }), loading ? (_jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", width: "100%" }, children: _jsx(LoadIndicator, {}) })) :
112
- _jsx(Accordion, { defaultSelectedItems: [], collapsible: true, multiple: false, animationDuration: 300, noDataText: SDKUI_Localizator.NoCredentialsSaved, style: { border: "1px solid #ddd", borderRadius: "6px", boxShadow: "0 2px 6px rgba(0, 0, 0, 0.1)" }, children: loginHistoryData.sort((a, b) => a.name.localeCompare(b.name)).map((data, index) => _jsxs(Item, { title: data.name, children: [itemTemplate(data), " "] }, index)) })] });
120
+ return (_jsxs(Popup, { maxWidth: 600, visible: visible, onHiding: closePopup, title: SDKUI_Localizator.SwitchUser, titleRender: titleRender, hideOnOutsideClick: false, showTitle: true, resizeEnabled: true, dragEnabled: true, showCloseButton: true, children: [_jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", width: "100%", position: "sticky", top: 0, backgroundColor: "#fff", zIndex: 1, padding: "10px 0" }, children: _jsx(TMSearchBar, { maxWidth: "200px", marginLeft: "0px", onSearchValueChanged: (e) => setSearchText(e), searchValue: searchText }) }), renderPopupContent()] }));
113
121
  };
114
122
  export default TMLoginPopupSaveLoginInfo;
123
+ export const TMLoginItemTemplate = (props) => {
124
+ const { data, fillLoginForm, reloadHistoryState, deleteItemFromLocalStorage, setSelectedItems, setSearchText } = props;
125
+ const [name, setName] = useState(data.name);
126
+ const [error, setError] = useState(false);
127
+ const [validationItems, setValidationItems] = useState([]);
128
+ const nameIsEqualToInitName = data.name.trim().toLowerCase() === name.trim().toLowerCase();
129
+ // Effect to handle validation side-effects (like setting error state)
130
+ useEffect(() => {
131
+ const validationsItems = getValidationItems();
132
+ setValidationItems(validationsItems);
133
+ setError(validationsItems.length > 0); // Set error state based on validation result
134
+ }, [name]); // Only re-run when 'name' changes
135
+ // Update the login history item name in local storage if no errors and name is different from the initial name
136
+ const updateNameHandler = () => {
137
+ if (error || nameIsEqualToInitName)
138
+ return;
139
+ const dataToUpdate = { ...data, name };
140
+ LocalStorageService.updateItemByField(LOGIN_HISTORY_KEY, "name", data.name, dataToUpdate);
141
+ reloadHistoryState();
142
+ setSelectedItems([]);
143
+ setSearchText("");
144
+ };
145
+ // Validation logic function
146
+ const getValidationItems = () => {
147
+ const validationsArray = [];
148
+ if (nameIsEqualToInitName)
149
+ return validationsArray;
150
+ if (name.length === 0)
151
+ validationsArray.push(new ValidationItem(ResultTypes.ERROR, 'saveLoginName', SDK_Localizator.RequiredField));
152
+ const findItemByField = LocalStorageService.findItemByField(LOGIN_HISTORY_KEY, "name", name);
153
+ if (findItemByField) {
154
+ validationsArray.push(new ValidationItem(ResultTypes.ERROR, 'saveLoginName', SDKUI_Localizator.DuplicateNameError));
155
+ }
156
+ return validationsArray;
157
+ };
158
+ // Function to calculate luminance from a hex color
159
+ const getLuminance = (color) => {
160
+ // Using slice() instead of substr()
161
+ let r = parseInt(color.slice(1, 3), 16) / 255; // slice(1, 3) extracts the hex digits for red
162
+ let g = parseInt(color.slice(3, 5), 16) / 255; // slice(3, 5) extracts the hex digits for green
163
+ let b = parseInt(color.slice(5, 7), 16) / 255; // slice(5, 7) extracts the hex digits for blue
164
+ // Apply the luminance formula
165
+ const a = [r, g, b].map(c => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
166
+ const luminance = 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
167
+ return luminance;
168
+ };
169
+ // Function to determine text color based on background luminance
170
+ const getTextColor = (backgroundColor) => {
171
+ return getLuminance(backgroundColor) > 0.5 ? 'black' : 'white';
172
+ };
173
+ // Function to generate a hash from a string (text)
174
+ const stringToHash = (str) => {
175
+ let hash = 0;
176
+ for (let i = 0; i < str.length; i++) {
177
+ hash = (hash << 5) - hash + str.charCodeAt(i);
178
+ hash = hash & hash; // Convert to 32bit integer
179
+ }
180
+ return hash;
181
+ };
182
+ const getRandomColorFromText = (text) => {
183
+ const hash = stringToHash(text);
184
+ // Map the hash to a color, using the hash value for RGB
185
+ const r = (hash & 0xFF0000) >> 16; // Red (8 bits)
186
+ const g = (hash & 0x00FF00) >> 8; // Green (8 bits)
187
+ const b = hash & 0x0000FF; // Blue (8 bits)
188
+ // Ensure the RGB values are within the valid range (0-255)
189
+ return `rgb(${r % 256}, ${g % 256}, ${b % 256})`;
190
+ };
191
+ // Generate a random background color for the circle
192
+ const randomBGColor = getRandomColorFromText(data.name);
193
+ // Determine the text color (black or white) based on background color luminance
194
+ const textColor = getTextColor(randomBGColor);
195
+ return _jsxs("div", { style: { display: 'flex', background: '#fff', boxShadow: '0 4px 20px rgba(0, 0, 0, 0.1)', overflow: 'hidden', width: '100%', justifyContent: 'center', alignItems: 'center' }, children: [_jsx(TMTooltip, { content: data.name, children: _jsx("div", { style: { background: randomBGColor, color: textColor, display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '70px', maxHeight: '70px', borderRadius: '50%', fontWeight: 'bold', margin: '20px', textAlign: 'center' }, children: data.name.slice(0, 3).toUpperCase() }) }), _jsxs("div", { style: { padding: '2px', flex: 1 }, children: [_jsx(TMTextBox, { type: "text", label: "Nome per l'accesso", value: name, readOnly: false, buttons: [{ text: `${SDKUI_Localizator.Save}`, icon: _jsx("i", { style: { color: (error || nameIsEqualToInitName) ? "rgb(80,80,80)" : "#28a745", fontSize: 20 }, className: "dx-icon-save" }), onClick: updateNameHandler }], onValueChanged: (e) => setName(e.target.value), validationItems: validationItems }, "name"), (data.endpoint && data.endpoint?.Description) && _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.Endpoint, value: data.endpoint.Description + (' (' + data.endpoint.URL + ')'), readOnly: true, onValueChanged: (e) => setName(e.target.value) }), (data.archive && data.archive?.description) && _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.ArchiveID, value: data.archive.description + (' (' + (data.archive.id ?? '-') + ')'), readOnly: true }), _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.AuthMode, value: data.authenticationMode, readOnly: true }), data.domain.length > 0 && _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.Domain, value: data.domain, readOnly: true }), _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.UserName, value: data.username, readOnly: true }), _jsx(TMTextBox, { type: "text", label: SDKUI_Localizator.CultureID, value: cultureIDsDataSource.find(item => item.value === data.language)?.display ?? '', readOnly: true }), _jsxs("div", { style: { display: 'flex', justifyContent: 'flex-start', alignItems: 'center', marginTop: 10 }, children: [_jsx(TMTooltip, { content: "Login", children: _jsx("div", { onClick: () => { fillLoginForm(data); }, style: { backgroundColor: randomBGColor, color: textColor, display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '50px', maxHeight: '50px', borderRadius: '50%', fontWeight: 'bold', marginRight: '10px', textAlign: 'center' }, children: _jsx("i", { className: "dx-icon-login", style: { fontSize: '1.5em', color: textColor, cursor: 'pointer' } }) }) }), _jsx(TMTooltip, { content: SDKUI_Localizator.Save, children: _jsx("div", { onClick: () => { updateNameHandler(); }, style: { backgroundColor: (error || nameIsEqualToInitName) ? "rgb(80,80,80, 0.5)" : "#28a745", color: textColor, display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '50px', maxHeight: '50px', borderRadius: '50%', fontWeight: 'bold', marginRight: '10px', textAlign: 'center' }, children: _jsx("i", { className: "dx-icon-save", style: { fontSize: '1.5em', color: textColor, cursor: 'pointer' } }) }) }), _jsx(TMTooltip, { content: SDKUI_Localizator.Delete, children: _jsx("div", { onClick: () => { deleteItemFromLocalStorage(data.name); }, style: { backgroundColor: "#ff4d4f", display: 'flex', justifyContent: 'center', alignItems: 'center', width: '15vw', height: '15vw', maxWidth: '50px', maxHeight: '50px', borderRadius: '50%', fontWeight: 'bold', textAlign: 'center' }, children: _jsx("i", { className: "dx-icon-trash", style: { fontSize: '1.5em', color: getTextColor("#ff4d4f"), cursor: 'pointer' } }) }) })] })] })] });
196
+ };
@@ -225,7 +225,7 @@ export declare class SDKUI_Localizator {
225
225
  static get ShowSearch(): "Suche anzeigen" | "Show search" | "Mostrar búsqueda" | "Afficher la recherche" | "Mostrar pesquisa" | "Mostra ricerca";
226
226
  static get HideSearch(): "Suche ausblenden" | "Hide search" | "Ocultar búsqueda" | "Masquer la recherche" | "Ocultar pesquisa" | "Nascondi ricerca";
227
227
  static get NoCredentialsSaved(): "Keine gespeicherten Anmeldedaten" | "No credentials saved" | "No se han guardado credenciales" | "Aucune information d'identification enregistrée" | "Nenhuma credencial salva" | "Nessuna credenziale salvata";
228
- static get DuplicateNameError(): "Der Name existiert bereits in der Anmeldehistorie. Jeder Eintrag muss einen eindeutigen Namen haben, um Duplikate zu vermeiden. Bitte wählen Sie einen anderen Namen." | "The name already exists in the login history. Each entry must have a unique name to avoid duplication. Please choose a different name." | "El nombre ya existe en el historial de inicio de sesión. Cada entrada debe tener un nombre único para evitar duplicados. Por favor, elija un nombre diferente." | "Le nom existe déjà dans l'historique de connexion. Chaque entrée doit avoir un nom unique pour éviter les doublons. Veuillez choisir un autre nom." | "O nome já existe no histórico de login. Cada entrada deve ter um nome único para evitar duplicações. Por favor, escolha um nome diferente." | "Il nome esiste già nella cronologia di accesso. Ogni voce deve avere un nome unico per evitare duplicati. Si prega di scegliere un nome diverso.";
228
+ static get DuplicateNameError(): "Der Name existiert bereits in der Anmeldehistorie. Bitte wählen Sie einen anderen Namen" | "The name already exists in the login history. Please choose a different nam" | "El nombre ya existe en el historial de inicio de sesión. Por favor, elija un nombre diferente" | "Le nom existe déjà dans l'historique de connexion. Veuillez choisir un autre nom" | "O nome já existe no histórico de login. Por favor, escolha um nome diferente" | "Il nome esiste già nella cronologia di accesso. Si prega di scegliere un nome diverso";
229
229
  static get EnterNameForAccess(): "Geben Sie einen Namen für den Zugriff ein" | "Enter a name for access" | "Introduzca un nombre para el acceso" | "Entrez un nom pour l'accès" | "Insira um nome para o acesso" | "Inserire un nome per l'accesso";
230
230
  static get RememberCredentials(): "Anmeldedaten merken" | "Remember credentials" | "Recordar credenciales" | "Se souvenir des identifiants" | "Lembrar credenciais" | "Ricorda credenziali";
231
231
  static get SwitchUser(): "Benutzer wechseln" | "Switch user" | "Cambiar usuario" | "Changer d'utilisateur" | "Mudar de usuário" | "Cambia utente";
@@ -2209,17 +2209,17 @@ export class SDKUI_Localizator {
2209
2209
  static get DuplicateNameError() {
2210
2210
  switch (this._cultureID) {
2211
2211
  case CultureIDs.De_DE:
2212
- return "Der Name existiert bereits in der Anmeldehistorie. Jeder Eintrag muss einen eindeutigen Namen haben, um Duplikate zu vermeiden. Bitte wählen Sie einen anderen Namen.";
2212
+ return "Der Name existiert bereits in der Anmeldehistorie. Bitte wählen Sie einen anderen Namen";
2213
2213
  case CultureIDs.En_US:
2214
- return "The name already exists in the login history. Each entry must have a unique name to avoid duplication. Please choose a different name.";
2214
+ return "The name already exists in the login history. Please choose a different nam";
2215
2215
  case CultureIDs.Es_ES:
2216
- return "El nombre ya existe en el historial de inicio de sesión. Cada entrada debe tener un nombre único para evitar duplicados. Por favor, elija un nombre diferente.";
2216
+ return "El nombre ya existe en el historial de inicio de sesión. Por favor, elija un nombre diferente";
2217
2217
  case CultureIDs.Fr_FR:
2218
- return "Le nom existe déjà dans l'historique de connexion. Chaque entrée doit avoir un nom unique pour éviter les doublons. Veuillez choisir un autre nom.";
2218
+ return "Le nom existe déjà dans l'historique de connexion. Veuillez choisir un autre nom";
2219
2219
  case CultureIDs.Pt_PT:
2220
- return "O nome já existe no histórico de login. Cada entrada deve ter um nome único para evitar duplicações. Por favor, escolha um nome diferente.";
2220
+ return "O nome já existe no histórico de login. Por favor, escolha um nome diferente";
2221
2221
  default:
2222
- return "Il nome esiste già nella cronologia di accesso. Ogni voce deve avere un nome unico per evitare duplicati. Si prega di scegliere un nome diverso.";
2222
+ return "Il nome esiste già nella cronologia di accesso. Si prega di scegliere un nome diverso";
2223
2223
  }
2224
2224
  }
2225
2225
  static get EnterNameForAccess() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.7.21",
3
+ "version": "6.7.23",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",