mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
fix workflow executions in modularistion (#12124)
This commit is contained in:
parent
ae3142dd4e
commit
528c354ed5
9 changed files with 102 additions and 17 deletions
|
|
@ -7,7 +7,6 @@ import { getWorkspaceId, decodeEntities } from '@/_helpers/utils';
|
|||
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
|
||||
import { useDataSources, useGlobalDataSources, useSampleDataSource } from '@/_stores/dataSourcesStore';
|
||||
import { useDataQueriesActions } from '@/_stores/dataQueriesStore';
|
||||
import { staticDataSources as staticDatasources } from '../constants';
|
||||
import { useQueryPanelActions } from '@/_stores/queryPanelStore';
|
||||
import Search from '@/_ui/Icon/solidIcons/Search';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
|
|
@ -16,7 +15,7 @@ import { canCreateDataSource } from '@/_helpers';
|
|||
import './../queryManager.theme.scss';
|
||||
import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
|
||||
|
||||
function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSources, onNewNode, defaultDataSources }) {
|
||||
function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSources, onNewNode, staticDataSources }) {
|
||||
const dataSources = useDataSources();
|
||||
const globalDataSources = useGlobalDataSources();
|
||||
const sampleDataSource = useSampleDataSource();
|
||||
|
|
@ -33,11 +32,6 @@ function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSourc
|
|||
closePopup();
|
||||
};
|
||||
|
||||
const workflowsEnabled = window.public_config?.ENABLE_WORKFLOWS_FEATURE == 'true';
|
||||
const staticDataSources = workflowsEnabled
|
||||
? staticDatasources
|
||||
: staticDatasources.filter((ds) => ds?.kind !== 'workflows');
|
||||
|
||||
useEffect(() => {
|
||||
const shouldAddSampleDataSource = !!sampleDataSource;
|
||||
const allDataSources = [...dataSources, ...globalDataSources, shouldAddSampleDataSource && sampleDataSource].filter(
|
||||
|
|
@ -148,7 +142,7 @@ function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSourc
|
|||
</div>
|
||||
),
|
||||
isDisabled: true,
|
||||
options: defaultDataSources?.map((source) => ({
|
||||
options: staticDataSources?.map((source) => ({
|
||||
label: (
|
||||
<div>
|
||||
<DataSourceIcon source={source} height={16} />{' '}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ export const DATA_SOURCE_TYPE = {
|
|||
LOCAL: 'local',
|
||||
GLOBAL: 'global',
|
||||
STATIC: 'static',
|
||||
DEFAULT: 'default',
|
||||
};
|
||||
|
||||
export const SAMPLE_DB_KIND = {
|
||||
|
|
|
|||
|
|
@ -26,4 +26,17 @@ export class AppVersionUpdateDto {
|
|||
|
||||
@IsOptional()
|
||||
pageSettings: any;
|
||||
|
||||
// Workflow related fields
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsUUID()
|
||||
currentEnvironmentId: string;
|
||||
|
||||
@IsOptional()
|
||||
definition: any;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
is_user_switched_version: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { sanitizeInput } from '@helpers/utils.helper';
|
||||
import { IsString, IsOptional, IsNotEmpty, MaxLength, IsBoolean, IsUUID } from 'class-validator';
|
||||
import { IsString, IsOptional, IsNotEmpty, MaxLength, IsBoolean, IsUUID, IsEnum } from 'class-validator';
|
||||
import { Exclude, Expose, Transform } from 'class-transformer';
|
||||
import { APP_TYPES } from '../constants';
|
||||
|
||||
export class AppCreateDto {
|
||||
@IsNotEmpty()
|
||||
|
|
@ -12,6 +13,11 @@ export class AppCreateDto {
|
|||
@IsString()
|
||||
@MaxLength(200, { message: 'Maximum length has been reached.' })
|
||||
icon?: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@IsEnum(APP_TYPES, { message: 'Invalid app type.' })
|
||||
type: string;
|
||||
}
|
||||
|
||||
export class AppUpdateDto {
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ export class AppsService implements IAppsService {
|
|||
protected readonly aiUtilService: AiUtilService
|
||||
) {}
|
||||
async create(user: User, appCreateDto: AppCreateDto) {
|
||||
const { name, icon } = appCreateDto;
|
||||
const { name, icon, type } = appCreateDto;
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const app = await this.appsUtilService.create(name, user, APP_TYPES.FRONT_END, manager);
|
||||
const app = await this.appsUtilService.create(name, user, type, manager);
|
||||
|
||||
const appUpdateDto = new AppUpdateDto();
|
||||
appUpdateDto.name = name;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
NotAcceptableException,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { EntityManager, SelectQueryBuilder } from 'typeorm';
|
||||
import { EntityManager, MoreThan, SelectQueryBuilder } from 'typeorm';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { AppsRepository } from './repository';
|
||||
import { AppVersion } from '@entities/app_version.entity';
|
||||
|
|
@ -36,6 +36,7 @@ import { AbilityService } from '@modules/ability/interfaces/IService';
|
|||
import { DataSourcesRepository } from '@modules/data-sources/repository';
|
||||
import { IAppsUtilService } from './interfaces/IUtilService';
|
||||
import { DataSourcesUtilService } from '@modules/data-sources/util.service';
|
||||
import { AppVersionUpdateDto } from '@dto/app-version-update.dto';
|
||||
|
||||
@Injectable()
|
||||
export class AppsUtilService implements IAppsUtilService {
|
||||
|
|
@ -281,6 +282,70 @@ export class AppsUtilService implements IAppsUtilService {
|
|||
}, manager);
|
||||
}
|
||||
|
||||
async updateWorflowVersion(version: AppVersion, body: AppVersionUpdateDto, app: App) {
|
||||
const { name, currentEnvironmentId, definition } = body;
|
||||
const { currentVersionId, organizationId } = app;
|
||||
let currentEnvironment: AppEnvironment;
|
||||
|
||||
if (version.id === currentVersionId && !body?.is_user_switched_version)
|
||||
throw new BadRequestException('You cannot update a released version');
|
||||
|
||||
if (currentEnvironmentId || definition) {
|
||||
currentEnvironment = await AppEnvironment.findOne({
|
||||
where: { id: version.currentEnvironmentId },
|
||||
});
|
||||
}
|
||||
|
||||
const editableParams = {};
|
||||
if (name) {
|
||||
//means user is trying to update the name
|
||||
const versionNameExists = await this.versionRepository.findOne({
|
||||
where: { name, appId: version.appId },
|
||||
});
|
||||
|
||||
if (versionNameExists) {
|
||||
throw new BadRequestException('Version name already exists.');
|
||||
}
|
||||
editableParams['name'] = name;
|
||||
}
|
||||
|
||||
//check if the user is trying to promote the environment & raise an error if the currentEnvironmentId is not correct
|
||||
if (currentEnvironmentId) {
|
||||
if (!(await this.licenseTermsService.getLicenseTerms(LICENSE_FIELD.MULTI_ENVIRONMENT))) {
|
||||
throw new BadRequestException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
if (version.currentEnvironmentId !== currentEnvironmentId) {
|
||||
throw new NotAcceptableException();
|
||||
}
|
||||
const nextEnvironment = await AppEnvironment.findOne({
|
||||
select: ['id'],
|
||||
where: {
|
||||
priority: MoreThan(currentEnvironment.priority),
|
||||
organizationId,
|
||||
},
|
||||
order: { priority: 'ASC' },
|
||||
});
|
||||
editableParams['currentEnvironmentId'] = nextEnvironment.id;
|
||||
}
|
||||
|
||||
if (definition) {
|
||||
const environments = await AppEnvironment.count({
|
||||
where: {
|
||||
organizationId,
|
||||
},
|
||||
});
|
||||
if (environments > 1 && currentEnvironment.priority !== 1 && !body?.is_user_switched_version) {
|
||||
throw new BadRequestException('You cannot update a promoted version');
|
||||
}
|
||||
editableParams['definition'] = definition;
|
||||
}
|
||||
|
||||
editableParams['updatedAt'] = new Date();
|
||||
|
||||
return await this.versionRepository.update(version.id, editableParams);
|
||||
}
|
||||
|
||||
protected async getEnvironmentOfVersion(versionId: string, manager: EntityManager): Promise<AppEnvironment> {
|
||||
return manager
|
||||
.createQueryBuilder(AppEnvironment, 'app_environments')
|
||||
|
|
|
|||
|
|
@ -191,11 +191,12 @@ export class DataQueriesService implements IDataQueriesService {
|
|||
|
||||
async changeQueryDataSource(user: User, queryId: string, dataSource: DataSource, newDataSourceId: string) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const newDataSource = await this.dataSourceRepository.findOne({ where: { id: newDataSourceId } });
|
||||
if (dataSource.kind !== newDataSource.kind) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
return this.dataQueryRepository.updateOne(queryId, { dataSourceId: newDataSourceId }, manager);
|
||||
const newDataSource = await this.dataSourceRepository.findOneOrFail({ where: { id: newDataSourceId } });
|
||||
// FIXME: Disabling this check as workflows can change data source of a query with different kind
|
||||
// if (dataSource.kind !== newDataSource.kind && dataSource) {
|
||||
// throw new BadRequestException();
|
||||
// }
|
||||
return this.dataQueryRepository.updateOne(queryId, { dataSourceId: newDataSource.id }, manager);
|
||||
|
||||
// TODO: Audit logs
|
||||
});
|
||||
|
|
|
|||
|
|
@ -175,6 +175,10 @@ export class VersionService implements IVersionService {
|
|||
|
||||
await this.versionsUtilService.updateVersion(appVersion, appVersionUpdateDto);
|
||||
|
||||
if (app.type === 'workflow') {
|
||||
await this.appUtilService.updateWorflowVersion(appVersion, appVersionUpdateDto, app);
|
||||
}
|
||||
|
||||
this.eventEmitter.emit('auditLogEntry', {
|
||||
userId: user.id,
|
||||
organizationId: user.organizationId,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ export class WorkflowsModule {
|
|||
UserRepository,
|
||||
DataSourcesRepository,
|
||||
DataQueryRepository,
|
||||
DataSourcesRepository,
|
||||
OrganizationConstantRepository,
|
||||
VersionRepository,
|
||||
AppsService,
|
||||
|
|
|
|||
Loading…
Reference in a new issue