Skip to content

Commit

Permalink
fix: fix filepicker component merge error
Browse files Browse the repository at this point in the history
  • Loading branch information
vsgoulart committed Oct 23, 2024
1 parent 2105c6d commit 89bc5b1
Show file tree
Hide file tree
Showing 24 changed files with 520 additions and 305 deletions.
3 changes: 2 additions & 1 deletion packages/form-js-carbon-styles/src/carbon-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,8 @@ const RADIO_STYLES = css`

const BUTTON_STYLES = css`
.fjs-container {
.fjs-form-field.fjs-form-field-button .fjs-button {
.fjs-form-field.fjs-form-field-button .fjs-button,
.fjs-form-field.fjs-form-field-filepicker .fjs-button {
font-size: var(--cds-body-short-01-font-size);
font-weight: var(--cds-body-short-01-font-weight);
line-height: var(--cds-body-short-01-line-height);
Expand Down
3 changes: 2 additions & 1 deletion packages/form-js-carbon-styles/src/carbon-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,8 @@
// Button styles /////////////

.fjs-container {
.fjs-form-field.fjs-form-field-button .fjs-button {
.fjs-form-field.fjs-form-field-button .fjs-button,
.fjs-form-field.fjs-form-field-filepicker .fjs-button {
font-size: var(--cds-body-short-01-font-size);
font-weight: var(--cds-body-short-01-font-weight);
line-height: var(--cds-body-short-01-line-height);
Expand Down
6 changes: 6 additions & 0 deletions packages/form-js-carbon-styles/test/spec/complex.json
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,12 @@
"height": 30,
"id": "Field_1a82jjsdasd"
},
{
"type": "filepicker",
"key": "filepicker",
"accept": ".png,.jpg",
"multiple": true
},
{
"action": "reset",
"label": "reset",
Expand Down
3 changes: 2 additions & 1 deletion packages/form-js-playground/src/components/PlaygroundRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ export function PlaygroundRoot(config) {

// pipe viewer changes to output data editor
formViewer.on('changed', updateOutputData);
formViewer.on('formFieldInstanceRegistry.changed', updateOutputData);
formViewer.on('formFieldInstance.added', updateOutputData);
formViewer.on('formFieldInstance.removed', updateOutputData);

inputDataEditor.on('changed', (event) => {
try {
Expand Down
6 changes: 6 additions & 0 deletions packages/form-js-playground/test/spec/form.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"$schema": "../../../form-json-schema/resources/schema.json",
"components": [
{
"type": "filepicker",
"key": "filepicker",
"accept": ".png,.jpg",
"multiple": true
},
{
"type": "expression",
"key": "expressionResult",
Expand Down
5 changes: 4 additions & 1 deletion packages/form-js-viewer/src/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class Form {
/**
* Submit the form, triggering all field validations.
*
* @returns { { data: Data, errors: Errors } }
* @returns { { data: Data, errors: Errors, files: Map<string, File[]> } }
*/
submit() {
const { properties } = this._getState();
Expand All @@ -168,9 +168,12 @@ export class Form {

const errors = this.validate();

const files = this.get('fileRegistry').getAllFiles();

const result = {
data,
errors,
files,
};

this._emit('submit', result);
Expand Down
60 changes: 37 additions & 23 deletions packages/form-js-viewer/src/core/FormFieldInstanceRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,50 @@ export class FormFieldInstanceRegistry {
eventBus.on('form.clear', () => this.clear());
}

add(instance) {
const { id, expressionContextInfo, valuePath, indexes } = instance;

const instanceId = [id, ...Object.values(indexes || {})].join('_');

if (this._formFieldInstances[instanceId]) {
throw new Error('this form field instance is already registered');
syncInstance(instanceId, formFieldInfo) {
const { hidden, ...restInfo } = formFieldInfo;

const isInstanceExpected = !hidden;
const doesInstanceExist = this._formFieldInstances[instanceId];

if (isInstanceExpected && !doesInstanceExist) {
this._formFieldInstances[instanceId] = {
instanceId,
...restInfo,
};

this._eventBus.fire('formFieldInstance.added', { instanceId });
} else if (!isInstanceExpected && doesInstanceExist) {
delete this._formFieldInstances[instanceId];

this._eventBus.fire('formFieldInstance.removed', { instanceId });
} else if (isInstanceExpected && doesInstanceExist) {
const wasInstanceChaged = Object.keys(restInfo).some((key) => {
return this._formFieldInstances[instanceId][key] !== restInfo[key];
});

if (wasInstanceChaged) {
this._formFieldInstances[instanceId] = {
instanceId,
...restInfo,
};

this._eventBus.fire('formFieldInstance.changed', { instanceId });
}
}

this._formFieldInstances[instanceId] = {
id,
instanceId,
expressionContextInfo,
valuePath,
indexes,
};

this._eventBus.fire('formFieldInstanceRegistry.changed', { instanceId, action: 'added' });

return instanceId;
}

remove(instanceId) {
if (!this._formFieldInstances[instanceId]) {
return;
cleanupInstance(instanceId) {
if (this._formFieldInstances[instanceId]) {
delete this._formFieldInstances[instanceId];
this._eventBus.fire('formFieldInstance.removed', { instanceId });
}
}

delete this._formFieldInstances[instanceId];

this._eventBus.fire('formFieldInstanceRegistry.changed', { instanceId, action: 'removed' });
get(instanceId) {
return this._formFieldInstances[instanceId];
}

getAll() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@ export class ConditionChecker {
// if we have a hidden repeatable field, and the data structure allows, we clear it directly at the root and stop recursion
if (context.isHidden && isRepeatable) {
context.preventRecursion = true;
this._eventBus.fire('conditionChecker.remove', {
item: { [field.key]: get(workingData, getFilterPath(field, indexes)) },
});
this._cleanlyClearDataAtPath(getFilterPath(field, indexes), workingData);
}

// for simple leaf fields, we always clear
if (context.isHidden && isClosed) {
this._eventBus.fire('conditionChecker.remove', {
item: { [field.key]: get(workingData, getFilterPath(field, indexes)) },
});
this._cleanlyClearDataAtPath(getFilterPath(field, indexes), workingData);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ import { useScrollIntoView } from '../../render/hooks';
import classNames from 'classnames';

export class RepeatRenderManager {
constructor(form, formFields, formFieldRegistry, pathRegistry) {
constructor(form, formFields, formFieldRegistry, pathRegistry, eventBus) {
this._form = form;
/** @type {import('../../render/FormFields').FormFields} */
this._formFields = formFields;
/** @type {import('../../core/FormFieldRegistry').FormFieldRegistry} */
this._formFieldRegistry = formFieldRegistry;
/** @type {import('../../core/PathRegistry').PathRegistry} */
this._pathRegistry = pathRegistry;
/** @type {import('../../core/EventBus').EventBus} */
this._eventBus = eventBus;
this.Repeater = this.Repeater.bind(this);
this.RepeatFooter = this.RepeatFooter.bind(this);
}
Expand Down Expand Up @@ -58,12 +63,14 @@ export class RepeatRenderManager {
const hasChildren = repeaterField.components && repeaterField.components.length > 0;
const showRemove = repeaterField.allowAddRemove && hasChildren;

const displayValues = isCollapsed ? values.slice(0, nonCollapsedItems) : values;
const hiddenValues = isCollapsed ? values.slice(nonCollapsedItems) : [];

/**
* @param {number} index
*/
const onDeleteItem = (index) => {
const updatedValues = values.slice();
updatedValues.splice(index, 1);
const removedItem = updatedValues.splice(index, 1)[0];

this._eventBus.fire('repeatRenderManager.remove', { dataPath, index, item: removedItem });

props.onChange({
field: repeaterField,
Expand All @@ -76,38 +83,24 @@ export class RepeatRenderManager {

return (
<>
{displayValues.map((itemValue, itemIndex) => (
<RepetitionScaffold
key={itemIndex}
itemIndex={itemIndex}
itemValue={itemValue}
parentExpressionContextInfo={parentExpressionContextInfo}
repeaterField={repeaterField}
RowsRenderer={RowsRenderer}
indexes={indexes}
onDeleteItem={onDeleteItem}
showRemove={showRemove}
{...restProps}
/>
))}
{hiddenValues.length > 0 ? (
<div className="fjs-repeat-row-collapsed">
{hiddenValues.map((itemValue, itemIndex) => (
<RepetitionScaffold
key={itemIndex}
itemIndex={itemIndex + nonCollapsedItems}
itemValue={itemValue}
parentExpressionContextInfo={parentExpressionContextInfo}
repeaterField={repeaterField}
RowsRenderer={RowsRenderer}
indexes={indexes}
onDeleteItem={onDeleteItem}
showRemove={showRemove}
{...restProps}
/>
))}
{values.map((itemValue, itemIndex) => (
<div
class={classNames({
'fjs-repeat-row-collapsed': isCollapsed ? itemIndex >= nonCollapsedItems : false,
})}>
<RepetitionScaffold
itemIndex={itemIndex}
itemValue={itemValue}
parentExpressionContextInfo={parentExpressionContextInfo}
repeaterField={repeaterField}
RowsRenderer={RowsRenderer}
indexes={indexes}
onDeleteItem={onDeleteItem}
showRemove={showRemove}
{...restProps}
/>
</div>
) : null}
))}
</>
);
}
Expand Down Expand Up @@ -146,6 +139,8 @@ export class RepeatRenderManager {

shouldScroll.current = true;

this._eventBus.fire('repeatRenderManager.add', { dataPath, index: updatedValues.length - 1, item: newItem });

props.onChange({
value: updatedValues,
});
Expand Down Expand Up @@ -186,7 +181,7 @@ export class RepeatRenderManager {
<button type="button" class="fjs-repeat-render-collapse" onClick={toggle}>
{isCollapsed ? (
<>
<ExpandSvg /> {`Expand all (${values.length})`}
<ExpandSvg /> {`Expand all (${values.length - 1})`}
</>
) : (
<>
Expand Down Expand Up @@ -277,4 +272,4 @@ const RepetitionScaffold = (props) => {
);
};

RepeatRenderManager.$inject = ['form', 'formFields', 'formFieldRegistry', 'pathRegistry'];
RepeatRenderManager.$inject = ['form', 'formFields', 'formFieldRegistry', 'pathRegistry', 'eventBus'];
91 changes: 91 additions & 0 deletions packages/form-js-viewer/src/render/FileRegistry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { extractFileReferencesFromRemovedData } from '../util/extractFileReferencesFromRemovedData';

const fileRegistry = Symbol('fileRegistry');
const eventBusSymbol = Symbol('eventBus');
const formFieldRegistrySymbol = Symbol('formFieldRegistry');
const formFieldInstanceRegistrySymbol = Symbol('formFieldInstanceRegistry');
const EMPTY_ARRAY = [];

class FileRegistry {
/**
* @param {import('../core/EventBus').EventBus} eventBus
* @param {import('../core/FormFieldRegistry').FormFieldRegistry} formFieldRegistry
* @param {import('../core/FormFieldInstanceRegistry').FormFieldInstanceRegistry} formFieldInstanceRegistry
*/
constructor(eventBus, formFieldRegistry, formFieldInstanceRegistry) {
/** @type {Map<string, File[]>} */
this[fileRegistry] = new Map();
/** @type {import('../core/EventBus').EventBus} */
this[eventBusSymbol] = eventBus;
/** @type {import('../core/FormFieldRegistry').FormFieldRegistry} */
this[formFieldRegistrySymbol] = formFieldRegistry;
/** @type {import('../core/FormFieldInstanceRegistry').FormFieldInstanceRegistry} */
this[formFieldInstanceRegistrySymbol] = formFieldInstanceRegistry;

const removeFileHandler = ({ item }) => {
const fileReferences = extractFileReferencesFromRemovedData(item);

// Remove all file references from the registry
fileReferences.forEach((fileReference) => {
this.deleteFiles(fileReference);
});
};

eventBus.on('form.clear', () => this.clear());
eventBus.on('conditionChecker.remove', removeFileHandler);
eventBus.on('repeatRenderManager.remove', removeFileHandler);
}

/**
* @param {string} id
* @param {File[]} files
*/
setFiles(id, files) {
this[fileRegistry].set(id, files);
}

/**
* @param {string} id
* @returns {File[]}
*/
getFiles(id) {
return this[fileRegistry].get(id) || EMPTY_ARRAY;
}

/**
* @returns {string[]}
*/
getKeys() {
return Array.from(this[fileRegistry].keys());
}

/**
* @param {string} id
* @returns {boolean}
*/
hasKey(id) {
return this[fileRegistry].has(id);
}

/**
* @param {string} id
*/
deleteFiles(id) {
this[fileRegistry].delete(id);
}

/**
* @returns {Map<string, File[]>}
*/
getAllFiles() {
return new Map(this[fileRegistry]);
}

clear() {
this[fileRegistry].clear();
}
}

FileRegistry.$inject = ['eventBus', 'formFieldRegistry', 'formFieldInstanceRegistry'];

export { FileRegistry };
Loading

0 comments on commit 89bc5b1

Please sign in to comment.