mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 01:18:23 +00:00
new controllers for components and layouts
This commit is contained in:
parent
ec58c5cbd0
commit
08274d53ff
12 changed files with 130 additions and 41 deletions
|
|
@ -60,8 +60,6 @@ export const Container = ({
|
|||
[JSON.stringify(appDefinition), currentPageId]
|
||||
);
|
||||
|
||||
console.log('----mohaaan components', { components });
|
||||
|
||||
const currentState = useCurrentState();
|
||||
const { appVersionsId, enableReleasedVersionPopupState, isVersionReleased } = useAppVersionStore(
|
||||
(state) => ({
|
||||
|
|
@ -149,6 +147,7 @@ export const Container = ({
|
|||
const noOfBoxs = Object.values(boxes || []).length;
|
||||
useEffect(() => {
|
||||
updateCanvasHeight(boxes);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [noOfBoxs]);
|
||||
|
||||
const moveBox = useCallback(
|
||||
|
|
|
|||
|
|
@ -64,9 +64,10 @@ import { shallow } from 'zustand/shallow';
|
|||
import { useEditorActions, useEditorState, useEditorStore } from '@/_stores/editorStore';
|
||||
import { useAppDataActions, useAppDataStore, useAppInfo } from '@/_stores/appDataStore';
|
||||
import { useMounted } from '@/_hooks/use-mount';
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { camelizeKeys } from 'humps';
|
||||
import { camelizeKeys, decamelizeKeys } from 'humps';
|
||||
|
||||
setAutoFreeze(false);
|
||||
enablePatches();
|
||||
|
|
@ -227,7 +228,6 @@ const EditorComponent = (props) => {
|
|||
}
|
||||
|
||||
if (mounted && didAppDefinitionChanged && currentPageId) {
|
||||
console.log('----mohaaan: useEffecr', { appDefinition });
|
||||
const components = appDefinition?.pages[currentPageId]?.components || {};
|
||||
|
||||
computeComponentState(components);
|
||||
|
|
@ -236,6 +236,7 @@ const EditorComponent = (props) => {
|
|||
autoSave();
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify({ appDefinition, currentPageId, dataQueries })]);
|
||||
|
||||
const editorRef = {
|
||||
|
|
@ -630,6 +631,47 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
//!--------
|
||||
|
||||
const buildComponentMetaDefinition = (components = {}) => {
|
||||
for (const componentId in components) {
|
||||
const currentComponentData = components[componentId];
|
||||
const componentMeta = componentTypes.find((comp) => currentComponentData.component.component === comp.component);
|
||||
|
||||
const mergedDefinition = {
|
||||
...componentMeta.definition,
|
||||
properties: {
|
||||
...componentMeta.definition.properties,
|
||||
...currentComponentData?.component.definition.properties,
|
||||
},
|
||||
|
||||
styles: {
|
||||
...componentMeta.definition.styles,
|
||||
...currentComponentData?.component.definition.styles,
|
||||
},
|
||||
validations: {
|
||||
...componentMeta.definition.validations,
|
||||
...currentComponentData?.component.definition.validations,
|
||||
},
|
||||
};
|
||||
|
||||
const mergedComponent = {
|
||||
component: {
|
||||
...componentMeta,
|
||||
...currentComponentData.component,
|
||||
},
|
||||
layouts: {
|
||||
...currentComponentData.layouts,
|
||||
},
|
||||
withDefaultChildren: componentMeta.withDefaultChildren ?? false,
|
||||
};
|
||||
|
||||
mergedComponent.component.definition = mergedDefinition;
|
||||
|
||||
components[componentId] = mergedComponent;
|
||||
}
|
||||
return components;
|
||||
};
|
||||
|
||||
const buildAppDefinition = (data) => {
|
||||
const editingVersion = _.omit(camelizeKeys(data.editing_version), ['definition', 'updatedAt', 'createdAt', 'name']);
|
||||
|
||||
|
|
@ -637,6 +679,10 @@ const EditorComponent = (props) => {
|
|||
_.unset(editingVersion, 'id');
|
||||
|
||||
const pages = data.pages.reduce((acc, page) => {
|
||||
const currentComponents = buildComponentMetaDefinition(_.cloneDeep(page?.components));
|
||||
|
||||
page.components = currentComponents;
|
||||
|
||||
acc[page.id] = page;
|
||||
|
||||
return acc;
|
||||
|
|
@ -649,6 +695,8 @@ const EditorComponent = (props) => {
|
|||
pages: pages,
|
||||
};
|
||||
|
||||
// const componentMeta = componentTypes.find((comp) => component.component === comp.component);
|
||||
|
||||
return appJSON;
|
||||
};
|
||||
|
||||
|
|
@ -677,7 +725,7 @@ const EditorComponent = (props) => {
|
|||
const homePageId = !startingPageId || startingPageId === 'null' ? appJson.homePageId : startingPageId;
|
||||
|
||||
const currentComponents = appJson.pages[homePageId]?.components ?? {};
|
||||
console.log('---piku [fetching app] [pages] ==> ', { currentComponents });
|
||||
console.log('---arpit [fetching app] [pages] ==> ', { currentComponents });
|
||||
const currentpageData = {
|
||||
handle: appJson.pages[homePageId]?.handle,
|
||||
name: appJson.pages[homePageId]?.name,
|
||||
|
|
@ -727,7 +775,6 @@ const EditorComponent = (props) => {
|
|||
|
||||
// !--------
|
||||
const setAppDefinitionFromVersion = (version, shouldWeEditVersion = true) => {
|
||||
console.log('---arpit [setAppFromVersion]--', version);
|
||||
if (version?.id !== props.editingVersion?.id) {
|
||||
appDefinitionChanged(defaults(version.definition, defaultDefinition(props.darkMode)), {
|
||||
skipAutoSave: true,
|
||||
|
|
@ -783,11 +830,6 @@ const EditorComponent = (props) => {
|
|||
let updatedAppDefinition;
|
||||
const copyOfAppDefinition = JSON.parse(JSON.stringify(appDefinition));
|
||||
|
||||
console.log('--arpit | appDefinitionChanged func()', {
|
||||
opts,
|
||||
newDefinition,
|
||||
});
|
||||
|
||||
updatedAppDefinition = produce(copyOfAppDefinition, (draft) => {
|
||||
if (_.isEmpty(draft)) return;
|
||||
|
||||
|
|
@ -822,6 +864,7 @@ const EditorComponent = (props) => {
|
|||
setUndoStack((prev) => [...prev, undoPatches]);
|
||||
|
||||
updateAppDefinitionDiff(diffPatches);
|
||||
|
||||
updateState({
|
||||
appDiffOptions: opts,
|
||||
});
|
||||
|
|
@ -839,7 +882,6 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const saveEditingVersion = (isUserSwitchedVersion = false) => {
|
||||
console.log('---arpit [saving - editionversion]--', { appDefinitionDiff });
|
||||
if (props.isVersionReleased && !isUserSwitchedVersion) {
|
||||
updateEditorState({
|
||||
isSaving: false,
|
||||
|
|
@ -952,10 +994,10 @@ const EditorComponent = (props) => {
|
|||
canUndo: undoStack.length > 0,
|
||||
canRedo: redoStack.length > 0,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(undoStack), JSON.stringify(redoStack)]);
|
||||
|
||||
const componentDefinitionChanged = (componentDefinition, props) => {
|
||||
console.log('---arpit checking:::: ', { props });
|
||||
if (props?.isVersionReleased) {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
return;
|
||||
|
|
@ -1024,6 +1066,7 @@ const EditorComponent = (props) => {
|
|||
}
|
||||
appDefinitionChanged(newDefinition, {
|
||||
componentDefinitionChanged: true,
|
||||
componentDeleted: true,
|
||||
});
|
||||
handleInspectorView();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ export const EditorKeyHooks = ({
|
|||
removeMultipleComponents,
|
||||
}) => {
|
||||
const handleHotKeysCallback = (key) => {
|
||||
console.log('---arpit-- hotkeys', { key });
|
||||
switch (key) {
|
||||
case 'Escape':
|
||||
handleEditorEscapeKeyPress();
|
||||
|
|
@ -19,7 +18,6 @@ export const EditorKeyHooks = ({
|
|||
removeMultipleComponents();
|
||||
break;
|
||||
case 'KeyD':
|
||||
console.log('---arpit-- paste component');
|
||||
cloneComponents();
|
||||
break;
|
||||
case 'KeyC':
|
||||
|
|
|
|||
|
|
@ -1130,10 +1130,11 @@ export function renderTooltip({ props, text }) {
|
|||
export function computeComponentState(components = {}) {
|
||||
let componentState = {};
|
||||
const currentComponents = getCurrentState().components;
|
||||
|
||||
Object.keys(components).forEach((key) => {
|
||||
const component = components[key];
|
||||
const componentMeta = componentTypes.find((comp) => component.component.component === comp.component);
|
||||
console.log('------tj: computeComponentState', { component, currentComponents });
|
||||
const { component } = components[key];
|
||||
const componentMeta = componentTypes.find((comp) => component.component === comp.component);
|
||||
|
||||
const existingComponentName = Object.keys(currentComponents).find((comp) => currentComponents[comp].id === key);
|
||||
const existingValues = currentComponents[existingComponentName];
|
||||
|
||||
|
|
@ -1149,14 +1150,14 @@ export function computeComponentState(components = {}) {
|
|||
}
|
||||
|
||||
if (!isListView && !isForm) {
|
||||
componentState[component.component.name] = {
|
||||
componentState[component.name] = {
|
||||
...componentMeta.exposedVariables,
|
||||
id: key,
|
||||
...existingValues,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
componentState[component.component.name] = {
|
||||
componentState[component.name] = {
|
||||
...componentMeta.exposedVariables,
|
||||
id: key,
|
||||
...existingValues,
|
||||
|
|
@ -1586,7 +1587,7 @@ export const removeSelectedComponent = (pageId, newDefinition, selectedComponent
|
|||
delete newDefinition.pages[pageId].components[component.id];
|
||||
});
|
||||
|
||||
updateAppDefinition(newDefinition, { componentDefinitionChanged: true });
|
||||
updateAppDefinition(newDefinition, { componentDefinitionChanged: true, componentDeleted: true });
|
||||
};
|
||||
|
||||
const getSelectedText = () => {
|
||||
|
|
|
|||
|
|
@ -60,8 +60,6 @@ function save(appId, versionId, values, isUserSwitchedVersion = false) {
|
|||
return fetch(`${config.apiUrl}/apps/${appId}/versions/${versionId}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
function autoSaveApp(appId, versionId, diff, type, pageId, operation, isUserSwitchedVersion = false) {
|
||||
console.log('---piku [version saved] [v2]', { operation, type, diff });
|
||||
|
||||
const OPERATION = Object.freeze({
|
||||
create: 'POST',
|
||||
update: 'PUT',
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ export const useAppDataStore = create(
|
|||
updateState: (state) => set((prev) => ({ ...prev, ...state })),
|
||||
updateAppDefinitionDiff: (appDefinitionDiff) => set(() => ({ appDefinitionDiff: appDefinitionDiff })),
|
||||
updateAppVersion: async (appId, versionId, pageId, appDefinitionDiff, isUserSwitchedVersion = false) => {
|
||||
// console.log('-piku :: from store', { appDefinitionDiff });
|
||||
return await appVersionService.autoSaveApp(
|
||||
appId,
|
||||
versionId,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ const defaultComponent = {
|
|||
styles: {},
|
||||
validation: {},
|
||||
events: [],
|
||||
type: '',
|
||||
};
|
||||
|
||||
const updateType = Object.freeze({
|
||||
|
|
@ -39,6 +40,7 @@ const updateType = Object.freeze({
|
|||
containerChanges: 'components/layout',
|
||||
componentAdded: 'components',
|
||||
componentDefinitionChanged: 'components',
|
||||
componentDeleted: 'components',
|
||||
});
|
||||
|
||||
export const computeAppDiff = (appDiff, currentPageId, opts) => {
|
||||
|
|
@ -46,10 +48,20 @@ export const computeAppDiff = (appDiff, currentPageId, opts) => {
|
|||
let updateDiff;
|
||||
let operation = 'update';
|
||||
|
||||
console.log('---piku [computeAppDiff]', { appDiff, currentPageId, opts });
|
||||
|
||||
if (opts?.pageDefinitionChanged) {
|
||||
updateDiff = appDiff?.pages[currentPageId];
|
||||
|
||||
type = updateType.pageDefinitionChanged;
|
||||
} else if (opts?.componentDeleted) {
|
||||
const currentPageComponents = appDiff?.pages[currentPageId]?.components;
|
||||
|
||||
updateDiff = _.keys(currentPageComponents);
|
||||
|
||||
type = updateType.componentDeleted;
|
||||
|
||||
operation = 'delete';
|
||||
} else if ((opts?.containerChanges || opts?.componentDefinitionChanged) && !opts?.componentAdded) {
|
||||
const currentPageComponents = appDiff?.pages[currentPageId]?.components;
|
||||
|
||||
|
|
@ -65,16 +77,15 @@ export const computeAppDiff = (appDiff, currentPageId, opts) => {
|
|||
|
||||
result[id] = _.defaultsDeep(metaDiff, defaultComponent);
|
||||
|
||||
result[id].type = componentMeta.component;
|
||||
result[id].layouts = appDiff.pages[currentPageId].components[id].layouts;
|
||||
|
||||
operation = 'create';
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
type = updateType.componentDefinitionChanged;
|
||||
}
|
||||
|
||||
console.log('---piku [currentPageComponents]', { updateDiff, opts, type });
|
||||
|
||||
return { updateDiff, type, operation };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ export class CreateComponentTable1691006952074 implements MigrationInterface {
|
|||
type: 'varchar',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
type: 'varchar',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'page_id',
|
||||
type: 'uuid',
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export class AppsController {
|
|||
|
||||
response['data_queries'] = seralizedQueries;
|
||||
response['definition'] = app.editingVersion?.definition;
|
||||
response['pages'] = decamelizeKeys(pagesForVersion);
|
||||
response['pages'] = pagesForVersion;
|
||||
|
||||
//! if editing version exists, camelize the definition
|
||||
if (app.editingVersion && app.editingVersion.definition) {
|
||||
|
|
@ -320,9 +320,6 @@ export class AppsController {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
// console.log('----arpit apps controller => ', { updateType });
|
||||
|
||||
await this.appsService.updateVersion(version, versionEditDto, app.organizationId);
|
||||
return;
|
||||
}
|
||||
|
|
@ -347,8 +344,6 @@ export class AppsController {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
console.log('----arpit apps controller v2 => ', { versionEditDto });
|
||||
await this.componentsService.create(versionEditDto.diff, versionEditDto.pageId);
|
||||
}
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -372,10 +367,33 @@ export class AppsController {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
console.log('----arpit apps controller v2 [update] => ', { versionEditDto });
|
||||
await this.componentsService.update(versionEditDto.diff);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Delete(':id/versions/:versionId/components')
|
||||
async deleteComponents(
|
||||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() versionEditDto: VersionEditDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
||||
if (app.id !== id) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, id);
|
||||
|
||||
if (!ability.can('updateVersions', app)) {
|
||||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.delete(versionEditDto.diff);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/components/layout')
|
||||
|
|
@ -397,8 +415,6 @@ export class AppsController {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
console.log('----arpit apps controller v2 |layput | [update] => ', { versionEditDto });
|
||||
await this.componentsService.componentLayoutChange(versionEditDto.diff);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ export class Component {
|
|||
@Column({ name: 'name' })
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'type' })
|
||||
type: string;
|
||||
|
||||
@Column({ name: 'page_id' })
|
||||
pageId: string;
|
||||
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ export class AppsService {
|
|||
|
||||
const defaultHomePage = await manager.save(
|
||||
manager.create(Page, {
|
||||
name: 'Home',
|
||||
pageHandle: 'home',
|
||||
name: 'Defualt Page',
|
||||
pageHandle: 'defaultpage',
|
||||
appVersionId: appVersion.id,
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,22 @@ export class ComponentsService {
|
|||
});
|
||||
}
|
||||
|
||||
async delete(componentIds: string[]) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const components = await manager.findByIds(Component, componentIds);
|
||||
|
||||
if (!components.length) {
|
||||
return {
|
||||
error: {
|
||||
message: `Components with ids ${componentIds} do not exist`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
await manager.delete(Component, componentIds);
|
||||
});
|
||||
}
|
||||
|
||||
async componentLayoutChange(componenstLayoutDiff: object) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
for (const componentId in componenstLayoutDiff) {
|
||||
|
|
@ -124,8 +140,6 @@ export class ComponentsService {
|
|||
...layout,
|
||||
};
|
||||
|
||||
console.log('--arpit [layput changed]', { type, layout, componentLayout, newLayout });
|
||||
|
||||
await manager.update(Layout, { id: componentLayout.id }, newLayout);
|
||||
}
|
||||
}
|
||||
|
|
@ -166,6 +180,7 @@ export class ComponentsService {
|
|||
const transformedComponent: Component = new Component();
|
||||
transformedComponent.id = componentId;
|
||||
transformedComponent.name = componentData.name;
|
||||
transformedComponent.type = componentData.type;
|
||||
transformedComponent.properties = componentData.properties || {};
|
||||
transformedComponent.styles = componentData.styles || {};
|
||||
transformedComponent.validations = componentData.validation || {};
|
||||
|
|
@ -184,6 +199,7 @@ export class ComponentsService {
|
|||
[id]: {
|
||||
component: {
|
||||
name,
|
||||
component: componentData.type,
|
||||
definition: {
|
||||
properties,
|
||||
styles,
|
||||
|
|
|
|||
Loading…
Reference in a new issue