mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Cb 5562 Fix bad this.setState for the new form API (#2903)
* CB-5478 adds useAdministrationUserFormState with flexible id field * CB-5478 simplifies logic fork form state hooks * CB-5562 refactors form state and form parts * CB-5562 fixes disabled param for formState * CB-5562 comments cleanup * CB-5562 fixes getting of exceptions * CB-5562 baseform bad set state fix * CB-5562 removes load and configure method for forms * CB-5562 reverts some state.exception changes * CB-5562 removes bad set state from user form * CB-5562 cleanup * CB-5562 cleanup * CB-5562 removes bad set state from user form * CB-5562 fixes bad set state for user profile * CB-5562 pr fixes * CB-5562 pr fixes --------- Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
This commit is contained in:
co-authored by
Daria Marutkina
parent
4f0db5b854
commit
2d1bde22a2
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { Button, Container, Form, s, StatusMessage, useAutoLoad, useForm, useS, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { Button, Container, Form, getComputed, s, StatusMessage, useForm, useS, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { getFirstException } from '@cloudbeaver/core-utils';
|
||||
|
||||
import { TabList } from '../../Tabs/TabList';
|
||||
@@ -22,7 +22,8 @@ export const BaseForm = observer<IBaseFormProps<any>>(function BaseForm({ servic
|
||||
const translate = useTranslate();
|
||||
|
||||
const editing = state.mode === FormMode.Edit;
|
||||
const changed = state.isChanged();
|
||||
const changed = state.isChanged;
|
||||
const error = getComputed(() => getFirstException(state.exception));
|
||||
|
||||
const form = useForm({
|
||||
async onSubmit() {
|
||||
@@ -36,15 +37,13 @@ export const BaseForm = observer<IBaseFormProps<any>>(function BaseForm({ servic
|
||||
},
|
||||
});
|
||||
|
||||
useAutoLoad(BaseForm, state);
|
||||
|
||||
return (
|
||||
<Form context={form} disabled={state.isDisabled} contents focusFirstChild>
|
||||
<TabsState container={service.parts} localState={state.parts} formState={state}>
|
||||
<Container compact parent noWrap vertical>
|
||||
<Container className={s(styles, { bar: true })} gap keepSize noWrap>
|
||||
<Container fill>
|
||||
<StatusMessage exception={getFirstException(state.exception)} type={state.statusType} message={state.statusMessage} />
|
||||
<StatusMessage exception={error} type={state.statusType} message={state.statusMessage} />
|
||||
<TabList className={s(styles, { tabList: true })} underline big />
|
||||
</Container>
|
||||
<Container keepSize noWrap center gap compact>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { action, makeObservable, observable, toJS } from 'mobx';
|
||||
import { action, computed, makeObservable, observable, toJS } from 'mobx';
|
||||
|
||||
import { executorHandlerFilter, ExecutorInterrupter, type IExecutionContextProvider } from '@cloudbeaver/core-executor';
|
||||
import { isObjectsEqual } from '@cloudbeaver/core-utils';
|
||||
@@ -16,6 +16,7 @@ import type { IFormState } from './IFormState';
|
||||
export abstract class FormPart<TPartState, TFormState = any> implements IFormPart<TPartState> {
|
||||
state: TPartState;
|
||||
initialState: TPartState;
|
||||
isSaving: boolean;
|
||||
|
||||
exception: Error | null;
|
||||
promise: Promise<any> | null;
|
||||
@@ -29,6 +30,7 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
) {
|
||||
this.initialState = initialState;
|
||||
this.state = toJS(this.initialState);
|
||||
this.isSaving = false;
|
||||
|
||||
this.exception = null;
|
||||
this.promise = null;
|
||||
@@ -37,7 +39,6 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
this.loading = false;
|
||||
|
||||
this.formState.submitTask.addHandler(executorHandlerFilter(() => this.isLoaded(), this.save.bind(this)));
|
||||
this.formState.configureTask.addHandler(executorHandlerFilter(() => this.isLoaded(), this.configure.bind(this)));
|
||||
this.formState.formatTask.addHandler(executorHandlerFilter(() => this.isLoaded(), this.format.bind(this)));
|
||||
this.formState.validationTask.addHandler(executorHandlerFilter(() => this.isLoaded(), this.validate.bind(this)));
|
||||
|
||||
@@ -46,12 +47,19 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
state: observable,
|
||||
exception: observable.ref,
|
||||
promise: observable.ref,
|
||||
isSaving: observable.ref,
|
||||
loaded: observable,
|
||||
loading: observable,
|
||||
setInitialState: action,
|
||||
isDisabled: computed,
|
||||
isChanged: computed,
|
||||
});
|
||||
}
|
||||
|
||||
get isDisabled(): boolean {
|
||||
return this.isSaving || this.isLoading();
|
||||
}
|
||||
|
||||
isLoading(): boolean {
|
||||
return this.loading;
|
||||
}
|
||||
@@ -68,7 +76,7 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
return this.exception !== null;
|
||||
}
|
||||
|
||||
isChanged(): boolean {
|
||||
get isChanged(): boolean {
|
||||
if (!this.loaded || this.initialState === this.state) {
|
||||
return false;
|
||||
}
|
||||
@@ -85,10 +93,12 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
try {
|
||||
await this.loader();
|
||||
|
||||
if (!this.isChanged()) {
|
||||
if (!this.isChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSaving = true;
|
||||
|
||||
await this.saveChanges(data, contexts);
|
||||
if (ExecutorInterrupter.isInterrupted(contexts)) {
|
||||
return;
|
||||
@@ -100,6 +110,7 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
this.exception = exception;
|
||||
throw exception;
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
@@ -136,7 +147,7 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
protected setInitialState(initialState: TPartState) {
|
||||
this.initialState = initialState;
|
||||
|
||||
if (this.isChanged()) {
|
||||
if (this.isChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,7 +158,6 @@ export abstract class FormPart<TPartState, TFormState = any> implements IFormPar
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
protected configure(data: IFormState<TFormState>, contexts: IExecutionContextProvider<IFormState<TFormState>>): void | Promise<void> {}
|
||||
protected format(data: IFormState<TFormState>, contexts: IExecutionContextProvider<IFormState<TFormState>>): void | Promise<void> {}
|
||||
protected validate(data: IFormState<TFormState>, contexts: IExecutionContextProvider<IFormState<TFormState>>): void | Promise<void> {}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { DataContext, dataContextAddDIProvider, DataContextGetter, type IDataCon
|
||||
import type { IServiceProvider } from '@cloudbeaver/core-di';
|
||||
import type { ENotificationType } from '@cloudbeaver/core-events';
|
||||
import { Executor, ExecutorInterrupter, IExecutionContextProvider, type IExecutor } from '@cloudbeaver/core-executor';
|
||||
import { isLoadableStateHasException, MetadataMap, uuid } from '@cloudbeaver/core-utils';
|
||||
import { isArraysEqual, isNotNullDefined, MetadataMap, uuid } from '@cloudbeaver/core-utils';
|
||||
import { DATA_CONTEXT_LOADABLE_STATE, loadableStateContext } from '@cloudbeaver/core-view';
|
||||
|
||||
import { DATA_CONTEXT_FORM_STATE } from './DATA_CONTEXT_FORM_STATE';
|
||||
@@ -25,23 +25,24 @@ export class FormState<TState> implements IFormState<TState> {
|
||||
mode: FormMode;
|
||||
parts: MetadataMap<string, IFormPart<any>>;
|
||||
state: TState;
|
||||
isSaving: boolean;
|
||||
|
||||
statusMessage: string | string[] | null;
|
||||
statusType: ENotificationType | null;
|
||||
exception: Error | (Error | null)[] | null;
|
||||
|
||||
promise: Promise<any> | null;
|
||||
|
||||
get isDisabled(): boolean {
|
||||
return this.isSaving || this.isLoading();
|
||||
return this.partsValues.some(part => part.isSaving || part?.isLoading?.());
|
||||
}
|
||||
|
||||
get isSaving(): boolean {
|
||||
return this.partsValues.some(part => part.isSaving);
|
||||
}
|
||||
|
||||
readonly id: string;
|
||||
readonly service: FormBaseService<TState, any>;
|
||||
readonly dataContext: IDataContext;
|
||||
|
||||
readonly configureTask: IExecutor<IFormState<TState>>;
|
||||
readonly formStateTask: IExecutor<TState>;
|
||||
readonly fillDefaultConfigTask: IExecutor<IFormState<TState>>;
|
||||
readonly submitTask: IExecutor<IFormState<TState>>;
|
||||
@@ -56,17 +57,12 @@ export class FormState<TState> implements IFormState<TState> {
|
||||
this.mode = FormMode.Create;
|
||||
this.parts = new MetadataMap<string, any>();
|
||||
this.state = state;
|
||||
this.isSaving = false;
|
||||
|
||||
this.statusMessage = null;
|
||||
this.statusType = null;
|
||||
this.exception = null;
|
||||
|
||||
this.promise = null;
|
||||
|
||||
this.configureTask = new Executor(this as IFormState<TState>, () => true);
|
||||
this.configureTask.addCollection(service.onConfigure);
|
||||
|
||||
this.formStateTask = new Executor<TState>(state, () => true);
|
||||
this.formStateTask.addCollection(service.onState).addPostHandler(this.updateFormState.bind(this));
|
||||
|
||||
@@ -90,42 +86,43 @@ export class FormState<TState> implements IFormState<TState> {
|
||||
mode: observable,
|
||||
parts: observable.ref,
|
||||
promise: observable.ref,
|
||||
exception: observable.ref,
|
||||
isSaving: observable.ref,
|
||||
state: observable,
|
||||
isSaving: computed,
|
||||
exception: computed,
|
||||
isDisabled: computed,
|
||||
setMode: action,
|
||||
setPartsState: action,
|
||||
setException: action,
|
||||
setState: action,
|
||||
isChanged: computed,
|
||||
partsValues: computed<IFormPart<any>[]>({
|
||||
equals: isArraysEqual,
|
||||
}),
|
||||
isError: computed,
|
||||
isCancelled: computed,
|
||||
});
|
||||
}
|
||||
|
||||
isLoading(): boolean {
|
||||
return this.promise !== null || this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders.some(loader => loader.isLoading());
|
||||
get partsValues() {
|
||||
return Array.from(this.parts.values());
|
||||
}
|
||||
|
||||
isLoaded(): boolean {
|
||||
if (this.promise) {
|
||||
return false;
|
||||
}
|
||||
return this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders.every(loader => loader.isLoaded());
|
||||
get exception(): Error | (Error | null)[] | null {
|
||||
return this.partsValues
|
||||
.map(part => part?.exception)
|
||||
.flat()
|
||||
.filter(isNotNullDefined);
|
||||
}
|
||||
|
||||
isError(): boolean {
|
||||
return this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders.some(loader => loader.isError());
|
||||
get isError(): boolean {
|
||||
return this.partsValues.some(part => part.isError());
|
||||
}
|
||||
|
||||
isOutdated(): boolean {
|
||||
return this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders.some(loader => loader.isOutdated?.() === true);
|
||||
get isCancelled(): boolean {
|
||||
return this.partsValues.some(part => part?.isCancelled?.());
|
||||
}
|
||||
|
||||
isCancelled(): boolean {
|
||||
return this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders.some(loader => loader.isCancelled?.() === true);
|
||||
}
|
||||
|
||||
isChanged(): boolean {
|
||||
return Array.from(this.parts.values()).some(part => part.isChanged());
|
||||
get isChanged(): boolean {
|
||||
return this.partsValues.some(part => part.isChanged);
|
||||
}
|
||||
|
||||
getPart<T extends IFormPart<any>>(getter: DataContextGetter<T>, init: (context: IDataContext, id: string) => T): T {
|
||||
@@ -140,50 +137,6 @@ export class FormState<TState> implements IFormState<TState> {
|
||||
}) as T;
|
||||
}
|
||||
|
||||
async load(refresh?: boolean): Promise<void> {
|
||||
if (this.promise !== null) {
|
||||
return this.promise;
|
||||
}
|
||||
|
||||
if (this.isLoaded() && !this.isOutdated() && !refresh) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.promise = (async () => {
|
||||
try {
|
||||
await this.configureTask.execute(this);
|
||||
|
||||
const loaders = this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders;
|
||||
|
||||
for (const loader of loaders) {
|
||||
if (isLoadableStateHasException(loader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!loader.isLoaded() || loader.isOutdated?.() === true) {
|
||||
try {
|
||||
await loader.load();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.fillDefaultConfigTask.execute(this);
|
||||
this.exception = null;
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
throw exception;
|
||||
} finally {
|
||||
this.promise = null;
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
async reload(): Promise<void> {
|
||||
await this.load(true);
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
const loaders = this.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!.loaders;
|
||||
|
||||
@@ -210,11 +163,6 @@ export class FormState<TState> implements IFormState<TState> {
|
||||
return this;
|
||||
}
|
||||
|
||||
setException(exception: Error | (Error | null)[] | null): this {
|
||||
this.exception = exception;
|
||||
return this;
|
||||
}
|
||||
|
||||
setState(state: TState): this {
|
||||
this.state = state;
|
||||
return this;
|
||||
@@ -222,20 +170,15 @@ export class FormState<TState> implements IFormState<TState> {
|
||||
|
||||
async save(): Promise<boolean> {
|
||||
try {
|
||||
this.isSaving = true;
|
||||
const context = await this.submitTask.execute(this);
|
||||
|
||||
if (ExecutorInterrupter.isInterrupted(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.exception = null;
|
||||
return true;
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
}
|
||||
} catch (exception: any) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ import type { ILoadableState } from '@cloudbeaver/core-utils';
|
||||
export interface IFormPart<TState> extends ILoadableState {
|
||||
readonly state: TState;
|
||||
readonly initialState: TState;
|
||||
isSaving: boolean;
|
||||
readonly isDisabled: boolean;
|
||||
|
||||
isChanged(): boolean;
|
||||
readonly isChanged: boolean;
|
||||
|
||||
load(): Promise<void>;
|
||||
reset(): void;
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
import type { DataContextGetter, IDataContext } from '@cloudbeaver/core-data-context';
|
||||
import type { ENotificationType } from '@cloudbeaver/core-events';
|
||||
import type { IExecutor } from '@cloudbeaver/core-executor';
|
||||
import type { ILoadableState, MetadataMap } from '@cloudbeaver/core-utils';
|
||||
import type { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
import type { FormBaseService } from './FormBaseService';
|
||||
import type { FormMode } from './FormMode';
|
||||
import type { IFormPart } from './IFormPart';
|
||||
|
||||
export interface IFormState<TState> extends ILoadableState {
|
||||
export interface IFormState<TState> {
|
||||
readonly id: string;
|
||||
readonly service: FormBaseService<TState>;
|
||||
readonly dataContext: IDataContext;
|
||||
@@ -23,14 +23,13 @@ export interface IFormState<TState> extends ILoadableState {
|
||||
readonly parts: MetadataMap<string, any>;
|
||||
readonly state: TState;
|
||||
readonly isDisabled: boolean;
|
||||
readonly exception: Error | (Error | null)[] | null;
|
||||
|
||||
readonly promise: Promise<any> | null;
|
||||
|
||||
readonly exception: Error | (Error | null)[] | null;
|
||||
readonly statusMessage: string | string[] | null;
|
||||
readonly statusType: ENotificationType | null;
|
||||
|
||||
readonly configureTask: IExecutor<IFormState<TState>>;
|
||||
readonly formStateTask: IExecutor<TState>;
|
||||
readonly fillDefaultConfigTask: IExecutor<IFormState<TState>>;
|
||||
readonly submitTask: IExecutor<IFormState<TState>>;
|
||||
@@ -39,20 +38,14 @@ export interface IFormState<TState> extends ILoadableState {
|
||||
|
||||
setMode(mode: FormMode): this;
|
||||
setPartsState(state: MetadataMap<string, any>): this;
|
||||
setException(exception: Error | (Error | null)[] | null): this;
|
||||
setState(state: TState): this;
|
||||
|
||||
getPart<T extends IFormPart<any>>(getter: DataContextGetter<T>, init: (context: IDataContext, id: string) => T): T;
|
||||
|
||||
isLoading(): boolean;
|
||||
isLoaded(): boolean;
|
||||
isError(): boolean;
|
||||
isOutdated(): boolean;
|
||||
isCancelled(): boolean;
|
||||
isChanged(): boolean;
|
||||
isError: boolean;
|
||||
isCancelled: boolean;
|
||||
isChanged: boolean;
|
||||
|
||||
load(): Promise<void>;
|
||||
reload(): Promise<void>;
|
||||
save(): Promise<boolean>;
|
||||
reset(): void;
|
||||
cancel(): void;
|
||||
|
||||
+2
-2
@@ -59,7 +59,7 @@ export const AdministrationUserForm = observer<Props>(function AdministrationUse
|
||||
},
|
||||
});
|
||||
|
||||
useAutoLoad(AdministrationUserForm, state);
|
||||
useAutoLoad(AdministrationUserForm, [userFormInfoPart]);
|
||||
|
||||
return (
|
||||
<Form context={form} disabled={state.isDisabled} contents focusFirstChild>
|
||||
@@ -69,7 +69,7 @@ export const AdministrationUserForm = observer<Props>(function AdministrationUse
|
||||
<Container fill>
|
||||
<StatusMessage
|
||||
className={s(styles, { statusMessage: true })}
|
||||
exception={getFirstException(state.exception)}
|
||||
exception={getFirstException(userFormInfoPart.exception)}
|
||||
type={state.statusType}
|
||||
message={state.statusMessage}
|
||||
/>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ export class UserFormConnectionAccessPart extends FormPart<AdminConnectionGrantI
|
||||
super(formState, []);
|
||||
}
|
||||
|
||||
isChanged(): boolean {
|
||||
get isChanged(): boolean {
|
||||
if (!this.loaded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+4
-13
@@ -9,12 +9,11 @@ import { observable, toJS } from 'mobx';
|
||||
|
||||
import type { AdminUser, AuthRolesResource, UserResourceIncludes, UsersResource } from '@cloudbeaver/core-authentication';
|
||||
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
|
||||
import { CachedResourceIncludeArgs, getCachedDataResourceLoaderState } from '@cloudbeaver/core-resource';
|
||||
import { CachedResourceIncludeArgs } from '@cloudbeaver/core-resource';
|
||||
import type { ServerConfigResource } from '@cloudbeaver/core-root';
|
||||
import type { AdminUserInfoFragment } from '@cloudbeaver/core-sdk';
|
||||
import { FormMode, FormPart, formValidationContext, IFormState } from '@cloudbeaver/core-ui';
|
||||
import { isArraysEqual, isDefined, isObjectsEqual, isValuesEqual } from '@cloudbeaver/core-utils';
|
||||
import { DATA_CONTEXT_LOADABLE_STATE } from '@cloudbeaver/core-view';
|
||||
|
||||
import type { IUserFormState } from '../AdministrationUserFormService';
|
||||
import type { IUserFormInfoState } from './IUserFormInfoState';
|
||||
@@ -62,7 +61,7 @@ export class UserFormInfoPart extends FormPart<IUserFormInfoState, IUserFormStat
|
||||
return this.usersResource.isOutdated(this.initialState.userId, this.baseIncludes);
|
||||
}
|
||||
|
||||
return false;
|
||||
return this.serverConfigResource.isOutdated() || this.authRolesResource.isOutdated();
|
||||
}
|
||||
|
||||
isLoaded(): boolean {
|
||||
@@ -77,7 +76,7 @@ export class UserFormInfoPart extends FormPart<IUserFormInfoState, IUserFormStat
|
||||
return this.loaded;
|
||||
}
|
||||
|
||||
isChanged(): boolean {
|
||||
get isChanged(): boolean {
|
||||
if (!this.loaded) {
|
||||
return false;
|
||||
}
|
||||
@@ -138,14 +137,6 @@ export class UserFormInfoPart extends FormPart<IUserFormInfoState, IUserFormStat
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override configure() {
|
||||
const loadableStateContext = this.formState.dataContext.get(DATA_CONTEXT_LOADABLE_STATE)!;
|
||||
|
||||
loadableStateContext.getState('user-info', () => [
|
||||
getCachedDataResourceLoaderState(this.serverConfigResource, () => undefined),
|
||||
getCachedDataResourceLoaderState(this.authRolesResource, () => undefined),
|
||||
]);
|
||||
}
|
||||
|
||||
private async updateCredentials() {
|
||||
const password = this.state.password;
|
||||
@@ -220,7 +211,7 @@ export class UserFormInfoPart extends FormPart<IUserFormInfoState, IUserFormStat
|
||||
|
||||
protected override async loader() {
|
||||
let user: AdminUser | null = null;
|
||||
const serverConfig = await this.serverConfigResource.load();
|
||||
const [serverConfig] = await Promise.all([this.serverConfigResource.load(), this.authRolesResource.load()]);
|
||||
|
||||
if (this.formState.mode === FormMode.Edit && this.initialState.userId) {
|
||||
user = await this.usersResource.load(this.initialState.userId, this.baseIncludes);
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ export class UserProfileFormAuthenticationPart extends FormPart<IUserProfileForm
|
||||
return this.loaded && this.userInfoResource.isLoaded(undefined, this.baseIncludes);
|
||||
}
|
||||
|
||||
isChanged(): boolean {
|
||||
get isChanged(): boolean {
|
||||
if (!this.loaded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ export class UserProfileFormInfoPart extends FormPart<IUserProfileFormInfoState,
|
||||
return this.loaded && this.userInfoResource.isLoaded(undefined, this.baseIncludes);
|
||||
}
|
||||
|
||||
isChanged(): boolean {
|
||||
get isChanged(): boolean {
|
||||
if (!this.loaded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const UserProfileFormPanel: TabContainerPanelComponent = observer(functio
|
||||
async function closeHandler(_, contexts) {
|
||||
const context = contexts.getContext(userProfileContext);
|
||||
|
||||
if (state.isChanged() && !context.force) {
|
||||
if (state.isChanged && !context.force) {
|
||||
const result = await commonDialogService.open(ConfirmationDialog, {
|
||||
title: 'connections_public_connection_edit_cancel_title',
|
||||
message: 'connections_public_connection_edit_cancel_message',
|
||||
|
||||
Reference in New Issue
Block a user