From 0085826203dafc6806cb31e0c692acffee1c81f7 Mon Sep 17 00:00:00 2001 From: Caleb Roseland Date: Tue, 14 Jan 2025 11:42:46 -0600 Subject: [PATCH] MM-62172: CPA/User Properties - System Console (#29672) * system properties - user properties * update * fix processing * refinements, fix cancel changes, fix type inclusion when saving/creating, i18n * fix: - property name value trimmed - name unique validation - name required validation - name max-length - user properties section titlecase - new property default incremented name - new property auto-focus/select - max fields count - table design/styling * add useUserPropertyFields test --- .../admin_console/admin_definition.tsx | 14 + .../blockable_button/blockable_button.tsx | 45 +++ .../admin_console/blockable_button/index.ts | 29 ++ .../group_details/group_details.tsx | 2 +- .../admin_console/ip_filtering/index.tsx | 2 +- .../save_changes_panel.tsx | 48 ++- .../secure_connection_detail.tsx | 2 +- .../system_properties/controls.tsx | 88 ++++ .../admin_console/system_properties/index.ts | 8 + .../system_properties/section_utils.test.ts | 151 +++++++ .../system_properties/section_utils.ts | 141 +++++++ .../system_properties/system_properties.tsx | 97 +++++ .../user_properties_delete_modal.tsx | 82 ++++ .../user_properties_table.tsx | 379 ++++++++++++++++++ .../user_properties_utils.test.ts | 78 ++++ .../user_properties_utils.ts | 198 +++++++++ .../system_roles/system_role/system_role.tsx | 2 +- .../channel/details/channel_details.tsx | 2 +- .../team/details/team_details.tsx | 2 +- webapp/channels/src/i18n/en.json | 16 + webapp/channels/src/utils/constants.tsx | 3 + webapp/platform/types/src/client4.ts | 2 + webapp/platform/types/src/utilities.ts | 38 ++ 23 files changed, 1407 insertions(+), 22 deletions(-) create mode 100644 webapp/channels/src/components/admin_console/blockable_button/blockable_button.tsx create mode 100644 webapp/channels/src/components/admin_console/blockable_button/index.ts rename webapp/channels/src/components/admin_console/{team_channel_settings => }/save_changes_panel.tsx (50%) create mode 100644 webapp/channels/src/components/admin_console/system_properties/controls.tsx create mode 100644 webapp/channels/src/components/admin_console/system_properties/index.ts create mode 100644 webapp/channels/src/components/admin_console/system_properties/section_utils.test.ts create mode 100644 webapp/channels/src/components/admin_console/system_properties/section_utils.ts create mode 100644 webapp/channels/src/components/admin_console/system_properties/system_properties.tsx create mode 100644 webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.tsx create mode 100644 webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx create mode 100644 webapp/channels/src/components/admin_console/system_properties/user_properties_utils.test.ts create mode 100644 webapp/channels/src/components/admin_console/system_properties/user_properties_utils.ts diff --git a/webapp/channels/src/components/admin_console/admin_definition.tsx b/webapp/channels/src/components/admin_console/admin_definition.tsx index 85cf579652..3757c19590 100644 --- a/webapp/channels/src/components/admin_console/admin_definition.tsx +++ b/webapp/channels/src/components/admin_console/admin_definition.tsx @@ -93,6 +93,7 @@ import SecureConnectionDetail from './secure_connections/secure_connection_detai import ServerLogs from './server_logs'; import {searchableStrings as serverLogsSearchableStrings} from './server_logs/logs'; import SessionLengthSettings, {searchableStrings as sessionLengthSearchableStrings} from './session_length_settings'; +import SystemProperties, {searchableStrings as systemPropertiesSearchableStrings} from './system_properties'; import SystemRoles from './system_roles'; import SystemRole from './system_roles/system_role'; import SystemUserDetail from './system_user_detail'; @@ -2172,6 +2173,19 @@ const AdminDefinition: AdminDefinitionType = { ], }, }, + system_properties: { + url: 'site_config/system_properties', + title: defineMessage({id: 'admin.sidebar.system_properties', defaultMessage: 'System Properties'}), + searchableStrings: systemPropertiesSearchableStrings, + isHidden: it.not(it.all( + it.licensedForSku(LicenseSkus.Enterprise), + it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'), + )), + schema: { + id: 'SystemProperties', + component: SystemProperties, + }, + }, localization: { url: 'site_config/localization', title: defineMessage({id: 'admin.sidebar.localization', defaultMessage: 'Localization'}), diff --git a/webapp/channels/src/components/admin_console/blockable_button/blockable_button.tsx b/webapp/channels/src/components/admin_console/blockable_button/blockable_button.tsx new file mode 100644 index 0000000000..229cc0a3f5 --- /dev/null +++ b/webapp/channels/src/components/admin_console/blockable_button/blockable_button.tsx @@ -0,0 +1,45 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React, {useCallback} from 'react'; +import type {MouseEvent} from 'react'; + +type Props = { + id?: string; + activeClassName?: string; + + // Bool whether navigation is blocked + blocked: boolean; + + actions: { + + // Function for deferring navigation while blocked + deferNavigation: (func: () => void) => void; + }; + children?: React.ReactNode; + className?: string; + onClick?: (e: React.MouseEvent) => void; + onCancelConfirmed: () => void; +}; + +const BlockableButton = ({blocked, actions, onClick, onCancelConfirmed, ...restProps}: Props) => { + const handleClick = useCallback((e: MouseEvent) => { + onClick?.(e); + + if (blocked) { + e.preventDefault(); + actions.deferNavigation(() => { + onCancelConfirmed(); + }); + } + }, [actions, blocked, onClick, onCancelConfirmed]); + + return ( +