diff --git a/web/messages/en/form.json b/web/messages/en/form.json index 0775653714..aa172e8ab9 100644 --- a/web/messages/en/form.json +++ b/web/messages/en/form.json @@ -13,6 +13,8 @@ "form_error_required": "Field is required", "form_error_token": "Token is not valid", "form_error_invalid": "Field is invalid", + "form_error_no_destination": "Select one of the options.", + "form_error_no_predefined_destination": "Configure manual destination.", "form_error_forbidden_char": "Field contains forbidden characters", "form_error_username_taken": "Username is already in use", "form_error_email_reserved": "Email is already in use", diff --git a/web/src/pages/CERulePage/CERulePage.tsx b/web/src/pages/CERulePage/CERulePage.tsx index 72b91d9347..86ada2e903 100644 --- a/web/src/pages/CERulePage/CERulePage.tsx +++ b/web/src/pages/CERulePage/CERulePage.tsx @@ -184,6 +184,7 @@ const Content = ({ rule: initialRule }: Props) => { }, [users]); const { data: destinations } = useQuery(getAppliedDestinationsQueryOptions); + const hasPredefinedDestinations = Boolean(destinations && destinations.length > 0); const destinationsOptions = useMemo(() => { if (isPresent(destinations)) { @@ -437,14 +438,22 @@ const Content = ({ rule: initialRule }: Props) => { }); } } else if (vals.destinations.size === 0) { + // If no predefined destinations exist, show error under the "Add manual destination settings" checkbox. + // If predefined destinations exist - show it at the end of "Destination" section. ctx.addIssue({ - path: ['destinations'], + path: [ + hasPredefinedDestinations + ? 'destinations' + : 'use_manual_destination_settings', + ], code: 'custom', - message: m.form_error_required(), + message: hasPredefinedDestinations + ? m.form_error_no_destination() + : m.form_error_no_predefined_destination(), }); } }), - [restrictDevices, restrictGroups, restrictUsers], + [hasPredefinedDestinations, restrictDevices, restrictGroups, restrictUsers], ); type FormFields = z.infer; @@ -618,7 +627,6 @@ const Content = ({ rule: initialRule }: Props) => { }); }} /> - {selectedDestinations.length > 0 && (
@@ -813,6 +821,13 @@ const Content = ({ rule: initialRule }: Props) => { )} + + {() => ( + + )} + @@ -1118,10 +1133,14 @@ const AliasDataBlock = ({ values }: AliasDataBlockProps) => { ); }; -const DestinationSelectionError = () => { +const DestinationSelectionError = ({ + hasPredefinedDestinations, +}: { + hasPredefinedDestinations: boolean; +}) => { const error = useFormFieldError(); - if (!error) return null; - return ( - - ); + + if (!hasPredefinedDestinations || !error) return null; + + return ; }; diff --git a/web/src/pages/EdgesPage/EdgesTable.tsx b/web/src/pages/EdgesPage/EdgesTable.tsx index 0bb409ca5d..d608f823e8 100644 --- a/web/src/pages/EdgesPage/EdgesTable.tsx +++ b/web/src/pages/EdgesPage/EdgesTable.tsx @@ -43,8 +43,6 @@ const isConnected = (edge: EdgeInfo) => { return connected > disconnected; }; -const displayModifiedBy = (edge: EdgeInfo) => `${edge.modified_by}`; - const getStatusBadge = (edge: EdgeInfo) => { if (!edge.enabled) { return ( @@ -112,7 +110,12 @@ export const EdgesTable = () => { const transformedData = useMemo(() => { let data = edges; if (search.length) { - data = data.filter((u) => u.name.toLowerCase().includes(search.toLowerCase())); + const query = search.toLowerCase(); + data = data.filter( + (edge) => + edge.name.toLowerCase().includes(query) || + edge.modified_by.toLowerCase().includes(query), + ); } return data; @@ -175,15 +178,15 @@ export const EdgesTable = () => { ), }), - columnHelper.display({ - id: 'modified_by', + columnHelper.accessor('modified_by', { size: 200, minSize: 175, header: m.edges_col_modified_by(), enableSorting: true, + sortingFn: 'text', cell: (info) => ( - {displayModifiedBy(info.row.original)} + {info.getValue()} ), }), diff --git a/web/src/pages/LocationsPage/components/GatewaysTable.tsx b/web/src/pages/LocationsPage/components/GatewaysTable.tsx index f39cd7c549..fa8276994b 100644 --- a/web/src/pages/LocationsPage/components/GatewaysTable.tsx +++ b/web/src/pages/LocationsPage/components/GatewaysTable.tsx @@ -28,8 +28,6 @@ type RowData = GatewayInfo; const columnHelper = createColumnHelper(); -const displayModifiedBy = (gateway: GatewayInfo) => `${gateway.modified_by}`; - const getStatusBadge = (gateway: GatewayInfo) => { if (!gateway.enabled) { return ( @@ -69,7 +67,7 @@ export const GatewaysTable = () => { if (query.length > 0) { data = data.filter((gateway) => { - const modifiedBy = displayModifiedBy(gateway).toLowerCase(); + const modifiedBy = gateway.modified_by.toLowerCase(); return ( gateway.name.toLowerCase().includes(query) || gateway.location_name.toLowerCase().includes(query) || @@ -145,15 +143,15 @@ export const GatewaysTable = () => { ), }), - columnHelper.display({ - id: 'modified_by', + columnHelper.accessor('modified_by', { size: 175, minSize: 175, header: m.edges_col_modified_by(), enableSorting: true, + sortingFn: 'text', cell: (info) => ( - {displayModifiedBy(info.row.original)} + {info.getValue()} ), }), diff --git a/web/src/pages/UsersOverviewPage/modals/AddUserModal/AddUserModal.tsx b/web/src/pages/UsersOverviewPage/modals/AddUserModal/AddUserModal.tsx index 0f735ad947..0f42bfabbd 100644 --- a/web/src/pages/UsersOverviewPage/modals/AddUserModal/AddUserModal.tsx +++ b/web/src/pages/UsersOverviewPage/modals/AddUserModal/AddUserModal.tsx @@ -479,7 +479,9 @@ const AddUserModalForm = () => { cancelProps={{ disabled: isSubmitting, text: m.controls_cancel(), - onClick: () => {}, + onClick: () => { + useAddUserModal.setState({ isOpen: false }); + }, }} submitProps={{ text: m.modal_add_user_submit(),