Merge pull request #7947 from ToolJet/main

Merge main to develop
This commit is contained in:
Midhun G S 2023-10-18 10:31:38 +05:30 committed by GitHub
commit 74282cbe97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 37 additions and 46 deletions

View file

@ -1 +1 @@
2.21.0
2.21.1

View file

@ -1 +1 @@
2.21.0
2.21.1

View file

@ -1,7 +1,7 @@
import React, { useRef, useEffect, useState } from 'react';
import { ToolTip } from '@/_components';
import { appService } from '@/_services';
import { handleHttpErrorMessages, validateAppName, validateName } from '@/_helpers/utils';
import { handleHttpErrorMessages, validateName } from '@/_helpers/utils';
import InfoOrErrorBox from './InfoOrErrorBox';
import { toast } from 'react-hot-toast';
@ -32,7 +32,7 @@ function EditAppName({ appId, appName = '', onNameChanged }) {
const saveAppName = async (newName) => {
const trimmedName = newName.trim();
if (validateName(trimmedName, 'App name', true)?.errorMsg) {
if (validateName(trimmedName, 'App', false, true)?.errorMsg) {
setName(appName);
clearError();
setIsEditing(false);

View file

@ -20,7 +20,6 @@ export default function AppCard({
canCreateApp,
canDeleteApp,
deleteApp,
cloneApp,
exportApp,
appActionModal,
canUpdateApp,
@ -85,7 +84,6 @@ export default function AppCard({
canDeleteApp={canDeleteApp(app)}
canUpdateApp={canUpdateApp(app)}
deleteApp={() => deleteApp(app)}
cloneApp={() => cloneApp(app)}
exportApp={() => exportApp(app)}
isMenuOpen={isMenuOpen}
darkMode={darkMode}

View file

@ -39,7 +39,6 @@ const AppList = (props) => {
canDeleteApp={props.canDeleteApp}
canUpdateApp={props.canUpdateApp}
deleteApp={props.deleteApp}
cloneApp={props.cloneApp}
exportApp={props.exportApp}
appActionModal={props.appActionModal}
/>

View file

@ -133,14 +133,14 @@ class HomePageComponent extends React.Component {
_self.setState({ creatingApp: true });
try {
const data = await appService.createApp({ icon: sample(iconList), name: appName });
const workspaceId = getWorkspaceId();
_self.props.navigate(`/${workspaceId}/apps/${data.id}`);
toast.success('App created successfully!');
_self.setState({ creatingApp: false });
return true;
} catch (errorResponse) {
_self.setState({ creatingApp: false });
if (errorResponse.statusCode === 409) {
_self.setState({ creatingApp: false });
return false;
} else {
throw errorResponse;
@ -155,11 +155,11 @@ class HomePageComponent extends React.Component {
await appService.saveApp(appId, { name: newAppName });
await this.fetchApps();
toast.success('App name has been updated!');
_self.setState({ renamingApp: false });
return true;
} catch (errorResponse) {
_self.setState({ renamingApp: false });
if (errorResponse.statusCode === 409) {
console.log(errorResponse);
_self.setState({ renamingApp: false });
return false;
} else {
throw errorResponse;
@ -171,13 +171,16 @@ class HomePageComponent extends React.Component {
this.setState({ showAppDeletionConfirmation: true, appToBeDeleted: app });
};
cloneApp = async (appId, appName) => {
cloneApp = async (appName, appId) => {
this.setState({ isCloningApp: true });
try {
const data = await appService.cloneApp(appName, appId);
const data = await appService.cloneResource({
app: [{ id: appId, name: appName }],
organization_id: getWorkspaceId(),
});
toast.success('App cloned successfully!');
this.props.navigate(`/${getWorkspaceId()}/apps/${data?.imports?.app[0]?.id}`);
this.setState({ isCloningApp: false });
this.props.navigate(`/${getWorkspaceId()}/apps/${data.id}`);
return true;
} catch (_error) {
this.setState({ isCloningApp: false });
@ -221,9 +224,9 @@ class HomePageComponent extends React.Component {
const organization_id = getWorkspaceId();
const isLegacyImport = isEmpty(importJSON.tooljet_version);
if (isLegacyImport) {
importJSON = { app: [{ definition: importJSON }], tooljet_version: importJSON.tooljetVersion };
importJSON = { app: [{ definition: importJSON, appName: appName }], tooljet_version: importJSON.tooljetVersion };
}
const requestBody = { organization_id, appName, ...importJSON };
const requestBody = { organization_id, ...importJSON };
try {
const data = await appService.importResource(requestBody);
toast.success('App imported successfully.');
@ -841,7 +844,6 @@ class HomePageComponent extends React.Component {
canDeleteApp={this.canDeleteApp}
canUpdateApp={this.canUpdateApp}
deleteApp={this.deleteApp}
cloneApp={this.cloneApp}
exportApp={this.exportApp}
meta={meta}
currentFolder={currentFolder}

View file

@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast';
import Modal from '../HomePage/Modal';
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import _ from 'lodash';
import { validateAppName } from '@/_helpers/utils';
import { validateName } from '@/_helpers/utils';
export function AppModal({
closeModal,
@ -105,7 +105,7 @@ export function AppModal({
setInfoText('Maximum length has been reached');
} else {
setInfoText('');
const error = validateAppName(trimmedName);
const error = validateName(trimmedName, 'App', false);
setErrorText(error?.errorMsg || '');
}
};

View file

@ -920,26 +920,10 @@ export function isExpectedDataType(data, expectedDataType) {
return data;
}
export const validateAppName = (name, showError = false) => {
export const validateName = (name, nameType, emptyCheck = true, showError = false, allowSpecialChars = true) => {
const newName = name.trim();
let errorMsg = '';
if (newName.length > 50) {
errorMsg = `Maximum length has been reached`;
showError &&
toast.error(errorMsg, {
id: '1',
});
}
return {
status: !(errorMsg.length > 0),
errorMsg,
};
};
export const validateName = (name, nameType, showError = false, allowSpecialChars = true) => {
const newName = name.trim();
let errorMsg = '';
if (!newName) {
if (emptyCheck && !newName) {
errorMsg = `${nameType} can't be empty`;
showError &&
toast.error(errorMsg, {

View file

@ -1 +1 @@
2.21.0
2.21.1

View file

@ -1,4 +1,4 @@
import { IsUUID, IsOptional } from 'class-validator';
import { IsUUID, IsOptional, IsString } from 'class-validator';
export class CloneResourcesDto {
@IsOptional()
@ -14,6 +14,9 @@ export class CloneResourcesDto {
export class CloneAppDto {
@IsUUID()
id: string;
@IsString()
name: string;
}
export class CloneTooljetDatabaseDto {

View file

@ -10,9 +10,6 @@ export class ImportResourcesDto {
@IsOptional()
app: ImportAppDto[];
@IsOptional()
appName: string;
@IsOptional()
tooljet_database: ImportTooljetDatabaseDto[];
}
@ -20,6 +17,9 @@ export class ImportResourcesDto {
export class ImportAppDto {
@IsDefined()
definition: any;
@IsString()
appName: string;
}
export class ImportTooljetDatabaseDto {

View file

@ -59,12 +59,16 @@ export class ImportExportResourcesService {
}
if (importResourcesDto.app) {
const appName = importResourcesDto.appName;
for (const appImportDto of importResourcesDto.app) {
user.organizationId = importResourcesDto.organization_id;
const createdApp = await this.appImportExportService.import(user, appImportDto.definition, appName, {
tooljet_database: tableNameMapping,
});
const createdApp = await this.appImportExportService.import(
user,
appImportDto.definition,
appImportDto.appName,
{
tooljet_database: tableNameMapping,
}
);
imports.app.push({ id: createdApp.id, name: createdApp.name });
}
}
@ -82,6 +86,7 @@ export class ImportExportResourcesService {
const resourceExport = await this.export(user, exportResourcesDto);
resourceExport['organization_id'] = cloneResourcesDto.organization_id;
resourceExport['app'][0]['appName'] = cloneResourcesDto.app[0].name;
const clonedResource = await this.import(user, resourceExport as ImportResourcesDto, true);
return clonedResource;