mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-21 16:08:35 +00:00
Merge pull request #11370 from ToolJet/release/lts-3.0.3
Release LTS v3.0.3 - Platform
This commit is contained in:
commit
167d1eb2db
15 changed files with 171 additions and 14 deletions
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
3.0.3-ce-lts
|
||||
3.0.4-ce-lts
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.0.3-ce-lts
|
||||
3.0.4-ce-lts
|
||||
|
|
|
|||
5
frontend/assets/images/icons/info-icon.svg
Normal file
5
frontend/assets/images/icons/info-icon.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="18" viewBox="0 0 17 18" fill="none">
|
||||
<circle opacity="0.4" cx="8.5118" cy="9.25781" r="8.33333" fill="#BF4F03"/>
|
||||
<path d="M9.34513 5.09115C9.34513 5.55138 8.97204 5.92448 8.5118 5.92448C8.05156 5.92448 7.67847 5.55138 7.67847 5.09115C7.67847 4.63091 8.05156 4.25781 8.5118 4.25781C8.97204 4.25781 9.34513 4.63091 9.34513 5.09115Z" fill="#BF4F03"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.05347 7.59115C7.05347 7.24597 7.33329 6.96615 7.67847 6.96615H8.5118C8.85698 6.96615 9.1368 7.24597 9.1368 7.59115V13.4245C9.1368 13.7697 8.85698 14.0495 8.5118 14.0495C8.16662 14.0495 7.8868 13.7697 7.8868 13.4245V8.21615H7.67847C7.33329 8.21615 7.05347 7.93633 7.05347 7.59115Z" fill="#BF4F03"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 769 B |
|
|
@ -19,6 +19,7 @@ import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
|
|||
import { canDeleteDataSource, canReadDataSource, canUpdateDataSource } from '@/_helpers';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { EventManager } from '@/AppBuilder/RightSideBar/Inspector/EventManager';
|
||||
import NotificationBanner from '@/_components/NotificationBanner';
|
||||
|
||||
export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) => {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -30,6 +31,7 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
|
|||
const selectedDataSource = useStore((state) => state.queryPanel.selectedDataSource);
|
||||
const changeDataQuery = useStore((state) => state.dataQuery.changeDataQuery);
|
||||
const updateDataQuery = useStore((state) => state.dataQuery.updateDataQuery);
|
||||
const [showLocalDataSourceDeprecationBanner, setshowLocalDataSourceDeprecationBanner] = useState(false);
|
||||
|
||||
const [dataSourceMeta, setDataSourceMeta] = useState(null);
|
||||
/* - Added the below line to cause re-rendering when the query is switched
|
||||
|
|
@ -280,7 +282,7 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
|
|||
return (
|
||||
<>
|
||||
<div className="" ref={paramListContainerRef}>
|
||||
{selectedQuery && (
|
||||
{selectedQuery && !showLocalDataSourceDeprecationBanner && (
|
||||
<ParameterList
|
||||
parameters={options.parameters}
|
||||
handleAddParameter={handleAddParameter}
|
||||
|
|
@ -310,6 +312,21 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
|
|||
</>
|
||||
);
|
||||
};
|
||||
useEffect(() => {
|
||||
const staticDataSources = ['runjs', 'runpy', 'tooljetdb'];
|
||||
// added specific check for rest api - as it is a part of both : default and global data sources
|
||||
const showDeprecationBanner =
|
||||
selectedDataSource == null &&
|
||||
selectedQuery &&
|
||||
!staticDataSources.includes(selectedDataSource?.kind) &&
|
||||
(selectedDataSource?.kind !== 'restapi' || selectedDataSource?.type !== 'default');
|
||||
|
||||
if (showDeprecationBanner) {
|
||||
setshowLocalDataSourceDeprecationBanner(true);
|
||||
} else {
|
||||
setshowLocalDataSourceDeprecationBanner(false);
|
||||
}
|
||||
}, [selectedDataSource, selectedQuery]);
|
||||
|
||||
// if (selectedQueryId !== selectedQuery?.id) return;
|
||||
const hasPermissions =
|
||||
|
|
@ -318,7 +335,6 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
|
|||
canReadDataSource(selectedQuery?.data_source_id) ||
|
||||
canDeleteDataSource()
|
||||
: true;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`query-details ${selectedDataSource?.kind === 'tooljetdb' ? 'tooljetdb-query-details' : ''} ${
|
||||
|
|
@ -331,7 +347,14 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
|
|||
}} // 40px for preview header height
|
||||
>
|
||||
{selectedDataSource === null || !selectedQuery ? (
|
||||
renderDataSourcesList()
|
||||
showLocalDataSourceDeprecationBanner ? (
|
||||
<>
|
||||
<NotificationBanner enhanceDisabledVisibility={!hasPermissions || isFreezed} darkMode={darkMode} />
|
||||
{renderChangeDataSource()}
|
||||
</>
|
||||
) : (
|
||||
renderDataSourcesList()
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
{selectedQuery?.data_source_id && activeTab === 1 && renderChangeDataSource()}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
border: 1px solid #e9ece;
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
width: 920px;
|
||||
// width: 920px; //Add it for EE
|
||||
height: 620px;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ const ConstantTable = ({
|
|||
<tbody>
|
||||
{constants.map((constant) => (
|
||||
<tr key={constant.id}>
|
||||
<td className="p-3">
|
||||
<td className="p-3-constants">
|
||||
<span
|
||||
data-cy={`${constant.name.toLowerCase().replace(/\s+/g, '-')}-workspace-constant-name`}
|
||||
data-tooltip-id="tooltip-for-org-constant-cell"
|
||||
|
|
@ -101,7 +101,7 @@ const ConstantTable = ({
|
|||
: constant.name}
|
||||
</span>
|
||||
</td>
|
||||
<td className="text-muted p-3" style={{ width: '350px' }}>
|
||||
<td className="text-muted p-3-constants" style={{ width: '350px' }}>
|
||||
<a
|
||||
className="text-reset user-email"
|
||||
data-cy={`${constant.name.toLowerCase().replace(/\s+/g, '-')}-workspace-constant-value`}
|
||||
|
|
@ -111,7 +111,7 @@ const ConstantTable = ({
|
|||
</td>
|
||||
|
||||
{canUpdateDeleteConstant && (
|
||||
<td className="p-3">
|
||||
<td className="p-3-constants">
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between', gap: 5 }}
|
||||
data-cy={`${constant.name.toLowerCase().replace(/\s+/g, '-')}-workspace-constant-update`}
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ const ManageOrgConstantsComponent = ({ darkMode }) => {
|
|||
<OrganizationList />
|
||||
</div>
|
||||
|
||||
<div className="page-wrapper mt-4">
|
||||
<div className="page-wrapper mt-4" style={{ marginLeft: '50px' }}>
|
||||
<div className="container-xl" style={{ width: '880px' }}>
|
||||
<div className="align-items-center d-flex justify-content-between">
|
||||
<div className="tj-text-sm font-weight-500" data-cy="env-name">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
import React from 'react';
|
||||
import { Alert } from '@/_ui/Alert/Alert';
|
||||
import './resources/styles.scss';
|
||||
|
||||
const DEFAULT_CONFIG = {
|
||||
docsLink: ' https://docs.tooljet.com/docs/data-sources/local-data-sources-migration',
|
||||
};
|
||||
|
||||
const DEFAULT_MESSAGES = {
|
||||
prefix: 'This query is connected to a local data source which has been',
|
||||
highlightedText: 'discontinued',
|
||||
middle: 'Please create a global data source connection to reconnect your query.',
|
||||
suffix: 'to know more.',
|
||||
linkText: 'Read documentation',
|
||||
};
|
||||
|
||||
const NotificationBanner = ({
|
||||
docsLink,
|
||||
customMessage,
|
||||
darkMode = false,
|
||||
highlightedText = DEFAULT_MESSAGES.highlightedText,
|
||||
highlightedClassName = 'highlighted-text',
|
||||
enhanceDisabledVisibility = false,
|
||||
}) => {
|
||||
const currentDocsLink = docsLink || DEFAULT_CONFIG.docsLink;
|
||||
|
||||
const bannerMessage = customMessage || (
|
||||
<>
|
||||
{DEFAULT_MESSAGES.prefix} <span className={highlightedClassName}>{highlightedText}</span>.{' '}
|
||||
{DEFAULT_MESSAGES.middle}{' '}
|
||||
<a href={currentDocsLink} className="documentation-link" target="_blank" rel="noopener noreferrer">
|
||||
{DEFAULT_MESSAGES.linkText}
|
||||
</a>{' '}
|
||||
{DEFAULT_MESSAGES.suffix}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="notification-banner-component">
|
||||
<Alert svg="info-icon" cls="notification-banner" useDarkMode={darkMode}>
|
||||
<div className={`notification-content ${enhanceDisabledVisibility ? 'disabled' : ''}`}>{bannerMessage}</div>
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationBanner;
|
||||
|
||||
// To Do later: Expand this component properly to make it generic notification component
|
||||
1
frontend/src/_components/NotificationBanner/index.js
Normal file
1
frontend/src/_components/NotificationBanner/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './NotificationBanner';
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
.notification-banner {
|
||||
display: flex;
|
||||
padding: var(--3, 6px) var(--6, 12px);
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 32px;
|
||||
flex: 1 0 0;
|
||||
border-radius: var(--3, 6px);
|
||||
background: var(--background-warning-weak, #FAEFE7);
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
opacity: 1;
|
||||
|
||||
img {
|
||||
margin-top: -5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
.notification-banner {
|
||||
justify-content: center !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
&>div {
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.notification-content {
|
||||
color: var(--text-default, #1B1F24);
|
||||
font-family: "IBM Plex Sans";
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
|
||||
&.disabled {
|
||||
font-weight: 700 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.highlighted-text {
|
||||
font-weight: 600 !important;
|
||||
font-style: bold;
|
||||
}
|
||||
|
||||
.documentation-link {
|
||||
font-weight: 400 !important;
|
||||
color: var(--primary, #3E63DD) !important;
|
||||
text-decoration-line: underline !important;
|
||||
}
|
||||
|
|
@ -148,9 +148,9 @@ export const CreateOrganization = ({ showCreateOrg, setShowCreateOrg }) => {
|
|||
setSlug({ value: defaultValue, error: '' });
|
||||
|
||||
const checkWorkspaceUniqueness = async () => {
|
||||
sluginput.current.value = defaultValue;
|
||||
try {
|
||||
await organizationService.checkWorkspaceUniqueness(null, defaultValue);
|
||||
sluginput.current.value = defaultValue;
|
||||
} catch (errResponse) {
|
||||
let error = {
|
||||
status: false,
|
||||
|
|
|
|||
|
|
@ -7864,7 +7864,7 @@ tbody {
|
|||
|
||||
.marketplace-page-sidebar {
|
||||
height: calc(100vh - 64px);
|
||||
max-width: 288px;
|
||||
max-width: 272px;
|
||||
background-color: var(--page-default);
|
||||
border-right: 1px solid var(--slate5) !important;
|
||||
display: grid !important;
|
||||
|
|
@ -12830,6 +12830,11 @@ color: var(--text-default);
|
|||
padding: 16px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
|
||||
.p-3-constants{
|
||||
padding: 1rem !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.0.3-ce-lts
|
||||
3.0.4-ce-lts
|
||||
|
|
|
|||
|
|
@ -424,3 +424,13 @@ export function mergeDeep(target, source, seen = new WeakMap()) {
|
|||
|
||||
return target;
|
||||
}
|
||||
export const getSubpath = () => {
|
||||
const subpath = process.env.SUB_PATH || '';
|
||||
// Ensure subpath starts and ends with slashes
|
||||
if (subpath) {
|
||||
if (!subpath.startsWith('/') || !subpath.endsWith('/')) {
|
||||
throw new Error('SUB_PATH must start and end with a slash');
|
||||
}
|
||||
}
|
||||
return subpath;
|
||||
};
|
||||
|
|
@ -13,6 +13,7 @@ import { bootstrap as globalAgentBootstrap } from 'global-agent';
|
|||
import { join } from 'path';
|
||||
import * as helmet from 'helmet';
|
||||
import * as express from 'express';
|
||||
import { getSubpath } from '@helpers/utils.helper';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
|
|
@ -100,7 +101,15 @@ function setSecurityHeaders(app, configService) {
|
|||
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader('Permissions-Policy', 'geolocation=(self), camera=(), microphone=()');
|
||||
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
|
||||
const subpath = getSubpath();
|
||||
const path = req.path.replace(subpath, subpath ? '/' : '');
|
||||
if (path.startsWith('/api/')) {
|
||||
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
} else {
|
||||
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue