Skip to content

Commit

Permalink
Migrated change password widget and editor
Browse files Browse the repository at this point in the history
  • Loading branch information
ygrik committed Oct 28, 2024
1 parent 400bf53 commit e275954
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 218 deletions.
2 changes: 1 addition & 1 deletion src/apim.design.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { ReportsEditorModule as ReportsDesignModule } from "./components/reports
import { ResetPasswordDesignModule } from "./components/users/reset-password/resetPassword.design.module";
import { ConfirmPasswordEditorModule as ConfirmPasswordDesignModule } from "./components/users/confirm-password/ko/confirmPasswordEditor.module";
import { HelpModule } from "./components/help";
import { ChangePasswordEditorModule as ChangePasswordDesignModule } from "./components/users/change-password/ko/changePasswordEditor.module";
import { ChangePasswordDesignModule } from "./components/users/change-password/changePassword.design.module";
import { TenantService } from "./services/tenantService";
import { ValidationSummaryDesignModule } from "./components/users/validation-summary/validationSummary.design.module";
import { BackendService } from "./services/backendService";
Expand Down
2 changes: 1 addition & 1 deletion src/apim.publish.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { ProductSubscriptionsPublishModule } from "./components/products/product
import { IdentityService } from "./services/identityService";
import { ResetPasswordPublishModule } from "./components/users/reset-password/resetPassword.publish.module";
import { ConfirmPasswordPublishModule } from "./components/users/confirm-password/ko/confirmPassword.module";
import { ChangePasswordPublishModule } from "./components/users/change-password/ko/changePassword.module";
import { ChangePasswordPublishModule } from "./components/users/change-password/changePassword.publish.module";
import { ReportsPublishModule } from "./components/reports/ko/reports.module";
import { TenantService } from "./services/tenantService";
import { ValidationSummaryPublishModule } from "./components/users/validation-summary/validationSummary.publish.module";
Expand Down
2 changes: 2 additions & 0 deletions src/components/react.components.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
declare namespace JSX {
interface IntrinsicElements {
"fui-change-password": any;
"change-password-runtime": any;
"fui-reset-password": any;
"reset-password-runtime": any;
"fui-signup-aad-runtime": any;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { IInjector, IInjectorModule } from "@paperbits/common/injection";
import { IWidgetService } from "@paperbits/common/widgets";
import { KnockoutComponentBinder } from "@paperbits/core/ko";
import { ChangePasswordHandlers } from "../changePasswordHandlers";
import { ChangePasswordModel } from "../changePasswordModel";
import { ChangePasswordModelBinder } from "../changePasswordModelBinder";
import { ChangePasswordEditor } from "./changePasswordEditor";
import { ChangePasswordViewModel } from "./changePasswordViewModel";
import { ReactComponentBinder } from "@paperbits/react/bindings";
import { ChangePasswordHandlers } from "./changePasswordHandlers";
import { ChangePasswordModel } from "./changePasswordModel";
import { ChangePasswordModelBinder } from "./changePasswordModelBinder";
import { ChangePasswordEditor } from "./react/ChangePasswordEditor";
import { ChangePasswordViewModel } from "./react/ChangePasswordViewModel";
import { ChangePasswordViewModelBinder } from "./changePasswordViewModelBinder";
import { ComponentFlow } from "@paperbits/common/components";


export class ChangePasswordEditorModule implements IInjectorModule {
export class ChangePasswordDesignModule implements IInjectorModule {
public register(injector: IInjector): void {
injector.bind("changePasswordEditor", ChangePasswordEditor);
injector.bindSingleton("changePasswordModelBinder", ChangePasswordModelBinder);
Expand All @@ -20,17 +20,18 @@ export class ChangePasswordEditorModule implements IInjectorModule {

widgetService.registerWidget("change-password", {
modelDefinition: ChangePasswordModel,
componentBinder: KnockoutComponentBinder,
componentBinder: ReactComponentBinder,
componentDefinition: ChangePasswordViewModel,
modelBinder: ChangePasswordModelBinder,
viewModelBinder: ChangePasswordViewModelBinder
viewModelBinder: ChangePasswordViewModelBinder,
componentFlow: ComponentFlow.Block
});

widgetService.registerWidgetEditor("change-password", {
displayName: "Password: Change form",
category: "User",
iconClass: "widget-icon widget-icon-api-management",
componentBinder: KnockoutComponentBinder,
componentBinder: ReactComponentBinder,
componentDefinition: ChangePasswordEditor,
handlerComponent: ChangePasswordHandlers
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { IInjector, IInjectorModule } from "@paperbits/common/injection";
import { IWidgetService } from "@paperbits/common/widgets";
import { KnockoutComponentBinder } from "@paperbits/core/ko";
import { ChangePasswordModel } from "../changePasswordModel";
import { ChangePasswordModelBinder } from "../changePasswordModelBinder";
import { ChangePasswordViewModel } from "./changePasswordViewModel";
import { ReactComponentBinder } from "@paperbits/react/bindings";
import { ChangePasswordModel } from "./changePasswordModel";
import { ChangePasswordModelBinder } from "./changePasswordModelBinder";
import { ChangePasswordViewModel } from "./react/ChangePasswordViewModel";
import { ChangePasswordViewModelBinder } from "./changePasswordViewModelBinder";


export class ChangePasswordPublishModule implements IInjectorModule {
public register(injector: IInjector): void {
injector.bindSingleton("changePasswordModelBinder", ChangePasswordModelBinder);
Expand All @@ -16,7 +15,7 @@ export class ChangePasswordPublishModule implements IInjectorModule {

widgetService.registerWidget("change-password", {
modelDefinition: ChangePasswordModel,
componentBinder: KnockoutComponentBinder,
componentBinder: ReactComponentBinder,
componentDefinition: ChangePasswordViewModel,
modelBinder: ChangePasswordModelBinder,
viewModelBinder: ChangePasswordViewModelBinder
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IInjector, IInjectorModule } from "@paperbits/common/injection";
import { registerCustomElement } from "@paperbits/react/customElements";
import { ChangePasswordRuntime } from "./react/runtime/ChangePasswordRuntime";
import { ChangePasswordRuntime } from "./react/ChangePasswordRuntime";

export class ChangePasswordRuntimeModule implements IInjectorModule {
public register(injector: IInjector): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { ISettingsProvider } from "@paperbits/common/configuration";
import { StyleCompiler } from "@paperbits/common/styles";
import { ISiteService } from "@paperbits/common/sites";
import { ViewModelBinder, WidgetState } from "@paperbits/common/widgets";
import { ChangePasswordModel } from "../changePasswordModel";
import { ChangePasswordViewModel } from "./changePasswordViewModel";
import { isRedesignEnabledSetting } from "../../../../constants";
import { ChangePasswordModel } from "./changePasswordModel";
import { ChangePasswordViewModel } from "./react/ChangePasswordViewModel";
import { isRedesignEnabledSetting } from "../../../constants";

export class ChangePasswordViewModelBinder implements ViewModelBinder<ChangePasswordModel, ChangePasswordViewModel> {
constructor(
Expand All @@ -14,17 +14,15 @@ export class ChangePasswordViewModelBinder implements ViewModelBinder<ChangePass
) { }

public stateToInstance(state: WidgetState, componentInstance: ChangePasswordViewModel): void {
componentInstance.styles(state.styles);
componentInstance.isRedesignEnabled(state.isRedesignEnabled);

componentInstance.runtimeConfig(JSON.stringify({
requireHipCaptcha: state.requireHipCaptcha
}));
componentInstance.setState(prevState => ({
isRedesignEnabled: state.isRedesignEnabled,
requireHipCaptcha: state.requireHipCaptcha,
styles: state.styles}));
}

public async modelToState(model: ChangePasswordModel, state: WidgetState): Promise<void> {
const useHipCaptcha = await this.settingsProvider.getSetting<boolean>("useHipCaptcha");
state.requireHipCaptcha = useHipCaptcha === undefined ? true : useHipCaptcha;
state.requireHipCaptcha = useHipCaptcha ?? true;

if (model.styles) {
state.styles = await this.styleCompiler.getStyleModelAsync(model.styles);
Expand Down
6 changes: 0 additions & 6 deletions src/components/users/change-password/ko/changePassword.html

This file was deleted.

This file was deleted.

33 changes: 0 additions & 33 deletions src/components/users/change-password/ko/changePasswordEditor.ts

This file was deleted.

21 changes: 0 additions & 21 deletions src/components/users/change-password/ko/changePasswordViewModel.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from "react";
import { ChangePasswordModel } from "../changePasswordModel";

export class ChangePasswordEditor extends React.Component {
public state: any;
private onChange: any;
private model: ChangePasswordModel;

constructor(props) {
super(props);

this.onChange = props.onChange;
this.model = props.model;

this.onPropertyChange = this.onPropertyChange.bind(this);

this.state = {
requireHipCaptcha: this.model.requireHipCaptcha
};
}

public onPropertyChange(event: any): void {
this.model.requireHipCaptcha = event.target.checked;
this.setState({ requireHipCaptcha: this.model.requireHipCaptcha });

if (this.onChange) {
this.onChange(this.model);
}
}

public render(): JSX.Element {
return (
<fieldset className="form flex-item flex-item-grow">
<div className="form-group">
<label htmlFor="requireHipCaptcha" className="form-label">
<input type="checkbox" id="requireHipCaptcha" checked={this.state.requireHipCaptcha} onChange={this.onPropertyChange} /> Require HipCaptcha on submit
</label>
</div>
</fieldset>
);
}
}
97 changes: 97 additions & 0 deletions src/components/users/change-password/react/ChangePasswordForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import * as React from "react";
import { useCallback } from "react";
import { Stack } from "@fluentui/react";
import { Body1Strong } from "@fluentui/react-components";
import { BackendService } from "../../../../services/backendService";
import { BtnSpinner } from "../../../utils/react/BtnSpinner";
import { HipCaptcha } from "../../runtime/hip-captcha/react";
import { TCaptchaObj, TOnInitComplete } from "../../runtime/hip-captcha/react/LegacyCaptcha";

export type TSubmit = (
password: string,
newPassword: string,
passwordConfirmation: string,
captchaObj: TCaptchaObj,
) => Promise<boolean>;

type ChangePasswordFormProps = {
requireHipCaptcha: boolean
backendService: BackendService
submit: TSubmit
}

export const ChangePasswordForm = ({
requireHipCaptcha,
backendService,
submit,
}: ChangePasswordFormProps) => {
const [password, setPassword] = React.useState<string>("");
const [newPassword, setNewPassword] = React.useState<string>("");
const [passwordConfirmation, setPasswordConfirmation] = React.useState<string>("");
const [captchaObj, setCaptchaObj] = React.useState<TCaptchaObj>();
const [isSubmitted, setIsSubmitted] = React.useState(false);

const handleSubmit = async () => submit(password, newPassword, passwordConfirmation, captchaObj).then(setIsSubmitted);

const onInitComplete: TOnInitComplete = useCallback((captchaValid, refreshCaptcha, captchaData) => {
setCaptchaObj({ captchaValid, refreshCaptcha, captchaData });
}, []);

if (isSubmitted) return (
<>
<Body1Strong>Your password was successfully updated</Body1Strong>
</>
);

return (
<>
<Stack className="form-group">
<label htmlFor="password" className="required">Password</label>
<input
id="password"
placeholder="Enter password"
type="password"
className="form-control"
value={password}
onChange={(event) => setPassword(event.target.value)}
/>
</Stack>
<Stack className="form-group">
<label htmlFor="new-password" className="required">New password</label>
<input
id="new-password"
placeholder="Enter new password"
type="password"
className="form-control"
value={newPassword}
onChange={(event) => setNewPassword(event.target.value)}
/>
</Stack>
<Stack className="form-group">
<label htmlFor="confirm-password" className="required">Confirm password</label>
<input
id="confirm-password"
placeholder="Enter new password again"
type="password"
className="form-control"
value={passwordConfirmation}
onChange={(event) => setPasswordConfirmation(event.target.value)}
/>
</Stack>

{requireHipCaptcha && (
<HipCaptcha
backendService={backendService}
onInitComplete={onInitComplete}
/>
)}

<BtnSpinner
onClick={handleSubmit}
className="button button-primary"
>
Change
</BtnSpinner>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { Resolve } from "@paperbits/react/decorators";
import { EventManager } from "@paperbits/common/events";
import { Logger } from "@paperbits/common/logging";
import { FluentProvider } from "@fluentui/react-components";
import { UsersService } from "../../../../../services";
import { BackendService } from "../../../../../services/backendService";
import { ChangePasswordRequest } from "../../../../../contracts/resetRequest";
import * as Constants from "../../../../../constants";
import { validateBasic } from "../../../../utils/react/validateBasic";
import { ValidationMessages } from "../../../validationMessages";
import { ErrorSources } from "../../../validation-summary/constants";
import { dispatchErrors, parseAndDispatchError } from "../../../validation-summary/utils";
import { UsersService } from "../../../../services";
import { BackendService } from "../../../../services/backendService";
import { ChangePasswordRequest } from "../../../../contracts/resetRequest";
import * as Constants from "../../../../constants";
import { validateBasic } from "../../../utils/react/validateBasic";
import { ValidationMessages } from "../../validationMessages";
import { ErrorSources } from "../../validation-summary/constants";
import { dispatchErrors, parseAndDispatchError } from "../../validation-summary/utils";
import { ChangePasswordForm, TSubmit } from "./ChangePasswordForm";

type ChangePasswordRuntimeProps = {
Expand Down
Loading

0 comments on commit e275954

Please sign in to comment.