Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LPS-129529 Adds the Data representation implementation of Forms to Data Engine #100493

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,87 @@
/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/

import {DataDefinitionSchema} from '../schema/DataDefinition.es';
import {DataLayoutSchema} from '../schema/DataLayout.es';
import {SYMBOL_RAW} from '../schema/Schema.es';

const SCHEMAS_DICTIONARY = {
dataDefinition: DataDefinitionSchema,
dataLayout: DataLayoutSchema,
};

/**
* Context stores all instances of schemas created by key to avoid recreating
* a new instance of the same Schema in different components.
*/
const context = {};

const getProps = (props, keys) =>
keys.reduce((prev, key) => {
prev[key] = props[key];

return prev;
}, {});

/**
* Compare the values of the properties at the reference level, the properties
* should only be for readonly, the raw object and props will always be different
* objects because props contain all the properties of the store but raw only
* the properties that the schema needs.
*/
const isStaleRaw = (props, schema) =>
schema.props.some((key) => props[key] !== schema[SYMBOL_RAW][key]);

const createSchema = (key, props) => {
const Schema = SCHEMAS_DICTIONARY[key];

const raw = getProps(props, Schema.props);
const instance = new Schema(raw);

context[key] = instance;

return instance;
};

const getSchema = (key, props) => {
if (key in context) {
if (isStaleRaw(props, context[key])) {
delete context[key];

return createSchema(key, props);
}

return context[key];
}
else {
return createSchema(key, props);
}
};

const parseSchema = (props, schema) =>
schema.reduce((prev, key) => {
const Schema = getSchema(key, props);

prev[key] = Schema;

return prev;
}, {});

/**
* UseDataView creates a representation of the data based on the passed
* schema otherwise nothing is done. It should not be used directly, it
* is exposed through `useFormState`.
*/
export const useDataView = (props, schema) =>
schema ? parseSchema(props, schema) : props;
Expand Up @@ -17,6 +17,7 @@ import React, {useContext, useReducer, useRef} from 'react';

import {createReducer} from '../reducers/createReducer.es';
import {useConfig} from './useConfig.es';
import {useDataView} from './useDataView.es';

const FormDispatchContext = React.createContext(() => {});

Expand Down Expand Up @@ -163,6 +164,6 @@ export const useForm = () => {
return useContext(FormDispatchContext);
};

export const useFormState = () => {
return useContext(FormStateContext);
export const useFormState = ({schema} = {}) => {
return useDataView(useContext(FormStateContext), schema);
};
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/

import {SYMBOL_RAW, Schema} from './Schema.es';

export class DataDefinitionSchema extends Schema {
static props = ['availableLanguageIds'];

constructor(raw) {
super('data_engine', 'dataDefinition', raw);
}

get availableLanguageIds() {
return this[SYMBOL_RAW].availableLanguageIds;
}
}
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/

import {SYMBOL_RAW, Schema} from './Schema.es';

export class DataLayoutRowSchema extends Schema {
constructor(raw) {
super('data_engine', 'dataLayoutRow', raw);
}

get dataLayoutColumns() {
return this[SYMBOL_RAW].columns.map((column) => ({
columnSize: column.size,
fieldNames: column.fields.map(({fieldName}) => fieldName),
}));
}
}

export class DataLayoutPageSchema extends Schema {
constructor(raw) {
super('data_engine', 'dataLayoutPage', raw);
}

get dataLayoutRows() {
return this[SYMBOL_RAW].rows.map((row) => new DataLayoutRowSchema(row));
}

get description() {
return this[SYMBOL_RAW].localizedDescription;
}

get title() {
return this[SYMBOL_RAW].localizedTitle;
}
}

export class DataLayoutSchema extends Schema {
static props = ['pages', 'rules'];

constructor(raw) {
super('data_engine', 'dataLayout', raw);
}

get dataRules() {
return this[SYMBOL_RAW].rules;
}

get dataLayoutPages() {
return this[SYMBOL_RAW].pages.map(
(page) => new DataLayoutPageSchema(page)
);
}
}
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/

const SYMBOL_CONTEXT = Symbol('schema.context');

const SYMBOL_TYPE = Symbol('schema.type');

export const SYMBOL_RAW = Symbol('schema.raw');

export class Schema {
constructor(context, type, raw) {
this[SYMBOL_CONTEXT] = context;
this[SYMBOL_TYPE] = type;
this[SYMBOL_RAW] = raw;
}
}