-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* define edit validation rules and EditForm * apply edit validation rules and display in ui * move edit dataSource management into edit form * remove cypress test thats no longert applicable * add edit conformetion prompt
- Loading branch information
Showing
58 changed files
with
1,503 additions
and
867 deletions.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
vuu-ui/packages/vuu-data-react/src/data-editing/EditForm.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
.EditForm { | ||
display: flex; | ||
flex-direction: column; | ||
gap: var(--salt-spacing-400); | ||
height: 100%; | ||
padding: var(--salt-spacing-200) var(--salt-spacing-200) | ||
var(--salt-spacing-200) var(--salt-spacing-400); | ||
width: 100%; | ||
} | ||
|
||
.EditForm-form-fields { | ||
display: flex; | ||
flex-direction: column; | ||
gap: var(--salt-spacing-400); | ||
} | ||
|
||
.EditForm-buttons { | ||
align-items: center; | ||
display: flex; | ||
gap: var(--salt-spacing-200); | ||
justify-content: flex-end; | ||
} | ||
|
||
.EditForm-field { | ||
display: flex; | ||
|
||
.saltFormField { | ||
flex: 1 1 auto; | ||
} | ||
|
||
.EditForm-edit-indicator { | ||
flex: 0 0 14px; | ||
position: relative; | ||
} | ||
|
||
&[data-edited="true"] { | ||
.EditForm-edit-indicator:after { | ||
background-color: var(--salt-content-secondary-foreground); | ||
border-radius: 5px; | ||
content: ""; | ||
height: 10px; | ||
position: absolute; | ||
top: 50%; | ||
right: -3px; | ||
width: 10px; | ||
} | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
vuu-ui/packages/vuu-data-react/src/data-editing/EditForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { getDataItemEditControl } from "@finos/vuu-data-react"; | ||
import { DataSource, DataValueDescriptor } from "@finos/vuu-data-types"; | ||
import { Button, FormField, FormFieldLabel } from "@salt-ds/core"; | ||
import { useComponentCssInjection } from "@salt-ds/styles"; | ||
import { useWindow } from "@salt-ds/window"; | ||
import cx from "clsx"; | ||
import { HTMLAttributes } from "react"; | ||
import { registerRules } from "./edit-validation-rules"; | ||
import { useEditForm } from "./useEditForm"; | ||
|
||
import editFormCss from "./EditForm.css"; | ||
|
||
const classBase = "EditForm"; | ||
|
||
registerRules(); | ||
|
||
export interface EditFormProps extends HTMLAttributes<HTMLDivElement> { | ||
dataSource?: DataSource; | ||
formFieldDescriptors: DataValueDescriptor[]; | ||
onSubmit?: () => void; | ||
} | ||
|
||
export const EditForm = ({ | ||
className, | ||
dataSource, | ||
formFieldDescriptors, | ||
onSubmit: onSubmitProp, | ||
...htmlAttributes | ||
}: EditFormProps) => { | ||
const targetWindow = useWindow(); | ||
useComponentCssInjection({ | ||
testId: "vuu-edit-form", | ||
css: editFormCss, | ||
window: targetWindow, | ||
}); | ||
|
||
const { | ||
editedFields, | ||
editEntity, | ||
errorMessages, | ||
formFieldsContainerRef, | ||
isClean, | ||
ok, | ||
onCancel, | ||
onChange, | ||
onCommit, | ||
onFocus, | ||
onSubmit, | ||
} = useEditForm({ | ||
dataSource, | ||
formFieldDescriptors, | ||
onSubmit: onSubmitProp, | ||
}); | ||
|
||
return ( | ||
<div | ||
{...htmlAttributes} | ||
className={cx(classBase, className)} | ||
onFocus={onFocus} | ||
> | ||
<div className={`${classBase}-form-fields`} ref={formFieldsContainerRef}> | ||
{formFieldDescriptors.map((dataDescriptor) => { | ||
const { name, label = name } = dataDescriptor; | ||
const errorMessage = errorMessages[name]; | ||
const isEdited = !isClean && editedFields.includes(name); | ||
|
||
return ( | ||
<div | ||
className={`${classBase}-field`} | ||
key={name} | ||
data-edited={isEdited} | ||
> | ||
<FormField data-field={name}> | ||
<FormFieldLabel>{label}</FormFieldLabel> | ||
{getDataItemEditControl({ | ||
InputProps: { | ||
onChange, | ||
value: editEntity?.[name]?.toString() ?? "", | ||
}, | ||
dataDescriptor, | ||
errorMessage, | ||
onCommit, | ||
})} | ||
</FormField> | ||
<div className={`${classBase}-edit-indicator`} /> | ||
</div> | ||
); | ||
})} | ||
</div> | ||
<div className={`${classBase}-buttons`}> | ||
<Button disabled={isClean} onClick={onCancel}> | ||
Cancel | ||
</Button> | ||
<Button onClick={onSubmit} disabled={!ok || isClean}> | ||
Save | ||
</Button> | ||
</div> | ||
</div> | ||
); | ||
}; |
22 changes: 22 additions & 0 deletions
22
vuu-ui/packages/vuu-data-react/src/data-editing/UnsavedChangesReport.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
.vuuUnsavedChanges-table { | ||
border-collapse: collapse; | ||
width: 100%; | ||
} | ||
|
||
.vuuUnsavedChanges-row { | ||
box-sizing: content-box; | ||
border-bottom: solid 1px var(--salt-separable-secondary-borderColor); | ||
height: 32px; | ||
|
||
td { | ||
padding: 0 var(--salt-spacing-200); | ||
} | ||
} | ||
|
||
.vuuUnsavedChanges-fieldName { | ||
text-transform: capitalize; | ||
} | ||
|
||
.vuuUnsavedChanges-new { | ||
font-weight: bold; | ||
} |
43 changes: 43 additions & 0 deletions
43
vuu-ui/packages/vuu-data-react/src/data-editing/UnsavedChangesReport.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { Entity } from "@finos/vuu-utils"; | ||
import { useComponentCssInjection } from "@salt-ds/styles"; | ||
import { useWindow } from "@salt-ds/window"; | ||
import { buildFormEditState } from "./form-edit-state"; | ||
|
||
import unsavedChangesCss from "./UnsavedChangesReport.css"; | ||
|
||
const classBase = "vuuUnsavedChanges"; | ||
|
||
export interface UnsavedChangesReportProps<T extends Entity = Entity> { | ||
entity: T; | ||
editedEntity: T; | ||
} | ||
|
||
export const UnsavedChangesReport = ({ | ||
entity, | ||
editedEntity, | ||
}: UnsavedChangesReportProps) => { | ||
const targetWindow = useWindow(); | ||
useComponentCssInjection({ | ||
testId: "vuu-unsaved-changes-report", | ||
css: unsavedChangesCss, | ||
window: targetWindow, | ||
}); | ||
|
||
const { editedFields } = buildFormEditState(entity, editedEntity); | ||
|
||
return ( | ||
<div className={classBase}> | ||
<table className={`${classBase}-table`}> | ||
<tbody> | ||
{editedFields.map((fieldName, i) => ( | ||
<tr className={`${classBase}-row`} key={i}> | ||
<td className={`${classBase}-fieldName`}>{fieldName}</td> | ||
<td className={`${classBase}-old`}>{entity[fieldName]}</td> | ||
<td className={`${classBase}-new`}>{editedEntity[fieldName]}</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
</div> | ||
); | ||
}; |
43 changes: 0 additions & 43 deletions
43
vuu-ui/packages/vuu-data-react/src/data-editing/date-editing-utils.tsx
This file was deleted.
Oops, something went wrong.
51 changes: 51 additions & 0 deletions
51
vuu-ui/packages/vuu-data-react/src/data-editing/edit-rule-validation-checker.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import type { | ||
DataValueDescriptor, | ||
DataValueValidationChecker, | ||
DataValueValidationResult, | ||
EditRuleValidationSuccessResult, | ||
EditValidationRule, | ||
} from "@finos/vuu-data-types"; | ||
import type { VuuRowDataItemType } from "@finos/vuu-protocol-types"; | ||
import { getEditRuleValidator, isTypeDescriptor } from "@finos/vuu-utils"; | ||
|
||
export const OK: EditRuleValidationSuccessResult = { ok: true }; | ||
|
||
const NO_VALIDATION_RULES: EditValidationRule[] = [] as const; | ||
|
||
export function getEditValidationRules( | ||
descriptor: DataValueDescriptor, | ||
apply: "change" | "commit", | ||
) { | ||
if (isTypeDescriptor(descriptor.type)) { | ||
return ( | ||
descriptor.type.rules?.filter(({ apply: a = "commit" }) => a === apply) ?? | ||
NO_VALIDATION_RULES | ||
); | ||
} | ||
|
||
return NO_VALIDATION_RULES; | ||
} | ||
|
||
export const buildValidationChecker = | ||
(rules: EditValidationRule[]): DataValueValidationChecker => | ||
(value?: VuuRowDataItemType) => | ||
applyRules(rules, value); | ||
|
||
function applyRules(rules: EditValidationRule[], value?: VuuRowDataItemType) { | ||
const result: { ok: boolean; messages?: string[] } = { ok: true }; | ||
for (const rule of rules) { | ||
const applyRuleToValue = getEditRuleValidator(rule.name); | ||
if (applyRuleToValue) { | ||
const res = applyRuleToValue(rule, value); | ||
if (!res.ok) { | ||
result.ok = false; | ||
(result.messages ?? (result.messages = [])).push(res.message); | ||
} | ||
} else { | ||
throw Error( | ||
`editable-utils applyRules, no validator registered for rule '${rule.name}'`, | ||
); | ||
} | ||
} | ||
return result as DataValueValidationResult; | ||
} |
54 changes: 54 additions & 0 deletions
54
vuu-ui/packages/vuu-data-react/src/data-editing/edit-validation-rules.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { registerComponent } from "@finos/vuu-utils"; | ||
import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; | ||
import { EditRuleValidator } from "@finos/vuu-data-types"; | ||
import { OK } from "./edit-rule-validation-checker"; | ||
|
||
const isString = (value?: VuuRowDataItemType): value is string => | ||
typeof value === "string"; | ||
|
||
const NUMERIC = /^(?:[0-9]|\.)+$/; | ||
|
||
const CharValidatorNumeric: EditRuleValidator = (rule, value) => { | ||
if (isString(value)) { | ||
if (value.trim() === "") { | ||
return OK; | ||
} else if (value.match(NUMERIC)) { | ||
return OK; | ||
} | ||
} | ||
return { ok: false, message: "only numeric characters are permitted" }; | ||
}; | ||
|
||
const ValueValidatorInteger: EditRuleValidator = (rule, value) => { | ||
if (isString(value)) { | ||
if (value.trim() === "") { | ||
return OK; | ||
} else { | ||
if (!value.match(NUMERIC)) { | ||
return { | ||
ok: false, | ||
message: "value must be an integer, invalid character", | ||
}; | ||
} | ||
if (parseFloat(value) === parseInt(value)) { | ||
return OK; | ||
} | ||
} | ||
} | ||
return { ok: false, message: "must be an integer value" }; | ||
}; | ||
|
||
export const registerRules = () => { | ||
registerComponent( | ||
"char-numeric", | ||
CharValidatorNumeric, | ||
"data-edit-validator", | ||
{}, | ||
); | ||
registerComponent( | ||
"value-integer", | ||
ValueValidatorInteger, | ||
"data-edit-validator", | ||
{}, | ||
); | ||
}; |
Oops, something went wrong.