Added move and delete functionality

This commit is contained in:
Sergej Schwabauer 2023-04-13 16:38:08 +02:00
parent cd0e96834c
commit 2b3da349b0
7 changed files with 145 additions and 34 deletions

View File

@ -3,6 +3,7 @@ import styles from './PasswordVault.module.scss';
import { cssClasses, isNullOrEmpty } from '@spfxappdev/utility';
import { ActionButton, Callout, Icon, TooltipHost, DirectionalHint } from 'office-ui-fabric-react';
import { ModuleType } from '@src/models';
import * as strings from 'PasswordVaultWebPartStrings';
export interface IAddNewModuleProps {
onModuleSelected(module: ModuleType): void;
@ -29,14 +30,14 @@ export default class AddNewModule extends React.Component<IAddNewModuleProps, IA
<div className={cssClasses(styles["separator-container"], isCallOutVisibleClass)}>
<button type="button"
aria-haspopup="true"
aria-label="Add a new control"
aria-label={strings.AddNewModuleLabel}
ref={(ref: HTMLButtonElement) => { this.addNewButtonRef = ref }}
onClick={() => {
this.setState({
showAddNewCallout: true
});
}}>
<TooltipHost content="Add a new secured module"
<TooltipHost content={strings.AddNewModuleLabel}
// id={this.WebPart.instanceId + "_addNewControl"}
>
<Icon iconName="Add" />
@ -70,15 +71,15 @@ export default class AddNewModule extends React.Component<IAddNewModuleProps, IA
}}
>
<ActionButton iconProps={{iconName: "PasswordField"}} onClick={() => { this.onModuleSelected(ModuleType.PasswordField); }}>
<div>Password</div>
<div>{strings.PasswordModuleLabel}</div>
</ActionButton>
<ActionButton iconProps={{iconName: "UserOptional"}} onClick={() => { this.onModuleSelected(ModuleType.UserField); }}>
<div>Username</div>
<div>{strings.UsernameModuleLabel}</div>
</ActionButton>
<ActionButton iconProps={{iconName: "EditNote"}} onClick={() => { this.onModuleSelected(ModuleType.NoteField); }}>
<div>Note</div>
<div>{strings.NoteModuleLabel}</div>
</ActionButton>
</Callout>
</>

View File

@ -27,7 +27,7 @@ export default class NoteField extends React.Component<INoteFieldProps, INoteFie
}
private renderDisplayMode(): JSX.Element {
return (<><Label>{strings.NoteLabel}</Label>
return (<>
<RichText
isEditMode={false}
value={this.props.defaultValue}

View File

@ -79,9 +79,43 @@
opacity: 1;
}
}
.edit-container {
border: dotted 1px $ms-color-themePrimary;
&--header {
background-color: $ms-color-neutralLighter;
.delete-btn {
float: right;
}
button:disabled,
button[disabled] {
cursor: not-allowed;
i {
color: $ms-color-neutralTertiaryAlt;
}
}
}
&--content {
padding: 10px;
}
}
}
:global {
.ql-editor
{
padding: 0px !important;
}
.ql-editor[contenteditable='true'] {
padding: 8px 10px !important;
}
.addnew-callout {
display: block;

View File

@ -3,10 +3,8 @@ import styles from './PasswordVault.module.scss';
import { SPFxAppDevWebPartComponent, ISPFxAppDevWebPartComponentProps } from '@spfxappdev/framework';
import PasswordVaultWebPart from '../PasswordVaultWebPart';
import { IPasswordVaultService } from '@src/services/PasswordVaultService';
import { Callout, DefaultButton, DirectionalHint, Icon, ITextField, Label, MessageBar, MessageBarType, PrimaryButton, TextField } from 'office-ui-fabric-react';
import { DefaultButton, IconButton, MessageBar, MessageBarType, PrimaryButton, TextField } from 'office-ui-fabric-react';
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
import { RichText } from "@pnp/spfx-controls-react/lib/RichText";
import { IVaultData } from '@src/models/IVaultData';
import * as strings from 'PasswordVaultWebPartStrings';
import AddNewModule from './AddNewModule';
import { IModule, ModuleType } from '@src/models';
@ -31,11 +29,7 @@ export interface IPasswordVaultProps extends ISPFxAppDevWebPartComponentProps<Pa
modules?: IModule[];
}
//TODO:
// Header Module????
// Filter/Search for combination?
// "Change Password" as command button, only if vault already have set a master password
// Delete Module
// Change Order of module
export default class PasswordVault extends SPFxAppDevWebPartComponent<PasswordVaultWebPart, IPasswordVaultProps, IPasswordVaultState> {
@ -150,8 +144,6 @@ export default class PasswordVault extends SPFxAppDevWebPartComponent<PasswordVa
}
private renderEditMode(): JSX.Element {
const wp: PasswordVaultWebPart = this.WebPart;
const showForm: boolean = this.state.isVaultOpen;
return (
@ -250,26 +242,60 @@ export default class PasswordVault extends SPFxAppDevWebPartComponent<PasswordVa
</div>
<div className="spfxappdev-grid-row" key={module.id}>
<div className="spfxappdev-grid-col spfxappdev-sm12">
{module.type == ModuleType.UserField &&
<UserField defaultValue={this.decryptedModuleData[module.id]} tabIndex={index} onChange={(newVal: string) => {
this.decryptedModuleData[module.id] = newVal;
}} isDisplayMode={false} />
}
<div className={styles["edit-container"]}>
<div className={styles["edit-container--header"]}>
<IconButton
className={styles["delete-btn"]}
iconProps={{ iconName: "Delete"}}
title={strings.DeleteModuleLabel}
onClick={() => {
this.onDeleteModule(index);
}}
/>
{module.type == ModuleType.PasswordField &&
<PasswordField defaultValue={this.decryptedModuleData[module.id]} tabIndex={index} onChange={(newVal: string) => {
this.decryptedModuleData[module.id] = newVal;
}} isDisplayMode={false} />
}
<IconButton
iconProps={{ iconName: "Up"}}
title={strings.MoveUpLabel}
disabled={this.state.modules.length === 1 || index === 0}
onClick={() => {
this.onMoveUp(index);
}}
/>
{module.type == ModuleType.NoteField &&
<NoteField defaultValue={this.decryptedModuleData[module.id]} onChange={(newVal: string) => {
<IconButton
iconProps={{ iconName: "Down"}}
title={strings.MoveDownLabel}
disabled={this.state.modules.length === 1 || this.state.modules.length - 1 === index}
onClick={() => {
this.onMoveDown(index);
}}
/>
</div>
this.decryptedModuleData[module.id] = newVal;
<div className={styles["edit-container--content"]}>
{module.type == ModuleType.UserField &&
<UserField defaultValue={this.decryptedModuleData[module.id]} tabIndex={index} onChange={(newVal: string) => {
this.decryptedModuleData[module.id] = newVal;
}} isDisplayMode={false} />
}
return newVal;
}} isDisplayMode={false} />
}
{module.type == ModuleType.PasswordField &&
<PasswordField defaultValue={this.decryptedModuleData[module.id]} tabIndex={index} onChange={(newVal: string) => {
this.decryptedModuleData[module.id] = newVal;
}} isDisplayMode={false} />
}
{module.type == ModuleType.NoteField &&
<NoteField defaultValue={this.decryptedModuleData[module.id]} onChange={(newVal: string) => {
this.decryptedModuleData[module.id] = newVal;
return newVal;
}} isDisplayMode={false} />
}
</div>
</div>
</div>
</div>
</>
@ -387,7 +413,6 @@ export default class PasswordVault extends SPFxAppDevWebPartComponent<PasswordVa
}
private onAddNewModule(moduleType: ModuleType, index: number): void {
console.log("add new Module", moduleType);
const module: IModule = {
id: Guid.newGuid().toString(),
@ -406,4 +431,34 @@ export default class PasswordVault extends SPFxAppDevWebPartComponent<PasswordVa
modules: this.state.modules
});
}
private onDeleteModule(index: number): void {
this.state.modules.RemoveAt(index);
this.setState({
modules: this.state.modules
});
}
private onMoveUp(index: number): void {
const prevModule: IModule = this.state.modules[index-1];
this.state.modules[index-1] = this.state.modules[index];
this.state.modules[index] = prevModule;
this.setState({
modules: this.state.modules
});
}
private onMoveDown(index: number): void {
this.state.modules.RemoveAt(index);
this.setState({
modules: this.state.modules
});
}
}

