mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 08:58:26 +00:00
updating components and pages into seperate tables
This commit is contained in:
parent
b132098c4c
commit
ec58c5cbd0
16 changed files with 442 additions and 69 deletions
|
|
@ -60,6 +60,8 @@ export const Container = ({
|
|||
[JSON.stringify(appDefinition), currentPageId]
|
||||
);
|
||||
|
||||
console.log('----mohaaan components', { components });
|
||||
|
||||
const currentState = useCurrentState();
|
||||
const { appVersionsId, enableReleasedVersionPopupState, isVersionReleased } = useAppVersionStore(
|
||||
(state) => ({
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ import { useAppDataActions, useAppDataStore, useAppInfo } from '@/_stores/appDat
|
|||
import { useMounted } from '@/_hooks/use-mount';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { camelizeKeys } from 'humps';
|
||||
|
||||
setAutoFreeze(false);
|
||||
enablePatches();
|
||||
|
|
@ -226,6 +227,7 @@ const EditorComponent = (props) => {
|
|||
}
|
||||
|
||||
if (mounted && didAppDefinitionChanged && currentPageId) {
|
||||
console.log('----mohaaan: useEffecr', { appDefinition });
|
||||
const components = appDefinition?.pages[currentPageId]?.components || {};
|
||||
|
||||
computeComponentState(components);
|
||||
|
|
@ -345,13 +347,9 @@ const EditorComponent = (props) => {
|
|||
theme: { name: props?.darkMode ? 'dark' : 'light' },
|
||||
urlparams: JSON.parse(JSON.stringify(queryString.parse(props.location.search))),
|
||||
};
|
||||
const page = {
|
||||
...props?.currentState?.page,
|
||||
handle: props?.pageHandle,
|
||||
variables: {},
|
||||
};
|
||||
|
||||
updateState({ appId: props?.params?.id });
|
||||
useCurrentStateStore.getState().actions.setCurrentState({ globals, page });
|
||||
useCurrentStateStore.getState().actions.setCurrentState({ globals });
|
||||
};
|
||||
|
||||
const fetchDataQueries = async (id, selectFirstQuery = false, runQueriesOnAppLoad = false) => {
|
||||
|
|
@ -632,6 +630,29 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
//!--------
|
||||
const buildAppDefinition = (data) => {
|
||||
const editingVersion = _.omit(camelizeKeys(data.editing_version), ['definition', 'updatedAt', 'createdAt', 'name']);
|
||||
|
||||
editingVersion['currentVersionId'] = editingVersion.id;
|
||||
_.unset(editingVersion, 'id');
|
||||
|
||||
const pages = data.pages.reduce((acc, page) => {
|
||||
acc[page.id] = page;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const appJSON = {
|
||||
globalSettings: editingVersion.globalSettings,
|
||||
homePageId: editingVersion.homePageId,
|
||||
showHideViewerNavigation: editingVersion.showHideViewerNavigation ?? true,
|
||||
pages: pages,
|
||||
};
|
||||
|
||||
return appJSON;
|
||||
};
|
||||
|
||||
//****** */
|
||||
|
||||
const fetchApp = async (startingPageHandle) => {
|
||||
const _appId = props?.params?.id;
|
||||
|
|
@ -641,12 +662,30 @@ const EditorComponent = (props) => {
|
|||
useAppVersionStore.getState().actions.updateReleasedVersionId(data.current_version_id);
|
||||
await fetchDataSources(data.editing_version?.id);
|
||||
await fetchDataQueries(data.editing_version?.id, true, true);
|
||||
console.log('---piku [fetching app]---]', { data, defaultDef: defaultDefinition(props.darkMode) });
|
||||
let dataDefinition = data.definition ?? defaults(data.definition, defaultDefinition(props.darkMode));
|
||||
const appDefData = buildAppDefinition(data);
|
||||
|
||||
const pages = Object.entries(dataDefinition.pages).map(([pageId, page]) => ({ id: pageId, ...page }));
|
||||
// let dataDefinition = data.definition ?? defaults(data.definition, defaultDefinition(props.darkMode));
|
||||
|
||||
// const pages = Object.entries(dataDefinition.pages).map(([pageId, page]) => ({ id: pageId, ...page }));
|
||||
// const startingPageId = pages.filter((page) => page.handle === startingPageHandle)[0]?.id;
|
||||
// const homePageId = !startingPageHandle || startingPageId === 'null' ? dataDefinition.homePageId : startingPageId;
|
||||
|
||||
// !------
|
||||
const appJson = appDefData;
|
||||
const pages = data.pages;
|
||||
const startingPageId = pages.filter((page) => page.handle === startingPageHandle)[0]?.id;
|
||||
const homePageId = !startingPageHandle || startingPageId === 'null' ? dataDefinition.homePageId : startingPageId;
|
||||
const homePageId = !startingPageId || startingPageId === 'null' ? appJson.homePageId : startingPageId;
|
||||
|
||||
const currentComponents = appJson.pages[homePageId]?.components ?? {};
|
||||
console.log('---piku [fetching app] [pages] ==> ', { currentComponents });
|
||||
const currentpageData = {
|
||||
handle: appJson.pages[homePageId]?.handle,
|
||||
name: appJson.pages[homePageId]?.name,
|
||||
id: homePageId,
|
||||
variables: {},
|
||||
};
|
||||
|
||||
// !------
|
||||
|
||||
setCurrentPageId(homePageId);
|
||||
|
||||
|
|
@ -662,20 +701,15 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: {
|
||||
handle: dataDefinition.pages[homePageId]?.handle,
|
||||
name: dataDefinition.pages[homePageId]?.name,
|
||||
id: homePageId,
|
||||
variables: {},
|
||||
},
|
||||
page: currentpageData,
|
||||
});
|
||||
|
||||
updateEditorState({
|
||||
isLoading: false,
|
||||
appDefinition: dataDefinition,
|
||||
appDefinition: appJson,
|
||||
});
|
||||
|
||||
for (const event of dataDefinition.pages[homePageId]?.events ?? []) {
|
||||
for (const event of appJson.pages[homePageId]?.events ?? []) {
|
||||
await handleEvent(event.eventId, event);
|
||||
}
|
||||
getCanvasWidth();
|
||||
|
|
@ -813,9 +847,7 @@ const EditorComponent = (props) => {
|
|||
} else if (!isEmpty(props?.editingVersion)) {
|
||||
const componentDiff = computeAppDiff(appDefinitionDiff, currentPageId, appDiffOptions);
|
||||
|
||||
// console.log('---piku [componentDiff]--', componentDiff);
|
||||
|
||||
updateAppVersion(appId, props.editingVersion?.id, appDefinition, componentDiff, isUserSwitchedVersion)
|
||||
updateAppVersion(appId, props.editingVersion?.id, currentPageId, componentDiff, isUserSwitchedVersion)
|
||||
.then(() => {
|
||||
const _editingVersion = {
|
||||
...props.editingVersion,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export const LeftSidebarInspector = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appDefinition['selectedComponent']]);
|
||||
const currentState = useCurrentState();
|
||||
|
||||
const queries = {};
|
||||
|
||||
if (!_.isEmpty(dataQueries)) {
|
||||
|
|
|
|||
|
|
@ -1133,7 +1133,7 @@ export function computeComponentState(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 existingComponentName = Object.keys(currentComponents).find((comp) => currentComponents[comp].id === key);
|
||||
const existingValues = currentComponents[existingComponentName];
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export const appVersionService = {
|
|||
create,
|
||||
del,
|
||||
save,
|
||||
autoSaveApp,
|
||||
};
|
||||
|
||||
function getAll(appId) {
|
||||
|
|
@ -44,7 +45,7 @@ function del(appId, versionId) {
|
|||
}
|
||||
|
||||
function save(appId, versionId, values, isUserSwitchedVersion = false) {
|
||||
console.log('---piku [version saved]', { values });
|
||||
// console.log('---piku [version saved]', { values });
|
||||
const body = { is_user_switched_version: isUserSwitchedVersion };
|
||||
if (values.definition) body['definition'] = values.definition;
|
||||
if (values.name) body['name'] = values.name;
|
||||
|
|
@ -58,3 +59,22 @@ 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',
|
||||
delete: 'DELETE',
|
||||
});
|
||||
|
||||
const body = { is_user_switched_version: isUserSwitchedVersion, pageId, diff: diff };
|
||||
|
||||
const requestOptions = {
|
||||
method: OPERATION[operation],
|
||||
headers: authHeader(),
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
return fetch(`${config.apiUrl}/apps/${appId}/versions/${versionId}/${type}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,15 @@ export const useAppDataStore = create(
|
|||
updateApps: (apps) => set(() => ({ apps: apps })),
|
||||
updateState: (state) => set((prev) => ({ ...prev, ...state })),
|
||||
updateAppDefinitionDiff: (appDefinitionDiff) => set(() => ({ appDefinitionDiff: appDefinitionDiff })),
|
||||
updateAppVersion: async (appId, versionId, appDefinition, appDefinitionDiff, isUserSwitchedVersion = false) => {
|
||||
return await appVersionService.save(
|
||||
updateAppVersion: async (appId, versionId, pageId, appDefinitionDiff, isUserSwitchedVersion = false) => {
|
||||
// console.log('-piku :: from store', { appDefinitionDiff });
|
||||
return await appVersionService.autoSaveApp(
|
||||
appId,
|
||||
versionId,
|
||||
{ definition: appDefinition, diff: appDefinitionDiff },
|
||||
appDefinitionDiff.updateDiff,
|
||||
appDefinitionDiff.type,
|
||||
pageId,
|
||||
appDefinitionDiff.operation,
|
||||
isUserSwitchedVersion
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const defaultComponent = {
|
|||
|
||||
const updateType = Object.freeze({
|
||||
pageDefinitionChanged: 'pages',
|
||||
containerChanges: 'layout',
|
||||
containerChanges: 'components/layout',
|
||||
componentAdded: 'components',
|
||||
componentDefinitionChanged: 'components',
|
||||
});
|
||||
|
|
@ -44,6 +44,7 @@ const updateType = Object.freeze({
|
|||
export const computeAppDiff = (appDiff, currentPageId, opts) => {
|
||||
let type;
|
||||
let updateDiff;
|
||||
let operation = 'update';
|
||||
|
||||
if (opts?.pageDefinitionChanged) {
|
||||
updateDiff = appDiff?.pages[currentPageId];
|
||||
|
|
@ -64,9 +65,10 @@ export const computeAppDiff = (appDiff, currentPageId, opts) => {
|
|||
|
||||
result[id] = _.defaultsDeep(metaDiff, defaultComponent);
|
||||
|
||||
result[id].layouts = appDiff.pages[currentPageId].components[id].layouts;
|
||||
|
||||
operation = 'create';
|
||||
return result;
|
||||
// result[id].componentId = id;
|
||||
// return { ..._.defaultsDeep(metaDiff, defaultComponent), componentId: id };
|
||||
}, {});
|
||||
|
||||
type = updateType.componentDefinitionChanged;
|
||||
|
|
@ -74,5 +76,5 @@ export const computeAppDiff = (appDiff, currentPageId, opts) => {
|
|||
|
||||
console.log('---piku [currentPageComponents]', { updateDiff, opts, type });
|
||||
|
||||
return { updateDiff, type };
|
||||
return { updateDiff, type, operation };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,24 +12,31 @@ export class CreateLayoutTable1691007037021 implements MigrationInterface {
|
|||
isPrimary: true,
|
||||
default: 'gen_random_uuid()',
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
type: 'varchar',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
type: 'varchar',
|
||||
type: 'enum',
|
||||
enumName: 'layput_type',
|
||||
enum: ['desktop', 'mobile'],
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'top',
|
||||
type: 'integer',
|
||||
type: 'double precision',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'left',
|
||||
type: 'integer',
|
||||
type: 'double precision',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'width',
|
||||
type: 'double precision',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'double precision',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { ValidAppInterceptor } from 'src/interceptors/valid.app.interceptor';
|
|||
import { AppDecorator } from 'src/decorators/app.decorator';
|
||||
|
||||
import { ComponentsService } from '@services/components.service';
|
||||
import { PageService } from '@services/page.service';
|
||||
|
||||
@Controller('apps')
|
||||
export class AppsController {
|
||||
|
|
@ -36,6 +37,7 @@ export class AppsController {
|
|||
private appsService: AppsService,
|
||||
private foldersService: FoldersService,
|
||||
private componentsService: ComponentsService,
|
||||
private pageService: PageService,
|
||||
private appsAbilityFactory: AppsAbilityFactory
|
||||
) {}
|
||||
|
||||
|
|
@ -88,9 +90,7 @@ export class AppsController {
|
|||
? await this.appsService.findDataQueriesForVersion(app.editingVersion.id)
|
||||
: [];
|
||||
|
||||
const pagesForVersion = app.editingVersion ? await this.appsService.findPagesForVersion(app.editingVersion.id) : [];
|
||||
|
||||
console.log('------arpit [pagesforVersion]', { pagesForVersion });
|
||||
const pagesForVersion = app.editingVersion ? await this.pageService.findPagesForVersion(app.editingVersion.id) : [];
|
||||
|
||||
// serialize queries
|
||||
for (const query of dataQueriesForVersion) {
|
||||
|
|
@ -320,16 +320,87 @@ 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 });
|
||||
|
||||
// if(updateType=== 'components') {
|
||||
// await this.componentsService.createOrUpdate(versionEditDto.app_diff.components, versionId)
|
||||
// }
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
// console.log('----arpit apps controller => ', { updateType });
|
||||
|
||||
await this.appsService.updateVersion(version, versionEditDto, app.organizationId);
|
||||
return;
|
||||
}
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Post(':id/versions/:versionId/components')
|
||||
async createComponent(
|
||||
@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');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
console.log('----arpit apps controller v2 => ', { versionEditDto });
|
||||
await this.componentsService.create(versionEditDto.diff, versionEditDto.pageId);
|
||||
}
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/components')
|
||||
async updateComponent(
|
||||
@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');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
console.log('----arpit apps controller v2 [update] => ', { versionEditDto });
|
||||
await this.componentsService.update(versionEditDto.diff);
|
||||
}
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/components/layout')
|
||||
async updateComponentLayput(
|
||||
@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');
|
||||
}
|
||||
|
||||
// const updateType = versionEditDto.app_diff?.type;
|
||||
console.log('----arpit apps controller v2 |layput | [update] => ', { versionEditDto });
|
||||
await this.componentsService.componentLayoutChange(versionEditDto.diff);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
|
|
|
|||
12
server/src/controllers/apps.controller.v2.ts
Normal file
12
server/src/controllers/apps.controller.v2.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
// import { JwtAuthGuard } from '../../src/modules/auth/jwt-auth.guard';
|
||||
|
||||
@Controller({
|
||||
path: 'apps',
|
||||
version: '2', // Set the version to '2'
|
||||
})
|
||||
export class AppsControllerV2 {
|
||||
constructor(/* Add your services and dependencies here */) {}
|
||||
|
||||
// Add your new version 2 methods here
|
||||
}
|
||||
|
|
@ -22,5 +22,9 @@ export class VersionEditDto {
|
|||
is_user_switched_version: boolean;
|
||||
|
||||
@IsOptional()
|
||||
app_diff: any;
|
||||
diff: any;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
pageId: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||
import { Component } from './component.entity';
|
||||
|
||||
@Entity({ name: 'layouts' })
|
||||
|
|
@ -6,21 +6,25 @@ export class Layout {
|
|||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ name: 'name' })
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'type' })
|
||||
@Column({ type: 'enum', enumName: 'layout_type', name: 'type', enum: ['desktop', 'mobile'] })
|
||||
type: string;
|
||||
|
||||
@Column({ name: 'top' })
|
||||
@Column({ name: 'top', type: 'double precision' })
|
||||
top: number;
|
||||
|
||||
@Column({ name: 'left' })
|
||||
@Column({ name: 'left', type: 'double precision' })
|
||||
left: number;
|
||||
|
||||
@Column({ name: 'width', type: 'double precision' })
|
||||
width: number;
|
||||
|
||||
@Column({ name: 'height', type: 'double precision' })
|
||||
height: number;
|
||||
|
||||
@Column({ name: 'component_id' })
|
||||
ComponentId: string;
|
||||
componentId: string;
|
||||
|
||||
@ManyToOne(() => Component, (component) => component.layouts)
|
||||
@JoinColumn({ name: 'component_id' })
|
||||
component: Component;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import { EventHandler } from 'src/entities/event_handler.entity';
|
|||
import { Layout } from 'src/entities/layout.entity';
|
||||
|
||||
import { ComponentsService } from '@services/components.service';
|
||||
import { PageService } from '@services/page.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -80,6 +81,7 @@ import { ComponentsService } from '@services/components.service';
|
|||
PluginsHelper,
|
||||
AppEnvironmentService,
|
||||
ComponentsService,
|
||||
PageService,
|
||||
],
|
||||
controllers: [AppsController, AppUsersController, AppsImportExportController],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -386,15 +386,6 @@ export class AppsService {
|
|||
});
|
||||
}
|
||||
|
||||
async findPagesForVersion(appVersionId: string): Promise<Page[]> {
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return manager
|
||||
.createQueryBuilder(Page, 'pages')
|
||||
.where('pages.appVersionId = :appVersionId', { appVersionId }) // Replace 'AppVersionId' with the actual column name
|
||||
.getMany();
|
||||
});
|
||||
}
|
||||
|
||||
async createNewDataSourcesAndQueriesForVersion(
|
||||
manager: EntityManager,
|
||||
appVersion: AppVersion,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Component } from 'src/entities/component.entity'; // Adjust the import path as per your project structure
|
||||
import { EntityManager, Repository } from 'typeorm';
|
||||
import { Component } from 'src/entities/component.entity';
|
||||
import { Layout } from 'src/entities/layout.entity';
|
||||
import { Page } from 'src/entities/page.entity';
|
||||
import { dbTransactionWrap } from 'src/helpers/utils.helper';
|
||||
|
||||
@Injectable()
|
||||
export class ComponentsService {
|
||||
|
|
@ -14,7 +17,190 @@ export class ComponentsService {
|
|||
return this.componentsRepository.findOne(id);
|
||||
}
|
||||
|
||||
async createOrUpdate(componentDiff: any) {
|
||||
console.log('----arpit:::: component service', { componentDiff });
|
||||
async create(componentDiff: object, pageId: string) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const page = await manager.findOne(Page, pageId);
|
||||
|
||||
const newComponents = this.transformComponentData(componentDiff);
|
||||
const componentLayouts = [];
|
||||
|
||||
newComponents.forEach((component) => {
|
||||
component.page = page;
|
||||
});
|
||||
|
||||
const savedComponents = await manager.save(Component, newComponents);
|
||||
|
||||
savedComponents.forEach((component) => {
|
||||
const componentLayout = componentDiff[component.id].layouts;
|
||||
|
||||
if (componentLayout) {
|
||||
for (const type in componentLayout) {
|
||||
const layout = componentLayout[type];
|
||||
const newLayout = new Layout();
|
||||
newLayout.type = type;
|
||||
newLayout.top = layout.top;
|
||||
newLayout.left = layout.left;
|
||||
newLayout.width = layout.width;
|
||||
newLayout.height = layout.height;
|
||||
newLayout.component = component;
|
||||
|
||||
componentLayouts.push(newLayout);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await manager.save(Layout, componentLayouts);
|
||||
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
async update(componentDiff: object) {
|
||||
return dbTransactionWrap(async (manager) => {
|
||||
for (const componentId in componentDiff) {
|
||||
const { component } = componentDiff[componentId];
|
||||
|
||||
const componentData = await manager.findOne(Component, componentId);
|
||||
|
||||
if (!componentData) {
|
||||
return {
|
||||
error: {
|
||||
message: `Component with id ${componentId} does not exist`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const isComponentDefinitionChanged = component.definition ? true : false;
|
||||
|
||||
if (isComponentDefinitionChanged) {
|
||||
const updatedDefinition = component.definition;
|
||||
const columnsUpdated = Object.keys(updatedDefinition);
|
||||
|
||||
const newComponentData = columnsUpdated.reduce((acc, column) => {
|
||||
const newColumnData = {
|
||||
...componentData[column],
|
||||
...updatedDefinition[column],
|
||||
};
|
||||
|
||||
acc[column] = newColumnData;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
await manager.update(Component, componentId, newComponentData);
|
||||
return;
|
||||
}
|
||||
|
||||
await manager.update(Component, componentId, component);
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async componentLayoutChange(componenstLayoutDiff: object) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
for (const componentId in componenstLayoutDiff) {
|
||||
const { layouts } = componenstLayoutDiff[componentId];
|
||||
|
||||
const componentLayout = await manager.findOne(Layout, { componentId });
|
||||
|
||||
if (!componentLayout) {
|
||||
return {
|
||||
error: {
|
||||
message: `Component with id ${componentId} does not exist`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
for (const type in layouts) {
|
||||
const layout = {
|
||||
type,
|
||||
...layouts[type],
|
||||
};
|
||||
const currentLayout = Object.assign({}, componentLayout);
|
||||
|
||||
const newLayout = {
|
||||
...currentLayout,
|
||||
...layout,
|
||||
};
|
||||
|
||||
console.log('--arpit [layput changed]', { type, layout, componentLayout, newLayout });
|
||||
|
||||
await manager.update(Layout, { id: componentLayout.id }, newLayout);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async getAllComponents(pageId: string) {
|
||||
// need to get all components for a page with their layouts
|
||||
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return manager
|
||||
.createQueryBuilder(Component, 'component')
|
||||
.leftJoinAndSelect('component.layouts', 'layout')
|
||||
.where('component.pageId = :pageId', { pageId })
|
||||
.getMany()
|
||||
.then((components) => {
|
||||
return components.reduce((acc, component) => {
|
||||
const componentId = component.id;
|
||||
const componentData = component;
|
||||
const componentLayout = component.layouts[0];
|
||||
|
||||
const transformedData = this.createComponentWithLayout(componentData, componentLayout);
|
||||
|
||||
acc[componentId] = transformedData[componentId];
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
transformComponentData(data: object): Component[] {
|
||||
const transformedComponents: Component[] = [];
|
||||
|
||||
for (const componentId in data) {
|
||||
const componentData = data[componentId];
|
||||
|
||||
const transformedComponent: Component = new Component();
|
||||
transformedComponent.id = componentId;
|
||||
transformedComponent.name = componentData.name;
|
||||
transformedComponent.properties = componentData.properties || {};
|
||||
transformedComponent.styles = componentData.styles || {};
|
||||
transformedComponent.validations = componentData.validation || {};
|
||||
|
||||
transformedComponents.push(transformedComponent);
|
||||
}
|
||||
|
||||
return transformedComponents;
|
||||
}
|
||||
|
||||
createComponentWithLayout(componentData, layoutData) {
|
||||
const { id, name, properties, styles, validations } = componentData;
|
||||
const { type, top, left, width, height } = layoutData;
|
||||
|
||||
const componentWithLayout = {
|
||||
[id]: {
|
||||
component: {
|
||||
name,
|
||||
definition: {
|
||||
properties,
|
||||
styles,
|
||||
validations,
|
||||
},
|
||||
},
|
||||
layouts: {
|
||||
[type]: {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return componentWithLayout;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
35
server/src/services/page.service.ts
Normal file
35
server/src/services/page.service.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, Repository } from 'typeorm';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Page } from 'src/entities/page.entity';
|
||||
import { ComponentsService } from './components.service';
|
||||
|
||||
@Injectable()
|
||||
export class PageService {
|
||||
constructor(
|
||||
private readonly manager: EntityManager,
|
||||
@InjectRepository(Page)
|
||||
private readonly pageRepository: Repository<Page>,
|
||||
|
||||
private componentsService: ComponentsService
|
||||
) {}
|
||||
|
||||
async findPagesForVersion(appVersionId: string): Promise<Page[]> {
|
||||
const allPages = await this.pageRepository.find({ appVersionId });
|
||||
|
||||
const pagesWithComponents = await Promise.all(
|
||||
allPages.map(async (page) => {
|
||||
const components = await this.componentsService.getAllComponents(page.id);
|
||||
delete page.appVersionId;
|
||||
return { ...page, components };
|
||||
})
|
||||
);
|
||||
|
||||
return pagesWithComponents;
|
||||
}
|
||||
|
||||
async findOne(id: string): Promise<Page> {
|
||||
return this.pageRepository.findOne(id);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue