Skip to content

Commit

Permalink
Merge pull request #9322 from ToolJet/release/platformv14.7
Browse files Browse the repository at this point in the history
Release: platform v14.7 (v2.35.1)
  • Loading branch information
gsmithun4 committed Apr 18, 2024
2 parents ac6f191 + aa5803b commit 757d5f5
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .version
@@ -1 +1 @@
2.35.3
2.35.4
2 changes: 1 addition & 1 deletion cypress-tests/cypress/constants/texts/exportImport.js
Expand Up @@ -18,7 +18,7 @@ export const exportAppModalText = {
};

export const importText = {
importOption: "Import",
importOption: "Import from device",
couldNotImportAppToastMessage: `Could not import: SyntaxError: Unexpected token`,
appImportedToastMessage: "App imported successfully.",
};
Expand Up @@ -62,7 +62,7 @@ describe("dashboard", () => {
cy.get(commonSelectors.editRectangleIcon).should("be.visible");
cy.get(commonSelectors.appCreateButton).verifyVisibleElement(
"have.text",
"Create new app"
"Create an app"
);
cy.get(dashboardSelector.folderLabel).should("be.visible");
cy.get(dashboardSelector.folderLabel).should(($el) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/.version
@@ -1 +1 @@
2.35.3
2.35.4
4 changes: 2 additions & 2 deletions frontend/assets/translations/en.json
Expand Up @@ -405,8 +405,8 @@
"wishToDeleteFolder": "Are you sure you want to delete the folder {{folderName}}? Apps within the folder will not be deleted."
},
"header": {
"createNewApplication": "Create new app",
"import": "Import",
"createNewApplication": "Create an app",
"import": "Import from device",
"chooseFromTemplate": "Choose from template"
},
"pagination": {
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/Editor/Inspector/Components/Table/Table.jsx
Expand Up @@ -1139,9 +1139,7 @@ class TableComponent extends React.Component {
<div className="field">
<div className="row g-2">
<div>{actions.value.map((action, index) => this.renderActionButton(action, index))}</div>
{actions.value.length === 0 && (
<NoListItem text={'No action buttons'} dataCy={`-action-button`} />
)}
{actions.value.length === 0 && <NoListItem text={'No action buttons'} dataCy={`-action-button`} />}
<AddNewButton dataCy="button-add-new-action-button" onClick={this.addNewAction} className="mt-0">
New action button
</AddNewButton>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/HomePage/AppList.jsx
Expand Up @@ -10,7 +10,7 @@ const AppList = (props) => {
{props.isLoading && (
<>
{Array.from(Array(2)).map((_, rowIndex) => (
<div className="row mb-3" key={rowIndex}>
<div className="row skeleton-container mb-3" key={rowIndex}>
{Array.from(Array(3)).map((_, index) => (
<div className="col" key={rowIndex * 3 + index}>
<div className="card-skeleton-container">
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/HomePage/AppMenu.jsx
Expand Up @@ -71,6 +71,10 @@ export const AppMenu = function AppMenu({
onClick={() => openAppActionModal('remove-app-from-folder')}
/>
)}
</>
)}
{canUpdateApp && canCreateApp && (
<>
<Field
text={t('homePage.appCard.cloneApp', 'Clone app')}
onClick={() => openAppActionModal('clone-app')}
Expand Down
26 changes: 14 additions & 12 deletions frontend/src/HomePage/BlankPage.jsx
Expand Up @@ -65,18 +65,20 @@ export const BlankPage = function BlankPage({
)}
</p>
<div className="row mt-4">
<ButtonSolid
leftIcon="plus"
onClick={openCreateAppModal}
isLoading={creatingApp}
data-cy="button-new-app-from-scratch"
className="col"
fill={'#FDFDFE'}
disabled={appCreationDisabled}
>
Create new application
</ButtonSolid>
<div className="col">
<div className="col-6">
<ButtonSolid
leftIcon="plus"
onClick={openCreateAppModal}
isLoading={creatingApp}
data-cy="button-new-app-from-scratch"
className="col"
fill={'#FDFDFE'}
disabled={appCreationDisabled}
>
Create new application
</ButtonSolid>
</div>
<div className="col-6">
<ButtonSolid
leftIcon="folderdownload"
onChange={readAndImport}
Expand Down
48 changes: 29 additions & 19 deletions frontend/src/HomePage/HomePage.jsx
Expand Up @@ -24,6 +24,7 @@ import { getWorkspaceId, pageTitles, setWindowTitle } from '@/_helpers/utils';
import { withRouter } from '@/_hoc/withRouter';
import FolderFilter from './FolderFilter';
import { APP_ERROR_TYPE } from '@/_helpers/error_constants';
import Skeleton from 'react-loading-skeleton';

const { iconList, defaultIcon } = configs;

Expand Down Expand Up @@ -773,7 +774,7 @@ class HomePageComponent extends React.Component {
data-cy="create-new-app-button"
>
{isImportingApp && <span className="spinner-border spinner-border-sm mx-2" role="status"></span>}
{this.props.t('homePage.header.createNewApplication', 'Create new app')}
{this.props.t('homePage.header.createNewApplication', 'Create an app')}
</Button>
<Dropdown.Toggle split className="d-inline" data-cy="import-dropdown-menu" />
<Dropdown.Menu className="import-lg-position new-app-dropdown">
Expand All @@ -789,7 +790,7 @@ class HomePageComponent extends React.Component {
data-cy="import-option-label"
onChange={this.readAndImport}
>
{this.props.t('homePage.header.import', 'Import')}
{this.props.t('homePage.header.import', 'Import from device')}
<input
type="file"
accept=".json"
Expand Down Expand Up @@ -824,6 +825,16 @@ class HomePageComponent extends React.Component {
data-cy="home-page-content"
>
<div className="w-100 mb-5 container home-page-content-container">
{isLoading && (
<Skeleton
count={1}
height={20}
width={880}
baseColor="#ECEEF0"
className="mb-3"
style={{ marginTop: '2rem' }}
/>
)}
{(meta?.total_count > 0 || appSearchKey) && (
<>
<HomeHeader onSearchSubmit={this.onSearchSubmit} darkMode={this.props.darkMode} />
Expand Down Expand Up @@ -873,23 +884,22 @@ class HomePageComponent extends React.Component {
</span>
</div>
)}
{isLoading ||
(meta.total_count > 0 && (
<AppList
apps={apps}
canCreateApp={this.canCreateApp}
canDeleteApp={this.canDeleteApp}
canUpdateApp={this.canUpdateApp}
deleteApp={this.deleteApp}
exportApp={this.exportApp}
meta={meta}
currentFolder={currentFolder}
isLoading={isLoading}
darkMode={this.props.darkMode}
appActionModal={this.appActionModal}
removeAppFromFolder={this.removeAppFromFolder}
/>
))}
{meta.total_count > 0 && (
<AppList
apps={apps}
canCreateApp={this.canCreateApp}
canDeleteApp={this.canDeleteApp}
canUpdateApp={this.canUpdateApp}
deleteApp={this.deleteApp}
exportApp={this.exportApp}
meta={meta}
currentFolder={currentFolder}
isLoading={isLoading}
darkMode={this.props.darkMode}
appActionModal={this.appActionModal}
removeAppFromFolder={this.removeAppFromFolder}
/>
)}
</div>
<div className="footer-container">
{this.pageCount() > MAX_APPS_PER_PAGE && (
Expand Down
26 changes: 22 additions & 4 deletions frontend/src/_styles/theme.scss
Expand Up @@ -883,7 +883,7 @@ button {
}

.app-icon-skeleton {
background-color: #91a4f6;
background-color: #ECEEF0 !important;
border-radius: 4px;
margin-bottom: 20px;
height: 40px;
Expand Down Expand Up @@ -8126,7 +8126,7 @@ tbody {

.logo-nav-card {
transform: translate(5px, 50px) !important;
z-index: 100;
z-index: 101;
}

.theme-dark {
Expand Down Expand Up @@ -11366,6 +11366,22 @@ tbody {
.app-list {
overflow-y: auto;
height: calc(100vh - 23rem);

.skeleton-container {
display: flex;
flex-direction: column;

.col {
display: flex;
justify-content: center;
margin-bottom: 1rem;
}

.card-skeleton-container {
width: 304px;

}
}
}

.menu-ico {
Expand Down Expand Up @@ -12503,10 +12519,12 @@ tbody {
}

.group-chip {
padding: 5px 8px;
padding: 2px 8px;
margin: 0;
border-radius: 6px;
background-color: var(--slate3);
color: var(--slate11);
min-height: 24px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
Expand All @@ -12525,7 +12543,7 @@ tbody {
border: 1px solid var(--slate1);
box-shadow: 0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08);
padding: 9px 10px;
gap: 15px;
gap: 10px;
cursor: default;
max-height: 240px;
overflow: auto;
Expand Down
2 changes: 1 addition & 1 deletion server/.version
@@ -1 +1 @@
2.35.3
2.35.4
35 changes: 16 additions & 19 deletions server/src/app.module.ts
Expand Up @@ -48,24 +48,6 @@ import { ImportExportResourcesModule } from './modules/import_export_resources/i
import { MailerModule } from '@nestjs-modules/mailer';
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';

const port = +process.env.SMTP_PORT || 587;
const transport =
process.env.NODE_ENV === 'development'
? {
host: 'localhost',
ignoreTLS: true,
secure: false,
}
: {
host: process.env.SMTP_DOMAIN,
port: port,
secure: port == 465,
auth: {
user: process.env.SMTP_USERNAME,
pass: process.env.SMTP_PASSWORD,
},
};

const imports = [
ScheduleModule.forRoot(),
ConfigModule.forRoot({
Expand Down Expand Up @@ -99,7 +81,22 @@ const imports = [
},
}),
MailerModule.forRoot({
transport: transport,
transport:
process.env.NODE_ENV === 'development'
? {
host: 'localhost',
ignoreTLS: true,
secure: false,
}
: {
host: process.env.SMTP_DOMAIN,
port: +process.env.SMTP_PORT || 587,
secure: process.env.SMTP_SSL === 'true',
auth: {
user: process.env.SMTP_USERNAME,
pass: process.env.SMTP_PASSWORD,
},
},
preview: process.env.NODE_ENV === 'development',
template: {
dir: join(__dirname, 'mails'),
Expand Down
1 change: 1 addition & 0 deletions server/src/controllers/apps.controller.ts
Expand Up @@ -240,6 +240,7 @@ export class AppsController {
return response;
}

// Deprecated - moved to import - export - controller
@UseGuards(JwtAuthGuard)
@UseInterceptors(ValidAppInterceptor)
@Post(':id/clone')
Expand Down
4 changes: 2 additions & 2 deletions server/src/controllers/import_export_resources.controller.ts
Expand Up @@ -40,7 +40,7 @@ export class ImportExportResourcesController {
async import(@User() user, @Body() importResourcesDto: ImportResourcesDto) {
const ability = await this.appsAbilityFactory.appsActions(user);

if (!ability.can('cloneApp', App)) {
if (!ability.can('importApp', App)) {
throw new ForbiddenException('You do not have permissions to perform this action');
}
const isNotCompatibleVersion = !checkVersionCompatibility(importResourcesDto.tooljet_version);
Expand All @@ -54,7 +54,7 @@ export class ImportExportResourcesController {
@UseGuards(JwtAuthGuard)
@Post('/clone')
async clone(@User() user, @Body() cloneResourcesDto: CloneResourcesDto) {
const ability = await this.appsAbilityFactory.appsActions(user);
const ability = await this.appsAbilityFactory.appsActions(user, cloneResourcesDto?.app?.[0]?.id);

if (!ability.can('cloneApp', App)) {
throw new ForbiddenException('You do not have permissions to perform this action');
Expand Down
11 changes: 8 additions & 3 deletions server/src/modules/casl/abilities/apps-ability.factory.ts
Expand Up @@ -8,6 +8,7 @@ import { UsersService } from 'src/services/users.service';
type Actions =
| 'authorizeOauthForSource'
| 'cloneApp'
| 'importApp'
| 'createApp'
| 'createDataSource'
| 'createQuery'
Expand Down Expand Up @@ -41,18 +42,22 @@ export class AppsAbilityFactory {

async appsActions(user: User, id?: string) {
const { can, build } = new AbilityBuilder<Ability<[Actions, Subjects]>>(Ability as AbilityClass<AppsAbility>);
const canUpdateApp = await this.usersService.userCan(user, 'update', 'App', id);

if (await this.usersService.userCan(user, 'create', 'User')) {
can('createUsers', App, { organizationId: user.organizationId });
}

if (await this.usersService.userCan(user, 'update', 'App', id)) {
if (canUpdateApp) {
can('editApp', App, { organizationId: user.organizationId });
}

if (await this.usersService.userCan(user, 'create', 'App')) {
can('createApp', App);
can('cloneApp', App, { organizationId: user.organizationId });
can('importApp', App);
if (canUpdateApp) {
can('cloneApp', App, { organizationId: user.organizationId });
}
}

if (await this.usersService.userCan(user, 'read', 'App', id)) {
Expand All @@ -72,7 +77,7 @@ export class AppsAbilityFactory {
});
}

if (await this.usersService.userCan(user, 'update', 'App', id)) {
if (canUpdateApp) {
can('updateParams', App, { organizationId: user.organizationId });
can('createVersions', App, { organizationId: user.organizationId });
can('deleteVersions', App, { organizationId: user.organizationId });
Expand Down

0 comments on commit 757d5f5

Please sign in to comment.