View File

@ -14,6 +14,13 @@ define([], function() {
"OpenVaultLabel": "Tresor entsperren",
"UsernameCopiedLabel": "Benutzername kopiert",
"PasswordCopiedLabel": "Passwort kopiert",
"DontLoseMasterpasswordLabel": "Wenn Sie das Master passwort vergessen, können Sie den Tresor nicht mehr entsperren und alle Daten gehen verloren. Es ist nicht möglich das Passwort wiederherzustellen."
"DontLoseMasterpasswordLabel": "Wenn Sie das Master passwort vergessen, können Sie den Tresor nicht mehr entsperren und alle Daten gehen verloren. Es ist nicht möglich das Passwort wiederherzustellen.",
"AddNewModuleLabel": "Ein neues Modul hinzufügen",
"DeleteModuleLabel": "Modul löschen",
"MoveUpLabel": "Nach oben verschieben",
"MoveDownLabel": "Nach unten verschieben",
"PasswordModuleLabel": "Passwort",
"UsernameModuleLabel": "Benutzername",
"NoteModuleLabel": "Notiz",
}
});

View File

@ -14,6 +14,13 @@ define([], function() {
"OpenVaultLabel": "Open vault",
"UsernameCopiedLabel": "Username copied",
"PasswordCopiedLabel": "Password copied",
"DontLoseMasterpasswordLabel": "If you forget the master password, you will not be able to unlock the vault and all data will be lost. It is not possible to recover the password."
"DontLoseMasterpasswordLabel": "If you forget the master password, you will not be able to unlock the vault and all data will be lost. It is not possible to recover the password.",
"AddNewModuleLabel": "Add a new secured module",
"DeleteModuleLabel": "Delete",
"MoveUpLabel": "Move up",
"MoveDownLabel": "Move down",
"PasswordModuleLabel": "Password",
"UsernameModuleLabel": "Username",
"NoteModuleLabel": "Note",
}
});

View File

@ -14,6 +14,13 @@ declare interface IPasswordVaultWebPartStrings {
UsernameCopiedLabel: string;
PasswordCopiedLabel: string;
DontLoseMasterpasswordLabel: string;
AddNewModuleLabel: string;
DeleteModuleLabel: string;
MoveUpLabel: string;
MoveDownLabel: string;
PasswordModuleLabel: string;
UsernameModuleLabel: string;
NoteModuleLabel: string;
}
declare module 'PasswordVaultWebPartStrings' {