forked from ToolJet/ToolJet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQueryCard.jsx
More file actions
216 lines (208 loc) · 11.4 KB
/
QueryCard.jsx
File metadata and controls
216 lines (208 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import React, { useState } from 'react';
import { Tooltip } from 'react-tooltip';
import { checkExistingQueryName, updateQuerySuggestions } from '@/_helpers/appUtils';
import { Confirm } from '../Viewer/Confirm';
import { toast } from 'react-hot-toast';
import { useDataQueriesActions, useDataQueriesStore } from '@/_stores/dataQueriesStore';
import { useQueryPanelActions, useSelectedDataSource, useSelectedQuery } from '@/_stores/queryPanelStore';
import { useAppVersionStore } from '@/_stores/appVersionStore';
import { shallow } from 'zustand/shallow';
import Copy from '@/_ui/Icon/solidIcons/Copy';
import DataSourceIcon from '../QueryManager/Components/DataSourceIcon';
import { isQueryRunnable, decodeEntities } from '@/_helpers/utils';
import { canDeleteDataSource, canReadDataSource, canUpdateDataSource } from '@/_helpers';
export const QueryCard = ({ dataQuery, darkMode = false, editorRef, appId, localDs }) => {
const selectedQuery = useSelectedQuery();
const selectedDataSource = useSelectedDataSource();
const { isDeletingQueryInProcess } = useDataQueriesStore();
const { deleteDataQueries, renameQuery, duplicateQuery } = useDataQueriesActions();
const { setSelectedQuery, setPreviewData } = useQueryPanelActions();
const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
const hasPermissions =
selectedDataSource?.scope === 'global'
? canUpdateDataSource(selectedQuery?.data_source_id) ||
canReadDataSource(selectedQuery?.data_source_id) ||
canDeleteDataSource()
: true;
const { isVersionReleased, isEditorFreezed } = useAppVersionStore(
(state) => ({
isVersionReleased: state.isVersionReleased,
isEditorFreezed: state.isEditorFreezed,
}),
shallow
);
const [renamingQuery, setRenamingQuery] = useState(false);
let isSeletedQuery = false;
if (selectedQuery) {
isSeletedQuery = dataQuery.id === selectedQuery.id;
}
const deleteDataQuery = (e) => {
e.stopPropagation();
setShowDeleteConfirmation(true);
};
const updateQueryName = (selectedQuery, newName) => {
const { name } = selectedQuery;
if (name === newName) {
return setRenamingQuery(false);
}
const isNewQueryNameAlreadyExists = checkExistingQueryName(newName);
if (newName && !isNewQueryNameAlreadyExists) {
renameQuery(dataQuery?.id, newName, editorRef);
setRenamingQuery(false);
updateQuerySuggestions(name, newName);
} else {
if (isNewQueryNameAlreadyExists) {
toast.error('Query name already exists');
}
setRenamingQuery(false);
}
};
const executeDataQueryDeletion = () => {
setShowDeleteConfirmation(false);
deleteDataQueries(dataQuery?.id, editorRef);
setPreviewData(null);
};
return (
<>
<div
className={`row query-row pe-2 ${darkMode && 'dark-theme'}` + (isSeletedQuery ? ' query-row-selected' : '')}
key={dataQuery.id}
onClick={() => {
if (selectedQuery?.id === dataQuery?.id) return;
setSelectedQuery(dataQuery?.id);
setPreviewData(null);
}}
role="button"
>
<div className="col-auto query-icon d-flex">
<DataSourceIcon source={dataQuery} height={16} />
</div>
<div className="col query-row-query-name">
{renamingQuery ? (
<input
data-cy={`query-edit-input-field`}
className={`query-name query-name-input-field border-indigo-09 bg-transparent ${
darkMode && 'text-white'
}`}
type="text"
defaultValue={decodeEntities(dataQuery.name)}
autoFocus={true}
onKeyDown={({ target, key }) => {
if (key === 'Enter') {
updateQueryName(selectedQuery, target.value);
}
}}
onBlur={({ target }) => {
updateQueryName(selectedQuery, target.value);
}}
/>
) : (
<div className="query-name" data-cy={`list-query-${dataQuery.name.toLowerCase()}`}>
<span
className="text-truncate"
data-tooltip-id="query-card-name-tooltip"
data-tooltip-content={decodeEntities(dataQuery.name)}
>
{decodeEntities(dataQuery.name)}
</span>{' '}
<Tooltip id="query-card-name-tooltip" className="tooltip query-manager-tooltip" />
{!isQueryRunnable(dataQuery) && <small className="mx-2 text-secondary">Draft</small>}
{localDs && (
<>
<a
className="text-truncate"
data-tooltip-id="query-card-local-ds-info"
href="https://docs.tooljet.ai/docs/data-sources/overview/#changing-scope-of-data-sources-on-an-app-created-on-older-versions-of-tooljet"
target="_blank"
rel="noreferrer"
>
<img src={`assets/images/icons/warning.svg`} style={{ height: '20px' }} alt="Warning" />
</a>{' '}
<Tooltip id="query-card-local-ds-info" className="tooltip" place="right" style={{ width: '200px' }}>
Important <br />
Local Data sources will be deprecated soon. Switch to Global Data sources for continued support
</Tooltip>
</>
)}
</div>
)}
</div>
{!(isVersionReleased || isEditorFreezed) && selectedQuery?.id === dataQuery.id && (
<div className="col-auto query-rename-delete-btn">
<div
className={`col-auto ${(renamingQuery || !hasPermissions) && 'd-none'} rename-query`}
onClick={() => setRenamingQuery(true)}
>
<span className="d-flex" data-tooltip-id="query-card-btn-tooltip" data-tooltip-content="Rename query">
<svg
data-cy={`edit-query-${dataQuery.name.toLowerCase()}`}
width="100%"
height="100%"
viewBox="0 0 19 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.7087 1.40712C14.29 0.826221 15.0782 0.499893 15.9 0.499893C16.7222 0.499893 17.5107 0.82651 18.0921 1.40789C18.6735 1.98928 19.0001 2.7778 19.0001 3.6C19.0001 4.42197 18.6737 5.21028 18.0926 5.79162C18.0924 5.79178 18.0928 5.79145 18.0926 5.79162L16.8287 7.06006C16.7936 7.11191 16.753 7.16118 16.7071 7.20711C16.6621 7.25215 16.6138 7.292 16.563 7.32665L9.70837 14.2058C9.52073 14.3942 9.26584 14.5 9 14.5H6C5.44772 14.5 5 14.0523 5 13.5V10.5C5 10.2342 5.10585 9.97927 5.29416 9.79163L12.1733 2.93697C12.208 2.88621 12.2478 2.83794 12.2929 2.79289C12.3388 2.74697 12.3881 2.70645 12.4399 2.67132L13.7079 1.40789C13.7082 1.40763 13.7084 1.40738 13.7087 1.40712ZM13.0112 4.92545L7 10.9153V12.5H8.58474L14.5745 6.48876L13.0112 4.92545ZM15.9862 5.07202L14.428 3.51376L15.1221 2.82211C15.3284 2.6158 15.6082 2.49989 15.9 2.49989C16.1918 2.49989 16.4716 2.6158 16.6779 2.82211C16.8842 3.02842 17.0001 3.30823 17.0001 3.6C17.0001 3.89177 16.8842 4.17158 16.6779 4.37789L15.9862 5.07202ZM0.87868 5.37868C1.44129 4.81607 2.20435 4.5 3 4.5H4C4.55228 4.5 5 4.94772 5 5.5C5 6.05228 4.55228 6.5 4 6.5H3C2.73478 6.5 2.48043 6.60536 2.29289 6.79289C2.10536 6.98043 2 7.23478 2 7.5V16.5C2 16.7652 2.10536 17.0196 2.29289 17.2071C2.48043 17.3946 2.73478 17.5 3 17.5H12C12.2652 17.5 12.5196 17.3946 12.7071 17.2071C12.8946 17.0196 13 16.7652 13 16.5V15.5C13 14.9477 13.4477 14.5 14 14.5C14.5523 14.5 15 14.9477 15 15.5V16.5C15 17.2957 14.6839 18.0587 14.1213 18.6213C13.5587 19.1839 12.7957 19.5 12 19.5H3C2.20435 19.5 1.44129 19.1839 0.87868 18.6213C0.31607 18.0587 0 17.2957 0 16.5V7.5C0 6.70435 0.31607 5.94129 0.87868 5.37868Z"
fill="#11181C"
/>
</svg>
</span>
</div>
<div
className={`col-auto rename-query ${!hasPermissions && 'd-none'}`}
onClick={() => duplicateQuery(dataQuery?.id, appId)}
>
<span className="d-flex" data-tooltip-id="query-card-btn-tooltip" data-tooltip-content="Duplicate query">
<Copy height={16} width={16} viewBox="0 5 20 20" />
</span>
</div>
<div className="col-auto">
{isDeletingQueryInProcess ? (
<div className="px-2">
<div className="text-center spinner-border spinner-border-sm" role="status"></div>
</div>
) : (
<span
className={`delete-query ${!hasPermissions && 'd-none'}`}
onClick={deleteDataQuery}
data-tooltip-id="query-card-btn-tooltip"
data-tooltip-content="Delete query"
>
<span className="d-flex">
<svg
data-cy={`delete-query-${dataQuery.name.toLowerCase()}`}
width="100%"
height="100%"
viewBox="0 0 18 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.58579 0.585786C5.96086 0.210714 6.46957 0 7 0H11C11.5304 0 12.0391 0.210714 12.4142 0.585786C12.7893 0.960859 13 1.46957 13 2V4H15.9883C15.9953 3.99993 16.0024 3.99993 16.0095 4H17C17.5523 4 18 4.44772 18 5C18 5.55228 17.5523 6 17 6H16.9201L15.9997 17.0458C15.9878 17.8249 15.6731 18.5695 15.1213 19.1213C14.5587 19.6839 13.7957 20 13 20H5C4.20435 20 3.44129 19.6839 2.87868 19.1213C2.32687 18.5695 2.01223 17.8249 2.00035 17.0458L1.07987 6H1C0.447715 6 0 5.55228 0 5C0 4.44772 0.447715 4 1 4H1.99054C1.9976 3.99993 2.00466 3.99993 2.0117 4H5V2C5 1.46957 5.21071 0.960859 5.58579 0.585786ZM3.0868 6L3.99655 16.917C3.99885 16.9446 4 16.9723 4 17C4 17.2652 4.10536 17.5196 4.29289 17.7071C4.48043 17.8946 4.73478 18 5 18H13C13.2652 18 13.5196 17.8946 13.7071 17.7071C13.8946 17.5196 14 17.2652 14 17C14 16.9723 14.0012 16.9446 14.0035 16.917L14.9132 6H3.0868ZM11 4H7V2H11V4ZM6.29289 10.7071C5.90237 10.3166 5.90237 9.68342 6.29289 9.29289C6.68342 8.90237 7.31658 8.90237 7.70711 9.29289L9 10.5858L10.2929 9.29289C10.6834 8.90237 11.3166 8.90237 11.7071 9.29289C12.0976 9.68342 12.0976 10.3166 11.7071 10.7071L10.4142 12L11.7071 13.2929C12.0976 13.6834 12.0976 14.3166 11.7071 14.7071C11.3166 15.0976 10.6834 15.0976 10.2929 14.7071L9 13.4142L7.70711 14.7071C7.31658 15.0976 6.68342 15.0976 6.29289 14.7071C5.90237 14.3166 5.90237 13.6834 6.29289 13.2929L7.58579 12L6.29289 10.7071Z"
fill="#DB4324"
/>
</svg>
</span>
</span>
)}
</div>
{/* <Tooltip id="query-card-btn-tooltip" className="tooltip" /> */}
</div>
)}
</div>
<Confirm
show={showDeleteConfirmation}
message={'Do you really want to delete this query?'}
confirmButtonLoading={isDeletingQueryInProcess}
onConfirm={executeDataQueryDeletion}
onCancel={() => setShowDeleteConfirmation(false)}
darkMode={darkMode}
/>
</>
);
};