mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Merge branch 'develop' of github.com:ToolJet/ToolJet into develop
This commit is contained in:
commit
2a98c6bbae
10 changed files with 273 additions and 46 deletions
|
|
@ -66,6 +66,8 @@ class App extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<ToastContainer />
|
||||||
|
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<div className={`main-wrapper ${darkMode ? 'theme-dark' : ''}`}>
|
<div className={`main-wrapper ${darkMode ? 'theme-dark' : ''}`}>
|
||||||
{updateAvailable && (
|
{updateAvailable && (
|
||||||
|
|
@ -96,8 +98,6 @@ class App extends React.Component {
|
||||||
|
|
||||||
{!onboarded && <OnboardingModal />}
|
{!onboarded && <OnboardingModal />}
|
||||||
|
|
||||||
<ToastContainer />
|
|
||||||
|
|
||||||
<PrivateRoute
|
<PrivateRoute
|
||||||
exact
|
exact
|
||||||
path="/"
|
path="/"
|
||||||
|
|
|
||||||
|
|
@ -5,45 +5,55 @@ import moment from 'moment';
|
||||||
import 'react-datetime/css/react-datetime.css';
|
import 'react-datetime/css/react-datetime.css';
|
||||||
import '@/_styles/custom.scss';
|
import '@/_styles/custom.scss';
|
||||||
|
|
||||||
export const Datepicker = function Datepicker({ value, onChange, readOnly, isTimeChecked, dateFormat }) {
|
const getDate = (value, parseDateFormat, displayFormat) => {
|
||||||
const [date, setDate] = React.useState(value);
|
const dateString = value;
|
||||||
|
const momentObj = moment(dateString, parseDateFormat);
|
||||||
|
const momentString = momentObj.format(displayFormat);
|
||||||
|
return momentString;
|
||||||
|
};
|
||||||
|
|
||||||
const dateChange = (e) => {
|
export const Datepicker = function Datepicker({
|
||||||
if (isTimeChecked) {
|
value,
|
||||||
setDate(e.format(`${dateFormat} LT`));
|
onChange,
|
||||||
} else {
|
readOnly,
|
||||||
setDate(e.format(dateFormat));
|
isTimeChecked,
|
||||||
}
|
dateDisplayFormat, //?Display date format
|
||||||
|
parseDateFormat, //?Parse date format
|
||||||
|
}) {
|
||||||
|
const [date, setDate] = React.useState(() => getDate(value, parseDateFormat, dateDisplayFormat));
|
||||||
|
|
||||||
|
const dateChange = (event) => {
|
||||||
|
const value = event._isAMomentObject ? event.format() : event;
|
||||||
|
let selectedDateFormat = isTimeChecked ? `${dateDisplayFormat} LT` : dateDisplayFormat;
|
||||||
|
const dateString = moment(value).format(selectedDateFormat);
|
||||||
|
setDate(() => dateString);
|
||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isTimeChecked) {
|
let selectedDateFormat = isTimeChecked ? `${dateDisplayFormat} LT` : dateDisplayFormat;
|
||||||
setDate(moment(value, 'DD-MM-YYYY').format(dateFormat));
|
const dateString = getDate(value, parseDateFormat, selectedDateFormat);
|
||||||
}
|
setDate(() => dateString);
|
||||||
|
|
||||||
if (isTimeChecked) {
|
|
||||||
setDate(moment(value, 'DD-MM-YYYY LT').format(`${dateFormat} LT`));
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isTimeChecked, readOnly, dateFormat]);
|
}, [isTimeChecked, readOnly, dateDisplayFormat]);
|
||||||
|
|
||||||
let inputProps = {
|
|
||||||
disabled: !readOnly,
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDatepickerClose = () => {
|
const onDatepickerClose = () => {
|
||||||
onChange(date);
|
onChange(date);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let inputProps = {
|
||||||
|
disabled: !readOnly,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Datetime
|
<Datetime
|
||||||
inputProps={inputProps}
|
inputProps={inputProps}
|
||||||
timeFormat={isTimeChecked}
|
timeFormat={isTimeChecked}
|
||||||
className="cell-type-datepicker"
|
className="cell-type-datepicker"
|
||||||
dateFormat={dateFormat}
|
dateFormat={dateDisplayFormat}
|
||||||
value={date}
|
value={date}
|
||||||
onChange={dateChange}
|
onChange={dateChange}
|
||||||
|
closeOnSelect={true}
|
||||||
onClose={onDatepickerClose}
|
onClose={onDatepickerClose}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ export function Table({
|
||||||
if (columnType === 'datepicker') {
|
if (columnType === 'datepicker') {
|
||||||
column.isTimeChecked = column.isTimeChecked ? column.isTimeChecked : false;
|
column.isTimeChecked = column.isTimeChecked ? column.isTimeChecked : false;
|
||||||
column.dateFormat = column.dateFormat ? column.dateFormat : 'DD/MM/YYYY';
|
column.dateFormat = column.dateFormat ? column.dateFormat : 'DD/MM/YYYY';
|
||||||
|
column.parseDateFormat = column.parseDateFormat ?? column.dateFormat; //backwards compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
const width = columnSize || defaultColumn.width;
|
const width = columnSize || defaultColumn.width;
|
||||||
|
|
@ -531,10 +532,11 @@ export function Table({
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Datepicker
|
<Datepicker
|
||||||
dateFormat={column.dateFormat}
|
dateDisplayFormat={column.dateFormat}
|
||||||
isTimeChecked={column.isTimeChecked}
|
isTimeChecked={column.isTimeChecked}
|
||||||
value={cellValue}
|
value={cellValue}
|
||||||
readOnly={column.isEditable}
|
readOnly={column.isEditable}
|
||||||
|
parseDateFormat={column.parseDateFormat}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
handleCellValueChange(cell.row.index, column.key || column.name, value, cell.row.original);
|
handleCellValueChange(cell.row.index, column.key || column.name, value, cell.row.original);
|
||||||
}}
|
}}
|
||||||
|
|
@ -665,7 +667,10 @@ export function Table({
|
||||||
] // Hack: need to fix
|
] // Hack: need to fix
|
||||||
);
|
);
|
||||||
|
|
||||||
const data = useMemo(() => tableData, [tableData.length, componentState.changeSet]);
|
const data = useMemo(
|
||||||
|
() => tableData,
|
||||||
|
[tableData.length, componentState.changeSet, component.definition.properties.data.value]
|
||||||
|
);
|
||||||
|
|
||||||
const computedStyles = {
|
const computedStyles = {
|
||||||
// width: `${width}px`,
|
// width: `${width}px`,
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ class Table extends React.Component {
|
||||||
|
|
||||||
{column.columnType === 'datepicker' && (
|
{column.columnType === 'datepicker' && (
|
||||||
<div>
|
<div>
|
||||||
<label className="form-label">Date Format</label>
|
<label className="form-label">Date Display Format</label>
|
||||||
<div className="field mb-2">
|
<div className="field mb-2">
|
||||||
<CodeHinter
|
<CodeHinter
|
||||||
currentState={this.props.currentState}
|
currentState={this.props.currentState}
|
||||||
|
|
@ -346,6 +346,19 @@ class Table extends React.Component {
|
||||||
onChange={(value) => this.onColumnItemChange(index, 'dateFormat', value)}
|
onChange={(value) => this.onColumnItemChange(index, 'dateFormat', value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<label className="form-label">Date Parse Format</label>
|
||||||
|
<div className="field mb-2">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control text-field"
|
||||||
|
onChange={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.onColumnItemChange(index, 'parseDateFormat', e.target.value);
|
||||||
|
}}
|
||||||
|
defaultValue={column.parseDateFormat}
|
||||||
|
placeholder={'DD-MM-YYYY'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="field mb-2">
|
<div className="field mb-2">
|
||||||
<label className="form-check form-switch my-2">
|
<label className="form-check form-switch my-2">
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,26 @@
|
||||||
"type": "dropdown-component-flip",
|
"type": "dropdown-component-flip",
|
||||||
"description": "Single select dropdown for operation",
|
"description": "Single select dropdown for operation",
|
||||||
"$options": [
|
"$options": [
|
||||||
{ "value": "read", "name": "Read data from a spreadsheet" },
|
{
|
||||||
{ "value": "append", "name": "Append data to a spreadsheet" },
|
"value": "read",
|
||||||
{ "value": "info", "name": "Get spreadsheet info" },
|
"name": "Read data from a spreadsheet"
|
||||||
{ "value": "delete_row", "name": "Delete row from a spreadsheet" }
|
},
|
||||||
|
{
|
||||||
|
"value": "append",
|
||||||
|
"name": "Append data to a spreadsheet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "info",
|
||||||
|
"name": "Get spreadsheet info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "update",
|
||||||
|
"name": "Update data to a spreadsheet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "delete_row",
|
||||||
|
"name": "Delete row from a spreadsheet"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"read": {
|
"read": {
|
||||||
|
|
@ -101,6 +117,51 @@
|
||||||
"lineNumbers": false,
|
"lineNumbers": false,
|
||||||
"description": "Enter row number"
|
"description": "Enter row number"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"spreadsheet_id": {
|
||||||
|
"$label": "Spreadsheet ID",
|
||||||
|
"$key": "spreadsheet_id",
|
||||||
|
"type": "codehinter",
|
||||||
|
"lineNumbers": false,
|
||||||
|
"description": "Enter spreadsheet_id"
|
||||||
|
},
|
||||||
|
"where_field": {
|
||||||
|
"$label": "Where",
|
||||||
|
"$key": "where_field",
|
||||||
|
"className": "col-4",
|
||||||
|
"type": "codehinter",
|
||||||
|
"lineNumbers": false,
|
||||||
|
"description": "Enter field"
|
||||||
|
},
|
||||||
|
"where_operation": {
|
||||||
|
"$label": "Operator",
|
||||||
|
"$key": "where_operation",
|
||||||
|
"className": "col-4",
|
||||||
|
"type": "dropdown",
|
||||||
|
"description": "Single select dropdown for where operation",
|
||||||
|
"$options": [
|
||||||
|
{
|
||||||
|
"value": "===",
|
||||||
|
"name": "==="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"where_value": {
|
||||||
|
"$label": "Value",
|
||||||
|
"$key": "where_value",
|
||||||
|
"className": "col-4",
|
||||||
|
"type": "codehinter",
|
||||||
|
"lineNumbers": false,
|
||||||
|
"description": "Enter value"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"$label": "Body",
|
||||||
|
"$key": "body",
|
||||||
|
"type": "codehinter",
|
||||||
|
"description": "Enter body",
|
||||||
|
"lineNumbers": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,11 @@ let QueryManager = class QueryManager extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {};
|
this.state = {
|
||||||
|
options: {},
|
||||||
|
selectedQuery: null,
|
||||||
|
selectedDataSource: null,
|
||||||
|
};
|
||||||
|
|
||||||
this.previewPanelRef = React.createRef();
|
this.previewPanelRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
@ -27,7 +31,7 @@ let QueryManager = class QueryManager extends React.Component {
|
||||||
const selectedQuery = props.selectedQuery;
|
const selectedQuery = props.selectedQuery;
|
||||||
const dataSourceId = selectedQuery?.data_source_id;
|
const dataSourceId = selectedQuery?.data_source_id;
|
||||||
const source = props.dataSources.find((datasource) => datasource.id === dataSourceId);
|
const source = props.dataSources.find((datasource) => datasource.id === dataSourceId);
|
||||||
const paneHeightChanged = this.state.queryPaneHeight !== props.queryPaneHeight;
|
// const paneHeightChanged = this.state.queryPaneHeight !== props.queryPaneHeight;
|
||||||
|
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
|
|
@ -56,13 +60,14 @@ let QueryManager = class QueryManager extends React.Component {
|
||||||
selectedQuery,
|
selectedQuery,
|
||||||
queryName: selectedQuery.name,
|
queryName: selectedQuery.name,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
options: {},
|
|
||||||
selectedQuery: null,
|
|
||||||
selectedDataSource: paneHeightChanged ? this.state.selectedDataSource : props.selectedDataSource,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// } else {
|
||||||
|
// this.setState({
|
||||||
|
// options: {},
|
||||||
|
// selectedQuery: null,
|
||||||
|
// selectedDataSource: paneHeightChanged ? this.state.selectedDataSource : props.selectedDataSource,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ const DynamicForm = ({
|
||||||
if (!isEditMode || isEmpty(options)) {
|
if (!isEditMode || isEmpty(options)) {
|
||||||
optionsChanged(schema?.defaults ?? {});
|
optionsChanged(schema?.defaults ?? {});
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getElement = (type) => {
|
const getElement = (type) => {
|
||||||
|
|
@ -71,6 +72,7 @@ const DynamicForm = ({
|
||||||
lineNumbers = true,
|
lineNumbers = true,
|
||||||
initialValue,
|
initialValue,
|
||||||
height = 'auto',
|
height = 'auto',
|
||||||
|
ignoreBraces = false,
|
||||||
}) => {
|
}) => {
|
||||||
const darkMode = localStorage.getItem('darkMode') === 'true';
|
const darkMode = localStorage.getItem('darkMode') === 'true';
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
@ -138,6 +140,7 @@ const DynamicForm = ({
|
||||||
theme: darkMode ? 'monokai' : lineNumbers ? 'duotone-light' : 'default',
|
theme: darkMode ? 'monokai' : lineNumbers ? 'duotone-light' : 'default',
|
||||||
placeholder,
|
placeholder,
|
||||||
height,
|
height,
|
||||||
|
ignoreBraces,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||||
import { QueryError } from 'src/modules/data_sources/query.error';
|
import { QueryError } from 'src/modules/data_sources/query.error';
|
||||||
import { QueryResult } from 'src/modules/data_sources/query_result.type';
|
import { QueryResult } from 'src/modules/data_sources/query_result.type';
|
||||||
import { QueryService } from 'src/modules/data_sources/query_service.interface';
|
import { QueryService } from 'src/modules/data_sources/query_service.interface';
|
||||||
import { readData, appendData, deleteData } from './operations';
|
import { readData, appendData, deleteData, batchUpdateToSheet } from './operations';
|
||||||
const got = require('got');
|
const got = require('got');
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
@ -71,6 +71,7 @@ export default class GooglesheetsQueryService implements QueryService {
|
||||||
const spreadsheetId = queryOptions['spreadsheet_id'];
|
const spreadsheetId = queryOptions['spreadsheet_id'];
|
||||||
const spreadsheetRange = queryOptions['spreadsheet_range'] ? queryOptions['spreadsheet_range'] : 'A1:Z500';
|
const spreadsheetRange = queryOptions['spreadsheet_range'] ? queryOptions['spreadsheet_range'] : 'A1:Z500';
|
||||||
const accessToken = sourceOptions['access_token'];
|
const accessToken = sourceOptions['access_token'];
|
||||||
|
const queryOptionFilter = { key: queryOptions['where_field'], value: queryOptions['where_value'] };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
|
|
@ -96,6 +97,16 @@ export default class GooglesheetsQueryService implements QueryService {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
result = await batchUpdateToSheet(
|
||||||
|
spreadsheetId,
|
||||||
|
queryOptions['body'],
|
||||||
|
queryOptionFilter,
|
||||||
|
queryOptions['where_operation'],
|
||||||
|
this.authHeader(accessToken)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'delete_row':
|
case 'delete_row':
|
||||||
result = await deleteData(
|
result = await deleteData(
|
||||||
spreadsheetId,
|
spreadsheetId,
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,85 @@ async function makeRequestToReadValues(spreadSheetId: string, sheet: string, ran
|
||||||
}
|
}
|
||||||
|
|
||||||
async function makeRequestToAppendValues(spreadSheetId: string, sheet: string, requestBody: any, authHeader: any) {
|
async function makeRequestToAppendValues(spreadSheetId: string, sheet: string, requestBody: any, authHeader: any) {
|
||||||
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}/values/${
|
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}/values/${sheet || ''
|
||||||
sheet || ''
|
}!A:Z:append?valueInputOption=USER_ENTERED`;
|
||||||
}!A:Z:append?valueInputOption=USER_ENTERED`;
|
|
||||||
|
|
||||||
return await got.post(url, { headers: authHeader, json: requestBody }).json();
|
return await got.post(url, { headers: authHeader, json: requestBody }).json();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function makeRequestToBatchUpdate(spreadSheetId: string, requestBody: any, authHeader: any) {
|
async function makeRequestToDeleteRows(spreadSheetId: string, requestBody: any, authHeader: any) {
|
||||||
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}:batchUpdate`;
|
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}:batchUpdate`;
|
||||||
|
|
||||||
return await got.post(url, { headers: authHeader, json: requestBody }).json();
|
return await got.post(url, { headers: authHeader, json: requestBody }).json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//*BatchUpdate Cell values
|
||||||
|
async function makeRequestToBatchUpdateValues(spreadSheetId: string, requestBody: any, authHeader: any) {
|
||||||
|
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}/values:batchUpdate`;
|
||||||
|
|
||||||
|
return await got.post(url, { headers: authHeader, json: requestBody }).json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeRequestToLookUpCellValues(spreadSheetId: string, range: string, authHeader: any) {
|
||||||
|
const url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadSheetId}/values/${range}?majorDimension=COLUMNS`;
|
||||||
|
|
||||||
|
return await got.get(url, { headers: authHeader }).json();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function batchUpdateToSheet(
|
||||||
|
spreadSheetId: string,
|
||||||
|
requestBody: any,
|
||||||
|
filterData: any,
|
||||||
|
filterOperator: string,
|
||||||
|
authHeader: any
|
||||||
|
) {
|
||||||
|
if (!filterOperator) {
|
||||||
|
return new Error('filterOperator is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const lookUpData = await lookUpSheetData(spreadSheetId, authHeader);
|
||||||
|
|
||||||
|
const updateBody = (requestBody, filterCondition, filterOperator, data) => {
|
||||||
|
const rowsIndexes = getRowsIndex(filterCondition, filterOperator, data) as any[];
|
||||||
|
const colIndexes = getInputKeys(requestBody, data);
|
||||||
|
|
||||||
|
const updateCellIndexes = [];
|
||||||
|
colIndexes.map((col) => {
|
||||||
|
rowsIndexes.map((rowIndex) => updateCellIndexes.push({ ...col, cellIndex: `${col.colIndex}${rowIndex}` }));
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = [];
|
||||||
|
Object.entries(requestBody).map((item) => {
|
||||||
|
updateCellIndexes.map((cell) => {
|
||||||
|
if (item[0] === cell.col) {
|
||||||
|
body.push({ cellValue: item[1], cellIndex: cell.cellIndex });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const _data = body.map((data) => {
|
||||||
|
return {
|
||||||
|
majorDimension: 'ROWS',
|
||||||
|
range: data.cellIndex,
|
||||||
|
values: [[data.cellValue]],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const reqBody = {
|
||||||
|
data: updateBody(requestBody, filterData, filterOperator, lookUpData),
|
||||||
|
valueInputOption: 'USER_ENTERED',
|
||||||
|
includeValuesInResponse: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!reqBody.data) return new Error('No data to update');
|
||||||
|
const response = await makeRequestToBatchUpdateValues(spreadSheetId, reqBody, authHeader);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
export async function readDataFromSheet(spreadSheetId: string, sheet: string, range: string, authHeader: any) {
|
export async function readDataFromSheet(spreadSheetId: string, sheet: string, range: string, authHeader: any) {
|
||||||
const data = await makeRequestToReadValues(spreadSheetId, sheet, range, authHeader);
|
const data = await makeRequestToReadValues(spreadSheetId, sheet, range, authHeader);
|
||||||
let headers = [];
|
let headers = [];
|
||||||
|
|
@ -83,7 +149,7 @@ async function deleteDataFromSheet(spreadSheetId: string, sheet: string, rowInde
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await makeRequestToBatchUpdate(spreadSheetId, requestBody, authHeader);
|
const response = await makeRequestToDeleteRows(spreadSheetId, requestBody, authHeader);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
@ -109,3 +175,56 @@ export async function deleteData(
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return await deleteDataFromSheet(spreadSheetId, sheet, rowIndex, authHeader);
|
return await deleteDataFromSheet(spreadSheetId, sheet, rowIndex, authHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function lookUpSheetData(spreadSheetId: string, authHeader: any) {
|
||||||
|
const responseLookUpCellValues = await makeRequestToLookUpCellValues(spreadSheetId, 'A1:Z500', authHeader);
|
||||||
|
const data = await responseLookUpCellValues['values'];
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//* utils
|
||||||
|
const getInputKeys = (inputBody, data) => {
|
||||||
|
const keys = Object.keys(inputBody);
|
||||||
|
const arr = [];
|
||||||
|
keys.map((key) =>
|
||||||
|
data.filter((val, index) => {
|
||||||
|
if (val[0] === key) {
|
||||||
|
const kIndex = `${String.fromCharCode(65 + index)}`;
|
||||||
|
arr.push({ col: val[0], colIndex: kIndex });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRowsIndex = (inputFilter, filterOperator, response) => {
|
||||||
|
const filterWithOperator = (type, array, value) => {
|
||||||
|
switch (type) {
|
||||||
|
case '===':
|
||||||
|
return array === value;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const columnValues = response.filter((column) => column[0] === inputFilter.key).flat();
|
||||||
|
|
||||||
|
if (columnValues.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rowIndex = [];
|
||||||
|
|
||||||
|
columnValues.forEach((col, index) => {
|
||||||
|
const inputValue = typeof inputFilter.value !== 'string' ? JSON.stringify(inputFilter.value) : inputFilter.value;
|
||||||
|
const isEqual = filterWithOperator(filterOperator, col, inputValue);
|
||||||
|
if (isEqual) {
|
||||||
|
rowIndex.push(index + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (rowIndex.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowIndex;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export class DataQueriesController {
|
||||||
private dataQueriesService: DataQueriesService,
|
private dataQueriesService: DataQueriesService,
|
||||||
private dataSourcesService: DataSourcesService,
|
private dataSourcesService: DataSourcesService,
|
||||||
private appsAbilityFactory: AppsAbilityFactory
|
private appsAbilityFactory: AppsAbilityFactory
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Get()
|
@Get()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue