From 3c7da0b03d51876ef5e5ffef40f18f08e83cd20b Mon Sep 17 00:00:00 2001 From: Wroud Date: Wed, 9 Sep 2020 15:47:02 +0300 Subject: [PATCH 1/5] chore: cleanup --- webapp/packages/core-bootstrap/src/AppBootstrap.ts | 2 -- .../src/AgGridTable/AgGridTableController.ts | 7 ------- 2 files changed, 9 deletions(-) diff --git a/webapp/packages/core-bootstrap/src/AppBootstrap.ts b/webapp/packages/core-bootstrap/src/AppBootstrap.ts index 1ac408b8ed..17546199db 100644 --- a/webapp/packages/core-bootstrap/src/AppBootstrap.ts +++ b/webapp/packages/core-bootstrap/src/AppBootstrap.ts @@ -12,12 +12,10 @@ import { NavigationTreeContextMenuService, LogViewerMenuService, ConnectionSchemaManagerService, - AppScreenService, } from '@cloudbeaver/core-app'; import { injectable } from '@cloudbeaver/core-di'; import { SessionExpireService } from '@cloudbeaver/core-dialogs'; import { ExceptionsCatcherService } from '@cloudbeaver/core-events'; -import { RouterService } from '@cloudbeaver/core-routing'; import { ThemeService } from '@cloudbeaver/core-theming'; /** diff --git a/webapp/packages/plugin-data-spreadsheet/src/AgGridTable/AgGridTableController.ts b/webapp/packages/plugin-data-spreadsheet/src/AgGridTable/AgGridTableController.ts index 744166d363..af98a39f38 100644 --- a/webapp/packages/plugin-data-spreadsheet/src/AgGridTable/AgGridTableController.ts +++ b/webapp/packages/plugin-data-spreadsheet/src/AgGridTable/AgGridTableController.ts @@ -18,7 +18,6 @@ import { ColDef, ValueGetterParams, GridOptions, - CellEditingStoppedEvent, CellClassParams, SortChangedEvent, RowNode, @@ -74,7 +73,6 @@ export class AgGridTableController implements IInitializableController, IDestruc onGridReady: this.handleGridReady.bind(this), onBodyScroll: this.handleBodyScroll.bind(this), - onCellEditingStopped: this.handleCellEditingStopped.bind(this), onSortChanged: this.handleSortChanged.bind(this), }; @@ -163,11 +161,6 @@ export class AgGridTableController implements IInitializableController, IDestruc this.gridModel.onCellEditingStopped(rowIndex, colId, value, editing); } - private handleCellEditingStopped(event: CellEditingStoppedEvent) { - // TODO: probably no more needed because editCellValue executes on every change in editor - // this.gridModel.onCellEditingStopped(event.rowIndex, event.column.getColId(), event.value, false); - } - private isCellEdited(rowIndex: number, column: string) { return this.gridModel.isCellEdited(rowIndex, column); } From 1750b15a70648e034b9e3d66e07f8a3a44a6a6e6 Mon Sep 17 00:00:00 2001 From: Wroud Date: Wed, 9 Sep 2020 15:48:26 +0300 Subject: [PATCH 2/5] fix(core-connections): driver custom properties CB-246 --- .../src/PropertiesTable/IProperty.ts | 1 + .../src/PropertiesTable/PropertiesTable.tsx | 2 +- .../src/PropertiesTable/PropertyItem.tsx | 4 ++-- .../DriverProperties/DriverProperties.tsx | 4 ++-- .../DriverPropertiesController.ts | 20 +++++++++++++++---- .../DriverProperties/DriverProperties.tsx | 4 ++-- .../DriverPropertiesController.ts | 19 ++++++++++++++---- 7 files changed, 39 insertions(+), 15 deletions(-) diff --git a/webapp/packages/core-blocks/src/PropertiesTable/IProperty.ts b/webapp/packages/core-blocks/src/PropertiesTable/IProperty.ts index 79076fdc00..e4dd204865 100644 --- a/webapp/packages/core-blocks/src/PropertiesTable/IProperty.ts +++ b/webapp/packages/core-blocks/src/PropertiesTable/IProperty.ts @@ -13,4 +13,5 @@ export interface IProperty { defaultValue?: string; description?: string; validValues?: string[]; + new?: boolean; } diff --git a/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx b/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx index 331afe8f13..5fce925b32 100644 --- a/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx +++ b/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx @@ -105,7 +105,7 @@ export const PropertiesTable = observer(function PropertiesTable({ {translate('block_properties_table_value')} - {onAdd && } + {onAdd && } diff --git a/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx b/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx index 6883c5ad8c..d4251ee281 100644 --- a/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx +++ b/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx @@ -134,10 +134,10 @@ export const PropertyItem = observer(function PropertyItem({ const handleRemove = useCallback(() => onRemove(property.id), [property]); useLayoutEffect(() => { - if (keyInputRef.current && isKeyEditable) { + if (keyInputRef.current && isKeyEditable && property.new) { keyInputRef.current.focus(); } - }, []); + }, [property]); return styled(useStyles(styles))( diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverProperties.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverProperties.tsx index 9049b630e9..004588e5bb 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverProperties.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverProperties.tsx @@ -39,7 +39,7 @@ export const DriverProperties = observer(function DriverProperties({ state, loadProperties, }: DriverPropertiesProps) { - const controller = useController(DriverPropertiesController, driverId); + const controller = useController(DriverPropertiesController, driverId, state); useMemo(() => { if (loadProperties) { @@ -54,7 +54,7 @@ export const DriverProperties = observer(function DriverProperties({ )} diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverPropertiesController.ts b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverPropertiesController.ts index 2d962886c0..e467d10628 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverPropertiesController.ts +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/DriverProperties/DriverPropertiesController.ts @@ -32,20 +32,24 @@ export class DriverPropertiesController implements IInitializableController { loaded = false; + private state!: Record; + constructor( private driverPropertiesService: DriverPropertiesService, private notificationService: NotificationService ) { } - init(driverId: string) { + init(driverId: string, state: Record) { this.driverId = driverId; + this.state = state; } - onAddProperty = () => { + addProperty = (key?: string, value?: string) => { this.driverProperties.unshift({ id: uuid(), - key: 'property', - defaultValue: '', + key: key ?? 'property', + defaultValue: value ?? '', + new: !key, }); } @@ -64,6 +68,14 @@ export class DriverPropertiesController implements IInitializableController { description: property.description, validValues: property.validValues, }))); + + for (const key of Object.keys(this.state)) { + if (this.driverProperties.some(property => property.key === key)) { + continue; + } + + this.addProperty(key, this.state[key]); + } this.loaded = true; } catch (exception) { this.notificationService.logException(exception, 'Can\'t load driver properties'); diff --git a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverProperties.tsx b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverProperties.tsx index e5b4b2714a..98978f1a40 100644 --- a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverProperties.tsx +++ b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverProperties.tsx @@ -41,7 +41,7 @@ export const DriverProperties = observer(function DriverProperties({ state, loadProperties, }: DriverPropertiesProps) { - const controller = useController(DriverPropertiesController, driver); + const controller = useController(DriverPropertiesController, driver, state); useEffect(() => { if (loadProperties) { @@ -56,7 +56,7 @@ export const DriverProperties = observer(function DriverProperties({ )} diff --git a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts index 9a1d574942..85a3ad9fc8 100644 --- a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts +++ b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts @@ -34,21 +34,24 @@ export class DriverPropertiesController implements IInitializableController { @observable driverProperties = observable([]) private loaded = false; + private state!: Record; constructor( private driverPropertiesService: DriverPropertiesService, private notificationService: NotificationService ) { } - init(driver: DBDriver) { + init(driver: DBDriver, state: Record) { this.driver = driver; + this.state = state; } - onAddProperty = () => { + addProperty = (key?: string, value?: string) => { this.driverProperties.unshift({ id: uuid(), - key: 'property', - defaultValue: '', + key: key ?? 'property', + defaultValue: value ?? '', + new: !key, }); } @@ -67,6 +70,14 @@ export class DriverPropertiesController implements IInitializableController { description: property.description, validValues: property.validValues, }))); + + for (const key of Object.keys(this.state)) { + if (this.driverProperties.some(property => property.key === key)) { + continue; + } + + this.addProperty(key, this.state[key]); + } this.loaded = true; } catch (exception) { this.notificationService.logException(exception, 'Can\'t load driver properties'); From 6fed7382690ce14cc8c7f201db614e18b4fe4f61 Mon Sep 17 00:00:00 2001 From: Wroud Date: Wed, 9 Sep 2020 18:06:25 +0300 Subject: [PATCH 3/5] fix: table overflow CB-247 --- .../Connections/ConnectionsTable/ConnectionEdit.tsx | 1 + .../Connections/ConnectionsTable/ConnectionsTable.tsx | 3 +++ webapp/packages/core-theming/src/styles/_table.scss | 9 ++++++++- .../src/Administration/Users/UsersTable/UsersTable.tsx | 3 +++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx index 3c83bf1a29..45d025b48a 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx @@ -26,6 +26,7 @@ const styles = composes( `, css` box { + box-sizing: border-box; padding: 24px; min-height: 320px; max-height: 500px; diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx index 927d0ea02a..b857fdde6f 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx @@ -25,6 +25,9 @@ const styles = composes( } `, css` + Table { + width: 100%; + } TableColumnHeader { border-top: solid 1px; } diff --git a/webapp/packages/core-theming/src/styles/_table.scss b/webapp/packages/core-theming/src/styles/_table.scss index c4edd9db1c..6ee29790cf 100644 --- a/webapp/packages/core-theming/src/styles/_table.scss +++ b/webapp/packages/core-theming/src/styles/_table.scss @@ -12,10 +12,15 @@ min-width: 100%; text-align: left; border-collapse: collapse; + table-layout: fixed; &[use|size="big"] { > thead > tr > th { height: 54px; + + &[use|min] { + width: 46px; + } } > tbody > tr > td { @@ -53,6 +58,7 @@ } th { + box-sizing: border-box; white-space: nowrap; padding: 16px; height: 36px; @@ -64,7 +70,7 @@ text-decoration: none !important; &[use|min] { - width: 1%; + width: 28px; } &:last-child { @@ -74,6 +80,7 @@ td { position: relative; + box-sizing: border-box; height: 28px; padding: 0 16px; transition: padding ease-in-out 0.24s; diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UsersTable.tsx b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UsersTable.tsx index 1cd3d78b9f..727e2b2972 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UsersTable.tsx +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UsersTable.tsx @@ -19,6 +19,9 @@ import { useStyles } from '@cloudbeaver/core-theming'; import { User } from './User'; const styles = css` + Table { + width: 100%; + } TableColumnHeader { border-top: solid 1px; } From 97f3a944a58c5a37330a3f55aa8f5278f61fd36b Mon Sep 17 00:00:00 2001 From: Wroud Date: Wed, 9 Sep 2020 19:01:42 +0300 Subject: [PATCH 4/5] fix(plugin-authentication): user creation CB-295 --- .../core-authentication/src/UsersResource.ts | 26 +-------- .../ConnectionsTable/ConnectionEdit.tsx | 6 -- .../src/Administration/Users/CreateUser.tsx | 8 +-- .../Users/UserForm/UserForm.tsx | 17 +++--- .../Users/UserForm/UserFormController.ts | 51 +++++++---------- .../Users/UsersAdministrationController.ts | 20 ++++--- .../Administration/Users/UsersTable/User.tsx | 12 +--- .../Users/UsersTable/UserEdit.tsx | 31 ++++++++++- .../Users/UsersTable/UserEditController.ts | 55 +++++++++++++++++++ 9 files changed, 135 insertions(+), 91 deletions(-) create mode 100644 webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEditController.ts diff --git a/webapp/packages/core-authentication/src/UsersResource.ts b/webapp/packages/core-authentication/src/UsersResource.ts index 6e2a34c652..5024886fed 100644 --- a/webapp/packages/core-authentication/src/UsersResource.ts +++ b/webapp/packages/core-authentication/src/UsersResource.ts @@ -26,7 +26,6 @@ type AdminUserNew = AdminUserInfo & { [NEW_USER_SYMBOL]: boolean } type UserCreateOptions = { userId: string; - newId?: string; roles: string[]; credentials: Record; grantedConnections: string[]; @@ -59,22 +58,6 @@ export class UsersResource extends CachedMapResource { return this.data.has(id); } - addNew() { - const user = { - userId: `new-${uuid()}`, - grantedRoles: [], - grantedConnections: [], - configurationParameters: {}, - metaParameters: {}, - [NEW_USER_SYMBOL]: true, - } as AdminUserNew; - - this.data.set(user.userId, user); - this.markUpdated(user.userId); - - return user; - } - async loadConnections(userId: string): Promise { if (this.isNew(userId)) { return []; @@ -90,15 +73,10 @@ export class UsersResource extends CachedMapResource { } async create({ - userId, newId, roles, credentials, grantedConnections, + userId, roles, credentials, grantedConnections, }: UserCreateOptions): Promise { const { user } = await this.graphQLService.gql.createUser({ userId }); - if (newId) { - this.data.delete(newId); - } - this.set(userId, user as AdminUserInfo); - try { await this.updateCredentials(userId, credentials); for (const roleId of roles) { @@ -106,6 +84,8 @@ export class UsersResource extends CachedMapResource { } await this.setConnections(userId, grantedConnections); + const user = await this.refresh(userId)as AdminUserNew; + user[NEW_USER_SYMBOL] = true; } catch (exception) { this.delete(userId); throw exception; diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx index 45d025b48a..2f946cd0a4 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx @@ -33,12 +33,6 @@ const styles = composes( display: flex; flex-direction: column; } - - ErrorMessage { - position: sticky; - bottom: 0; - padding: 8px 24px; - } ` ); diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/CreateUser.tsx b/webapp/packages/plugin-authentication/src/Administration/Users/CreateUser.tsx index 0ff36b77d6..9b00d72650 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/CreateUser.tsx +++ b/webapp/packages/plugin-authentication/src/Administration/Users/CreateUser.tsx @@ -28,13 +28,13 @@ const styles = composes( css` title-bar { composes: theme-typography--headline6 from global; - padding: 0 16px; + box-sizing: border-box; + padding: 16px 24px; border-top: solid 1px; align-items: center; - height: 48px; display: flex; font-weight: 400; - flex: 1; + flex: auto 0 0; } ` ); @@ -47,7 +47,7 @@ export function CreateUser({ return styled(useStyles(styles))( - + ); } diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserForm.tsx b/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserForm.tsx index 9c5861ee45..210f58da14 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserForm.tsx +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserForm.tsx @@ -21,6 +21,7 @@ import { } from '@cloudbeaver/core-blocks'; import { useController } from '@cloudbeaver/core-di'; import { useTranslate } from '@cloudbeaver/core-localization'; +import { AdminUserInfo } from '@cloudbeaver/core-sdk'; import { useStyles, composes } from '@cloudbeaver/core-theming'; import { GrantedConnections } from './GrantedConnections'; @@ -53,10 +54,6 @@ const styles = composes( } `, css` - box { - padding: 24px; - } - SubmittingForm { flex: 1; display: flex; @@ -128,16 +125,18 @@ const styles = composes( ); type Props = { - userId: string; + user: AdminUserInfo; + editing?: boolean; onCancel: () => void; } export const UserForm = observer(function UserForm({ - userId, + user, + editing = false, onCancel, }: Props) { const translate = useTranslate(); - const controller = useController(UserFormController, userId, onCancel); + const controller = useController(UserFormController, user, editing, onCancel); const [focusedRef] = useFocus({ focusFirstChild: true }); const handleLoginChange = useCallback( @@ -182,7 +181,7 @@ export const UserForm = observer(function UserForm({ mod={['unelevated']} onClick={controller.save} > - {translate(controller.isNew ? 'ui_processing_create' : 'ui_processing_save')} + {translate(!editing ? 'ui_processing_create' : 'ui_processing_save')} @@ -199,7 +198,7 @@ export const UserForm = observer(function UserForm({ name='login' value={controller.credentials.login} onChange={handleLoginChange} - disabled={!controller.isNew || controller.isSaving} + disabled={editing || controller.isSaving} mod='surface' required > diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserFormController.ts b/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserFormController.ts index feba6eb8b2..6edbc7a5f9 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserFormController.ts +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/UserFormController.ts @@ -31,10 +31,6 @@ export class UserFormController implements IInitializableController, IDestructib roles: new Map(), }; - @computed get isNew() { - return this.usersResource.isNew(this.userId); - } - @computed get connections() { return Array.from(this.connectionsResource.data.values()) .filter(connection => !this.connectionsResource.isNew(connection.id)); @@ -44,16 +40,14 @@ export class UserFormController implements IInitializableController, IDestructib return Array.from(this.rolesManagerService.roles.data.values()); } - @computed get user(): AdminUserInfo { - return this.usersResource.get(this.userId)!; - } + user!: AdminUserInfo; readonly error = new GQLErrorCatcher(); private isDistructed = false; - private userId!: string; private connectionAccessChanged = false; private connectionAccessLoaded = false; private collapse!: () => void; + private editing!: boolean; constructor( private notificationService: NotificationService, @@ -64,8 +58,9 @@ export class UserFormController implements IInitializableController, IDestructib private dbDriverResource: DBDriverResource ) { } - init(id: string, collapse: () => void) { - this.userId = id; + init(user: AdminUserInfo, editing: boolean, collapse: () => void) { + this.user = user; + this.editing = editing; this.collapse = collapse; this.loadRoles(); } @@ -84,10 +79,9 @@ export class UserFormController implements IInitializableController, IDestructib this.isSaving = true; try { - if (this.isNew) { + if (!this.editing) { await this.usersResource.create({ userId: this.credentials.login, - newId: this.userId, credentials: { password: this.credentials.password }, roles: this.getGrantedRoles(), grantedConnections: this.getGrantedConnections(), @@ -103,12 +97,9 @@ export class UserFormController implements IInitializableController, IDestructib await this.usersResource.refresh(this.user.userId); this.notificationService.logInfo({ title: 'authentication_administration_user_updated' }); } - - this.connectionAccessLoaded = false; - await this.loadConnectionsAccess(); } catch (exception) { if (!this.error.catch(exception) || this.isDistructed) { - if (this.isNew) { + if (!this.editing) { this.notificationService.logException(exception, 'Error creating new user'); } else { this.notificationService.logException(exception, 'Error saving user'); @@ -134,12 +125,14 @@ export class UserFormController implements IInitializableController, IDestructib this.isLoading = true; try { - this.grantedConnections = await this.usersResource.loadConnections(this.userId); + if (this.editing) { + this.grantedConnections = await this.usersResource.loadConnections(this.user.userId); - this.selectedConnections.clear(); - for (const connection of this.grantedConnections) { - if (connection.subjectType !== AdminSubjectType.Role) { - this.selectedConnections.set(connection.connectionId, true); + this.selectedConnections.clear(); + for (const connection of this.grantedConnections) { + if (connection.subjectType !== AdminSubjectType.Role) { + this.selectedConnections.set(connection.connectionId, true); + } } } this.connectionAccessLoaded = true; @@ -161,12 +154,12 @@ export class UserFormController implements IInitializableController, IDestructib return; } - if (!this.credentials.password && this.isNew) { + if (!this.credentials.password && !this.editing) { this.notificationService.logError({ title: 'authentication_user_password_not_set' }); return; } - if (!this.credentials.password && this.isNew) { + if (!this.credentials.password && !this.editing) { this.notificationService.logError({ title: 'authentication_user_password_not_set' }); return; } @@ -190,7 +183,7 @@ export class UserFormController implements IInitializableController, IDestructib if (!this.user.grantedRoles.includes(roleId)) { await this.usersResource.grantRole(this.user.userId, roleId, true); } - } else if (!this.isNew) { + } else { await this.usersResource.revokeRole(this.user.userId, roleId, true); } } @@ -215,8 +208,10 @@ export class UserFormController implements IInitializableController, IDestructib if (!this.connectionAccessChanged) { return; } - await this.usersResource.setConnections(this.userId, this.getGrantedConnections()); + await this.usersResource.setConnections(this.user.userId, this.getGrantedConnections()); this.connectionAccessChanged = false; + this.connectionAccessLoaded = false; + await this.loadConnectionsAccess(); } private async loadRoles() { @@ -232,11 +227,7 @@ export class UserFormController implements IInitializableController, IDestructib private async loadUser() { try { - await this.usersResource.load(this.userId); - - if (!this.isNew) { - this.credentials.login = this.user.userId; - } + this.credentials.login = this.user.userId; this.credentials.roles = new Map(this.user.grantedRoles.map(roleId => ([roleId, true]))); } catch (exception) { this.notificationService.logException(exception, 'Can\'t load user'); diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts b/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts index 8df7843c18..351e00765a 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts @@ -13,7 +13,7 @@ import { injectable } from '@cloudbeaver/core-di'; import { CommonDialogService, ConfirmationDialog } from '@cloudbeaver/core-dialogs'; import { NotificationService } from '@cloudbeaver/core-events'; import { ErrorDetailsDialog } from '@cloudbeaver/core-notifications'; -import { GQLErrorCatcher, resourceKeyList } from '@cloudbeaver/core-sdk'; +import { GQLErrorCatcher, resourceKeyList, AdminUserInfo } from '@cloudbeaver/core-sdk'; import { UsersAdministrationNavigationService } from './UsersAdministrationNavigationService'; @@ -26,10 +26,9 @@ export class UsersAdministrationController { @computed get users() { return Array.from(this.usersResource.data.values()) - .filter(user => !this.usersResource.isNew(user.userId)) .sort((a, b) => { if (this.usersResource.isNew(a.userId) === this.usersResource.isNew(b.userId)) { - return 0; + return a.userId.localeCompare(b.userId); } if (this.usersResource.isNew(a.userId)) { return -1; @@ -38,10 +37,7 @@ export class UsersAdministrationController { }); } - @computed get creatingUser() { - return Array.from(this.usersResource.data.values()) - .find(user => this.usersResource.isNew(user.userId)); - } + @observable creatingUser: AdminUserInfo | null = null; get isLoading() { return this.usersResource.isLoading() || this.isDeleting; @@ -55,7 +51,13 @@ export class UsersAdministrationController { ) { } create = () => { - this.usersResource.addNew(); + this.creatingUser = { + userId: '', + grantedRoles: [], + grantedConnections: [], + configurationParameters: {}, + metaParameters: {}, + } as AdminUserInfo; this.usersAdministrationNavigationService.navToAdd(); } @@ -64,7 +66,7 @@ export class UsersAdministrationController { return; } - this.usersResource.delete(this.creatingUser.userId); + this.creatingUser = null; this.usersAdministrationNavigationService.navToRoot(); } diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/User.tsx b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/User.tsx index 760f123893..2f0a814f10 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/User.tsx +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/User.tsx @@ -7,14 +7,11 @@ */ import { observer } from 'mobx-react'; -import styled, { css, use } from 'reshadow'; +import styled, { css } from 'reshadow'; -import { UsersResource } from '@cloudbeaver/core-authentication'; import { TableItem, TableColumnValue, TableItemSelect, TableItemExpand } from '@cloudbeaver/core-blocks'; -import { useService } from '@cloudbeaver/core-di'; -import { useTranslate } from '@cloudbeaver/core-localization'; import { AdminUserInfo } from '@cloudbeaver/core-sdk'; import { useStyles } from '@cloudbeaver/core-theming'; @@ -31,9 +28,6 @@ type Props = { } export const User = observer(function User({ user }: Props) { - const translate = useTranslate(); - const usersResource = useService(UsersResource); - const isNew = usersResource.isNew(user.userId); return styled(useStyles(styles))( @@ -43,9 +37,9 @@ export const User = observer(function User({ user }: Props) { - {isNew ? translate('authentication_administration_user_connections_user_new') : user.userId} + {user.userId} {user.grantedRoles.join(', ')} - {isNew && {translate('ui_tag_new')}} + ); }); diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEdit.tsx b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEdit.tsx index ab38706268..3146c39f2c 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEdit.tsx +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEdit.tsx @@ -8,12 +8,34 @@ import { observer } from 'mobx-react'; import { useContext, useCallback } from 'react'; +import styled, { css } from 'reshadow'; import { TableContext, } from '@cloudbeaver/core-blocks'; +import { useController } from '@cloudbeaver/core-di'; +import { composes, useStyles } from '@cloudbeaver/core-theming'; import { UserForm } from '../UserForm/UserForm'; +import { UserEditController } from './UserEditController'; + +const styles = composes( + css` + box { + composes: theme-background-secondary theme-text-on-secondary from global; + } + `, + css` + box { + box-sizing: border-box; + padding: 24px; + min-height: 320px; + max-height: 500px; + display: flex; + flex-direction: column; + } + ` +); type Props = { item: string; @@ -22,8 +44,15 @@ type Props = { export const UserEdit = observer(function UserEdit({ item, }: Props) { + const controller = useController(UserEditController, item); const tableContext = useContext(TableContext); const collapse = useCallback(() => tableContext?.setItemExpand(item, false), [tableContext]); - return ; + return styled(useStyles(styles))( + + {controller.user && ( + + )} + + ); }); diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEditController.ts b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEditController.ts new file mode 100644 index 0000000000..6210dbd87c --- /dev/null +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UsersTable/UserEditController.ts @@ -0,0 +1,55 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +import { observable, computed } from 'mobx'; + +import { UsersResource } from '@cloudbeaver/core-authentication'; +import { + injectable, IInitializableController, IDestructibleController +} from '@cloudbeaver/core-di'; +import { NotificationService } from '@cloudbeaver/core-events'; +import { GQLErrorCatcher, AdminUserInfo } from '@cloudbeaver/core-sdk'; + +@injectable() +export class UserEditController +implements IInitializableController, IDestructibleController { + @observable isLoading = true; + @observable user: AdminUserInfo | null = null; + + @computed get isDisabled() { + return this.isLoading; + } + + userId!: string; + + readonly error = new GQLErrorCatcher(); + + constructor( + private notificationService: NotificationService, + private usersResource: UsersResource, + ) { } + + init(id: string) { + this.userId = id; + this.loadUser(); + } + + destruct(): void { } + + private async loadUser() { + this.isLoading = true; + try { + // we create a copy to protect the current value from mutation + this.user = JSON.parse(JSON.stringify(await this.usersResource.load(this.userId))); + } catch (exception) { + this.notificationService.logException(exception, `Can't load user ${this.userId}`); + } finally { + this.isLoading = false; + } + } +} From 91834c9c7df8e62badc0ff1f36eb412c4e1797eb Mon Sep 17 00:00:00 2001 From: Wroud Date: Wed, 9 Sep 2020 19:15:31 +0300 Subject: [PATCH 5/5] feat(core-administration): localization CB-293 --- .../Pages/Finish/FinishPage.tsx | 9 +++++++-- .../ServerConfigurationPage.tsx | 10 ++++++++-- .../Pages/Welcome/WelcomePage.tsx | 14 ++++++++++++-- .../core-administration/src/locales/en.ts | 11 +++++++++-- .../Connections/ConnectionsAdministration.tsx | 18 +++++++++++++++++- .../core-connections/src/locales/en.ts | 1 + 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/Pages/Finish/FinishPage.tsx b/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/Pages/Finish/FinishPage.tsx index c19974014d..0e851d08ae 100644 --- a/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/Pages/Finish/FinishPage.tsx +++ b/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/Pages/Finish/FinishPage.tsx @@ -41,6 +41,11 @@ const styles = composes( border: solid 1px; padding: 16px 24px } + + p { + line-height: 2; + white-space: pre; + } ` ); @@ -52,8 +57,8 @@ export const FinishPage = observer(function FinishPage() { -

All done

-

Go to fun

+

{translate('administration_configuration_wizard_finish_title')}

+

{translate('administration_configuration_wizard_finish_message')}