2021-04-01 08:30:33 +00:00
|
|
|
import {
|
|
|
|
|
FontStyleTypes,
|
|
|
|
|
TextSizes,
|
2021-05-31 11:39:06 +00:00
|
|
|
GridDefaults,
|
2021-04-01 08:30:33 +00:00
|
|
|
} from "constants/WidgetConstants";
|
2021-12-29 11:42:07 +00:00
|
|
|
import {
|
|
|
|
|
generateTableColumnId,
|
|
|
|
|
getAllTableColumnKeys,
|
|
|
|
|
} from "widgets/TableWidget/component/TableHelpers";
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
import type { ColumnProperties } from "widgets/TableWidget/component/Constants";
|
2021-02-16 10:29:08 +00:00
|
|
|
import {
|
|
|
|
|
CellAlignmentTypes,
|
|
|
|
|
VerticalAlignmentTypes,
|
|
|
|
|
ColumnTypes,
|
2021-09-09 15:10:22 +00:00
|
|
|
} from "widgets/TableWidget/component/Constants";
|
2021-02-16 10:29:08 +00:00
|
|
|
import { Colors } from "constants/Colors";
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
import type { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
2021-02-16 10:29:08 +00:00
|
|
|
import { cloneDeep, isString } from "lodash";
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
import type { WidgetProps } from "widgets/BaseWidget";
|
|
|
|
|
import type { DSLWidget } from "widgets/constants";
|
2021-09-13 12:03:39 +00:00
|
|
|
import { getSubstringBetweenTwoWords } from "utils/helpers";
|
2022-11-05 09:54:20 +00:00
|
|
|
import { traverseDSLAndMigrate } from "utils/WidgetMigrationUtils";
|
|
|
|
|
import { isDynamicValue } from "utils/DynamicBindingUtils";
|
2022-12-16 04:35:51 +00:00
|
|
|
import { stringToJS } from "components/editorComponents/ActionCreator/utils";
|
2023-04-06 18:28:24 +00:00
|
|
|
import {
|
|
|
|
|
type ColumnProperties as ColumnPropertiesV2,
|
|
|
|
|
StickyType,
|
|
|
|
|
} from "widgets/TableWidgetV2/component/Constants";
|
2021-02-16 10:29:08 +00:00
|
|
|
|
2021-11-09 05:08:39 +00:00
|
|
|
export const isSortableMigration = (currentDSL: DSLWidget) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
|
|
|
|
if (child.type === "TABLE_WIDGET" && !child.hasOwnProperty("isSortable")) {
|
|
|
|
|
child["isSortable"] = true;
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = isSortableMigration(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-09-09 15:10:22 +00:00
|
|
|
export const tableWidgetPropertyPaneMigrations = (currentDSL: DSLWidget) => {
|
2021-02-16 10:29:08 +00:00
|
|
|
currentDSL.children = currentDSL.children?.map((_child: WidgetProps) => {
|
|
|
|
|
let child = cloneDeep(_child);
|
|
|
|
|
// If the current child is a TABLE_WIDGET
|
2021-09-09 15:10:22 +00:00
|
|
|
if (child.type === "TABLE_WIDGET") {
|
2021-02-16 10:29:08 +00:00
|
|
|
const hiddenColumns = child.hiddenColumns || [];
|
|
|
|
|
const columnNameMap = child.columnNameMap;
|
|
|
|
|
const columnSizeMap = child.columnSizeMap;
|
|
|
|
|
const columnTypeMap = child.columnTypeMap;
|
|
|
|
|
let tableColumns: string[] = [];
|
|
|
|
|
const dynamicBindingPathList = child.dynamicBindingPathList;
|
|
|
|
|
if (child.tableData.length) {
|
|
|
|
|
let tableData = [];
|
|
|
|
|
// Try parsing the table data, if it parses great
|
|
|
|
|
// If it does not parse, assign tableData the value as is.
|
|
|
|
|
try {
|
|
|
|
|
tableData = JSON.parse(child.tableData);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
tableData = child.tableData;
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
!isString(tableData) &&
|
|
|
|
|
dynamicBindingPathList?.findIndex((item) => item.key !== "tableData")
|
|
|
|
|
) {
|
|
|
|
|
// Get the list of column ids
|
|
|
|
|
tableColumns = getAllTableColumnKeys(tableData);
|
|
|
|
|
} else {
|
|
|
|
|
child.migrated = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Get primaryColumns to be the list of column keys
|
|
|
|
|
// Use the old order if it exists, else use the new order
|
|
|
|
|
const primaryColumns = child.columnOrder?.length
|
|
|
|
|
? child.columnOrder
|
|
|
|
|
: tableColumns;
|
|
|
|
|
child.primaryColumns = {};
|
|
|
|
|
|
|
|
|
|
// const hasActions = child.columnActions && child.columnActions.length > 0;
|
|
|
|
|
// Generate new primarycolumns
|
|
|
|
|
primaryColumns.forEach((accessor: string, index: number) => {
|
|
|
|
|
// Get the column type from the columnTypeMap
|
|
|
|
|
let columnType =
|
|
|
|
|
columnTypeMap && columnTypeMap[accessor]
|
|
|
|
|
? columnTypeMap[accessor].type
|
|
|
|
|
: ColumnTypes.TEXT;
|
|
|
|
|
// If the columnType is currency make it a text type
|
|
|
|
|
// We're deprecating currency types
|
|
|
|
|
if (columnType === "currency") {
|
|
|
|
|
columnType = ColumnTypes.TEXT;
|
|
|
|
|
}
|
|
|
|
|
// Get a full set of column properties
|
|
|
|
|
const column: ColumnProperties = {
|
|
|
|
|
index, // Use to maintain order of columns
|
|
|
|
|
// The widget of the column
|
|
|
|
|
width:
|
|
|
|
|
columnSizeMap && columnSizeMap[accessor]
|
|
|
|
|
? columnSizeMap[accessor]
|
|
|
|
|
: 150,
|
|
|
|
|
// id of the column
|
|
|
|
|
id: accessor,
|
|
|
|
|
// default horizontal alignment
|
|
|
|
|
horizontalAlignment: CellAlignmentTypes.LEFT,
|
|
|
|
|
// default vertical alignment
|
|
|
|
|
verticalAlignment: VerticalAlignmentTypes.CENTER,
|
|
|
|
|
// columnType
|
|
|
|
|
columnType,
|
|
|
|
|
// default text color
|
|
|
|
|
textColor: Colors.THUNDER,
|
|
|
|
|
// default text size
|
|
|
|
|
textSize: TextSizes.PARAGRAPH,
|
|
|
|
|
// default font size
|
|
|
|
|
fontStyle: FontStyleTypes.REGULAR,
|
|
|
|
|
enableFilter: true,
|
|
|
|
|
enableSort: true,
|
|
|
|
|
// hide the column if it was hidden earlier using hiddenColumns
|
|
|
|
|
isVisible: hiddenColumns.includes(accessor) ? false : true,
|
|
|
|
|
// We did not have a concept of derived columns so far
|
|
|
|
|
isDerived: false,
|
|
|
|
|
// Use renamed names from the map
|
|
|
|
|
// or use the newly generated name
|
|
|
|
|
label:
|
|
|
|
|
columnNameMap && columnNameMap[accessor]
|
|
|
|
|
? columnNameMap[accessor]
|
|
|
|
|
: accessor,
|
|
|
|
|
// Generate computed value
|
2021-07-22 08:43:58 +00:00
|
|
|
computedValue: `{{${child.widgetName}.sanitizedTableData.map((currentRow) => ( currentRow.${accessor})}}`,
|
2021-02-16 10:29:08 +00:00
|
|
|
};
|
|
|
|
|
// copy inputForma nd outputFormat for date column types
|
|
|
|
|
if (columnTypeMap && columnTypeMap[accessor]) {
|
|
|
|
|
column.outputFormat = columnTypeMap[accessor].format || "";
|
|
|
|
|
column.inputFormat = columnTypeMap[accessor].inputFormat || "";
|
|
|
|
|
}
|
|
|
|
|
child.primaryColumns[column.id] = column;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Get all column actions
|
|
|
|
|
const columnActions = child.columnActions || [];
|
|
|
|
|
// Get dynamicTriggerPathList
|
|
|
|
|
let dynamicTriggerPathList: Array<{ key: string }> =
|
|
|
|
|
child.dynamicTriggerPathList || [];
|
|
|
|
|
|
|
|
|
|
const columnPrefix = "customColumn";
|
|
|
|
|
const updatedDerivedColumns: Record<string, ColumnProperties> = {};
|
|
|
|
|
// Add derived column for each column action
|
|
|
|
|
columnActions.forEach((action: ColumnAction, index: number) => {
|
|
|
|
|
const column = {
|
|
|
|
|
index: child.primaryColumns.length + index, // Add to the end of the columns list
|
|
|
|
|
width: 150, // Default width
|
|
|
|
|
id: `${columnPrefix}${index + 1}`, // A random string which was generated previously
|
|
|
|
|
label: action.label, // Revert back to "Actions"
|
|
|
|
|
columnType: "button", // All actions are buttons
|
|
|
|
|
isVisible: true,
|
2021-08-17 12:54:43 +00:00
|
|
|
isDisabled: false,
|
2021-02-16 10:29:08 +00:00
|
|
|
isDerived: true,
|
|
|
|
|
buttonLabel: action.label,
|
2021-03-02 03:13:43 +00:00
|
|
|
buttonStyle: "rgb(3, 179, 101)",
|
2021-02-16 10:29:08 +00:00
|
|
|
buttonLabelColor: "#FFFFFF",
|
|
|
|
|
onClick: action.dynamicTrigger,
|
|
|
|
|
computedValue: "",
|
|
|
|
|
};
|
2021-02-19 04:49:54 +00:00
|
|
|
dynamicTriggerPathList.push({
|
|
|
|
|
key: `primaryColumns.${columnPrefix}${index + 1}.onClick`,
|
|
|
|
|
});
|
2021-02-16 10:29:08 +00:00
|
|
|
updatedDerivedColumns[column.id] = column;
|
2021-02-24 10:29:19 +00:00
|
|
|
child.primaryColumns[column.id] = column;
|
2021-02-16 10:29:08 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (Object.keys(updatedDerivedColumns).length) {
|
|
|
|
|
dynamicTriggerPathList = dynamicTriggerPathList.filter(
|
|
|
|
|
(triggerPath: Record<string, string>) => {
|
|
|
|
|
triggerPath.key !== "columnActions";
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
child.dynamicTriggerPathList = dynamicTriggerPathList;
|
|
|
|
|
child.textSize = TextSizes.PARAGRAPH;
|
|
|
|
|
child.horizontalAlignment = CellAlignmentTypes.LEFT;
|
|
|
|
|
child.verticalAlignment = VerticalAlignmentTypes.CENTER;
|
|
|
|
|
child.fontStyle = FontStyleTypes.REGULAR;
|
|
|
|
|
|
|
|
|
|
child.derivedColumns = updatedDerivedColumns;
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = tableWidgetPropertyPaneMigrations(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-02-25 11:51:54 +00:00
|
|
|
|
|
|
|
|
const removeSpecialChars = (value: string, limit?: number) => {
|
2021-08-10 07:57:29 +00:00
|
|
|
const separatorRegex = /\W+/;
|
2021-02-25 11:51:54 +00:00
|
|
|
return value
|
|
|
|
|
.split(separatorRegex)
|
|
|
|
|
.join("_")
|
|
|
|
|
.slice(0, limit || 30);
|
|
|
|
|
};
|
|
|
|
|
|
2021-09-09 15:10:22 +00:00
|
|
|
export const migrateTablePrimaryColumnsBindings = (currentDSL: DSLWidget) => {
|
2021-02-25 11:51:54 +00:00
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
2021-09-09 15:10:22 +00:00
|
|
|
if (child.type === "TABLE_WIDGET") {
|
2021-02-25 11:51:54 +00:00
|
|
|
if (
|
|
|
|
|
child.primaryColumns &&
|
|
|
|
|
Object.keys(child.primaryColumns).length > 0
|
|
|
|
|
) {
|
|
|
|
|
const newPrimaryColumns: Record<string, ColumnProperties> = {};
|
|
|
|
|
for (const [key, value] of Object.entries(
|
|
|
|
|
child.primaryColumns as Record<string, ColumnProperties>,
|
|
|
|
|
)) {
|
|
|
|
|
const sanitizedKey = removeSpecialChars(key, 200);
|
|
|
|
|
const newComputedValue = value.computedValue
|
|
|
|
|
? value.computedValue.replace(
|
|
|
|
|
`${child.widgetName}.tableData.map`,
|
|
|
|
|
`${child.widgetName}.sanitizedTableData.map`,
|
|
|
|
|
)
|
|
|
|
|
: "";
|
|
|
|
|
newPrimaryColumns[sanitizedKey] = {
|
|
|
|
|
...value,
|
|
|
|
|
computedValue: newComputedValue,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
child.primaryColumns = newPrimaryColumns;
|
|
|
|
|
child.dynamicBindingPathList = child.dynamicBindingPathList?.map(
|
|
|
|
|
(path) => {
|
|
|
|
|
path.key = path.key.split(" ").join("_");
|
|
|
|
|
return path;
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTablePrimaryColumnsBindings(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-05-31 11:39:06 +00:00
|
|
|
|
|
|
|
|
export const migrateTableWidgetParentRowSpaceProperty = (
|
2021-09-09 15:10:22 +00:00
|
|
|
currentDSL: DSLWidget,
|
2021-05-31 11:39:06 +00:00
|
|
|
) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
2021-09-09 15:10:22 +00:00
|
|
|
if (child.type === "TABLE_WIDGET") {
|
2021-05-31 11:39:06 +00:00
|
|
|
if (child.parentRowSpace === 40) {
|
|
|
|
|
child.parentRowSpace = GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
|
|
|
|
|
}
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetParentRowSpaceProperty(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-06-09 10:16:48 +00:00
|
|
|
|
|
|
|
|
export const migrateTableWidgetHeaderVisibilityProperties = (
|
2021-09-09 15:10:22 +00:00
|
|
|
currentDSL: DSLWidget,
|
2021-06-09 10:16:48 +00:00
|
|
|
) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
2021-09-09 15:10:22 +00:00
|
|
|
if (child.type === "TABLE_WIDGET") {
|
2021-06-09 10:16:48 +00:00
|
|
|
if (!("isVisibleSearch" in child)) {
|
|
|
|
|
child.isVisibleSearch = true;
|
|
|
|
|
child.isVisibleFilters = true;
|
|
|
|
|
child.isVisibleDownload = true;
|
|
|
|
|
child.isVisiblePagination = true;
|
|
|
|
|
}
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetHeaderVisibilityProperties(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-07-22 08:43:58 +00:00
|
|
|
|
2021-08-18 10:33:26 +00:00
|
|
|
export const migrateTableWidgetDelimiterProperties = (
|
2021-09-09 15:10:22 +00:00
|
|
|
currentDSL: DSLWidget,
|
2021-08-18 10:33:26 +00:00
|
|
|
) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
2021-09-09 15:10:22 +00:00
|
|
|
if (child.type === "TABLE_WIDGET") {
|
2021-08-18 10:33:26 +00:00
|
|
|
if (!child.delimiter) {
|
|
|
|
|
child.delimiter = ",";
|
|
|
|
|
}
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetDelimiterProperties(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
|
|
|
|
|
2021-07-22 08:43:58 +00:00
|
|
|
export const migrateTablePrimaryColumnsComputedValue = (
|
2021-09-09 15:10:22 +00:00
|
|
|
currentDSL: DSLWidget,
|
2021-07-22 08:43:58 +00:00
|
|
|
) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
2021-09-09 15:10:22 +00:00
|
|
|
if (child.type === "TABLE_WIDGET") {
|
2021-07-22 08:43:58 +00:00
|
|
|
if (
|
|
|
|
|
child.primaryColumns &&
|
|
|
|
|
Object.keys(child.primaryColumns).length > 0
|
|
|
|
|
) {
|
|
|
|
|
const newPrimaryColumns: Record<string, ColumnProperties> = {};
|
|
|
|
|
for (const [key, value] of Object.entries(
|
|
|
|
|
child.primaryColumns as Record<string, ColumnProperties>,
|
|
|
|
|
)) {
|
|
|
|
|
const sanitizedKey = removeSpecialChars(key, 200);
|
|
|
|
|
let newComputedValue = "";
|
|
|
|
|
if (value.computedValue) {
|
|
|
|
|
newComputedValue = value.computedValue.replace(
|
|
|
|
|
`${child.widgetName}.sanitizedTableData.map((currentRow) => { return`,
|
|
|
|
|
`${child.widgetName}.sanitizedTableData.map((currentRow) => (`,
|
|
|
|
|
);
|
|
|
|
|
// change matching "}" bracket with ")"
|
|
|
|
|
const lastParanthesesInd = newComputedValue.length - 4;
|
|
|
|
|
newComputedValue =
|
|
|
|
|
newComputedValue.substring(0, lastParanthesesInd) +
|
|
|
|
|
")" +
|
|
|
|
|
newComputedValue.substring(lastParanthesesInd + 1);
|
|
|
|
|
}
|
|
|
|
|
newPrimaryColumns[sanitizedKey] = {
|
|
|
|
|
...value,
|
|
|
|
|
computedValue: newComputedValue,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
child.primaryColumns = newPrimaryColumns;
|
|
|
|
|
}
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTablePrimaryColumnsComputedValue(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-09-13 12:03:39 +00:00
|
|
|
|
2021-09-23 11:46:47 +00:00
|
|
|
const getUpdatedColumns = (
|
|
|
|
|
widgetName: string,
|
|
|
|
|
columns: Record<string, ColumnProperties>,
|
|
|
|
|
) => {
|
|
|
|
|
const updatedColumns: Record<string, ColumnProperties> = {};
|
|
|
|
|
if (columns && Object.keys(columns).length > 0) {
|
|
|
|
|
for (const [columnId, columnProps] of Object.entries(columns)) {
|
|
|
|
|
const sanitizedColumnId = removeSpecialChars(columnId, 200);
|
|
|
|
|
const selectedRowBindingValue = `${widgetName}.selectedRow`;
|
|
|
|
|
let newOnClickBindingValue = undefined;
|
|
|
|
|
if (
|
|
|
|
|
columnProps.onClick &&
|
|
|
|
|
columnProps.onClick.includes(selectedRowBindingValue)
|
|
|
|
|
) {
|
|
|
|
|
newOnClickBindingValue = columnProps.onClick.replace(
|
|
|
|
|
selectedRowBindingValue,
|
|
|
|
|
"currentRow",
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-09-27 05:15:51 +00:00
|
|
|
updatedColumns[sanitizedColumnId] = columnProps;
|
|
|
|
|
if (newOnClickBindingValue)
|
|
|
|
|
updatedColumns[sanitizedColumnId].onClick = newOnClickBindingValue;
|
2021-09-23 11:46:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return updatedColumns;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const migrateTableWidgetSelectedRowBindings = (
|
|
|
|
|
currentDSL: DSLWidget,
|
|
|
|
|
) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
|
|
|
|
if (child.type === "TABLE_WIDGET") {
|
|
|
|
|
child.derivedColumns = getUpdatedColumns(
|
|
|
|
|
child.widgetName,
|
|
|
|
|
child.derivedColumns as Record<string, ColumnProperties>,
|
|
|
|
|
);
|
|
|
|
|
child.primaryColumns = getUpdatedColumns(
|
|
|
|
|
child.widgetName,
|
|
|
|
|
child.primaryColumns as Record<string, ColumnProperties>,
|
|
|
|
|
);
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetSelectedRowBindings(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
|
|
|
|
|
2021-09-13 12:03:39 +00:00
|
|
|
/**
|
|
|
|
|
* This migration sanitizes the following properties -
|
|
|
|
|
* primaryColumns object key, for the value of each key - id, computedValue are sanitized
|
|
|
|
|
* columnOrder
|
|
|
|
|
* dynamicBindingPathList
|
|
|
|
|
*
|
|
|
|
|
* This migration solves the following issue -
|
|
|
|
|
* https://github.com/appsmithorg/appsmith/issues/6897
|
|
|
|
|
*/
|
|
|
|
|
export const migrateTableSanitizeColumnKeys = (currentDSL: DSLWidget) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
|
|
|
|
if (child.type === "TABLE_WIDGET") {
|
|
|
|
|
const primaryColumnEntries: [string, ColumnProperties][] = Object.entries(
|
|
|
|
|
child.primaryColumns || {},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const newPrimaryColumns: Record<string, ColumnProperties> = {};
|
|
|
|
|
if (primaryColumnEntries.length) {
|
2021-11-12 09:33:47 +00:00
|
|
|
for (const [, primaryColumnEntry] of primaryColumnEntries.entries()) {
|
|
|
|
|
// Value is reassigned when its invalid(Faulty DSL https://github.com/appsmithorg/appsmith/issues/8979)
|
|
|
|
|
const [key] = primaryColumnEntry;
|
|
|
|
|
let [, value] = primaryColumnEntry;
|
2021-09-13 12:03:39 +00:00
|
|
|
const sanitizedKey = removeSpecialChars(key, 200);
|
2021-11-12 09:33:47 +00:00
|
|
|
let id = "";
|
|
|
|
|
if (value.id) {
|
|
|
|
|
id = removeSpecialChars(value.id, 200);
|
|
|
|
|
}
|
|
|
|
|
// When id is undefined it's likely value isn't correct and needs fixing
|
|
|
|
|
else if (Object.keys(value)) {
|
|
|
|
|
const onlyKey = Object.keys(value)[0] as keyof ColumnProperties;
|
|
|
|
|
const obj: ColumnProperties = value[onlyKey] as any;
|
|
|
|
|
if (!obj.id && !obj.columnType) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
value = obj;
|
|
|
|
|
id = removeSpecialChars(value.id, 200);
|
|
|
|
|
}
|
2021-09-13 12:03:39 +00:00
|
|
|
|
|
|
|
|
// Sanitizes "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.$$$random_header))}}"
|
|
|
|
|
// to "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow._random_header))}}"
|
|
|
|
|
const computedValue = (value?.computedValue || "").replace(
|
|
|
|
|
key,
|
|
|
|
|
sanitizedKey,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
newPrimaryColumns[sanitizedKey] = {
|
|
|
|
|
...value,
|
|
|
|
|
computedValue,
|
|
|
|
|
id,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
child.primaryColumns = newPrimaryColumns;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sanitizes [ "id", "name", $$$random_header ]
|
|
|
|
|
// to [ "id", "name", _random_header ]
|
|
|
|
|
child.columnOrder = (child.columnOrder || []).map((co: string) =>
|
|
|
|
|
removeSpecialChars(co, 200),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Sanitizes [ {key: primaryColumns.$random.header.computedValue }]
|
|
|
|
|
// to [ {key: primaryColumns._random_header.computedValue }]
|
|
|
|
|
child.dynamicBindingPathList = (child.dynamicBindingPathList || []).map(
|
|
|
|
|
(path) => {
|
|
|
|
|
const pathChunks = path.key.split("."); // primaryColumns.$random.header.computedValue -> [ "primaryColumns", "$random", "header", "computedValue"]
|
|
|
|
|
|
|
|
|
|
// tableData is a valid dynamicBindingPath and pathChunks would have just one entry
|
|
|
|
|
if (pathChunks.length < 2) {
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const firstPart = pathChunks[0] + "."; // "primaryColumns."
|
|
|
|
|
const lastPart = "." + pathChunks[pathChunks.length - 1]; // ".computedValue"
|
|
|
|
|
|
|
|
|
|
const key = getSubstringBetweenTwoWords(
|
|
|
|
|
path.key,
|
|
|
|
|
firstPart,
|
|
|
|
|
lastPart,
|
|
|
|
|
); // primaryColumns.$random.header.computedValue -> $random.header
|
|
|
|
|
|
|
|
|
|
const sanitizedPrimaryColumnKey = removeSpecialChars(key, 200);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
key: firstPart + sanitizedPrimaryColumnKey + lastPart,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableSanitizeColumnKeys(child);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-11-23 14:10:13 +00:00
|
|
|
|
|
|
|
|
export const migrateTableWidgetIconButtonVariant = (currentDSL: DSLWidget) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
|
|
|
|
if (child.type === "TABLE_WIDGET") {
|
|
|
|
|
const primaryColumns = child.primaryColumns as Record<
|
|
|
|
|
string,
|
|
|
|
|
ColumnProperties
|
|
|
|
|
>;
|
|
|
|
|
Object.keys(primaryColumns).forEach((accessor: string) => {
|
|
|
|
|
const primaryColumn = primaryColumns[accessor];
|
|
|
|
|
|
|
|
|
|
if (primaryColumn.columnType === "iconButton") {
|
|
|
|
|
if (!("buttonVariant" in primaryColumn)) {
|
|
|
|
|
primaryColumn.buttonVariant = "TERTIARY";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetIconButtonVariant(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2021-12-29 11:42:07 +00:00
|
|
|
|
2022-02-04 17:37:22 +00:00
|
|
|
/*
|
|
|
|
|
* DO NOT USE THIS. it overwrites conputedValues of the Table Columns
|
|
|
|
|
*/
|
2021-12-29 11:42:07 +00:00
|
|
|
export const migrateTableWidgetNumericColumnName = (currentDSL: DSLWidget) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
|
|
|
|
if (child.type === "TABLE_WIDGET") {
|
|
|
|
|
child.columnOrder = (child.columnOrder || []).map((col: string) =>
|
|
|
|
|
generateTableColumnId(col),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const primaryColumns = { ...child.primaryColumns };
|
|
|
|
|
// clear old primaryColumns
|
|
|
|
|
child.primaryColumns = {};
|
|
|
|
|
for (const key in primaryColumns) {
|
|
|
|
|
if (Object.prototype.hasOwnProperty.call(primaryColumns, key)) {
|
|
|
|
|
const column = primaryColumns[key];
|
|
|
|
|
const columnId = generateTableColumnId(key);
|
|
|
|
|
const newComputedValue = `{{${child.widgetName}.sanitizedTableData.map((currentRow) => ( currentRow.${columnId}))}}`;
|
|
|
|
|
// added column with old accessor
|
|
|
|
|
child.primaryColumns[columnId] = {
|
|
|
|
|
...column,
|
|
|
|
|
id: columnId,
|
|
|
|
|
computedValue: newComputedValue,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
child.dynamicBindingPathList = (child.dynamicBindingPathList || []).map(
|
|
|
|
|
(path) => {
|
|
|
|
|
const pathChunks = path.key.split(".");
|
|
|
|
|
// tableData is a valid dynamicBindingPath and pathChunks would have just one entry
|
|
|
|
|
if (pathChunks.length < 2) {
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
const firstPart = pathChunks[0] + "."; // "primaryColumns."
|
|
|
|
|
const lastPart = "." + pathChunks.pop(); // ".computedValue"
|
|
|
|
|
const key = getSubstringBetweenTwoWords(
|
|
|
|
|
path.key,
|
|
|
|
|
firstPart,
|
|
|
|
|
lastPart,
|
|
|
|
|
); // primaryColumns.$random.header.computedValue -> $random.header
|
|
|
|
|
|
|
|
|
|
const sanitizedPrimaryColumnKey = generateTableColumnId(key);
|
|
|
|
|
return {
|
|
|
|
|
key: firstPart + sanitizedPrimaryColumnKey + lastPart,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetNumericColumnName(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2022-09-13 05:41:59 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Adds validation object to each column in the primaryColumns
|
|
|
|
|
*/
|
|
|
|
|
export const migrateTableWidgetV2Validation = (currentDSL: DSLWidget) => {
|
|
|
|
|
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
|
|
|
|
|
if (child.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
const primaryColumns = child.primaryColumns;
|
|
|
|
|
|
|
|
|
|
for (const key in primaryColumns) {
|
|
|
|
|
if (primaryColumns.hasOwnProperty(key)) {
|
|
|
|
|
primaryColumns[key].validation = {};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (child.children && child.children.length > 0) {
|
|
|
|
|
child = migrateTableWidgetV2Validation(child);
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return currentDSL;
|
|
|
|
|
};
|
2022-11-05 09:54:20 +00:00
|
|
|
|
|
|
|
|
const oldBindingPrefix = `{{
|
|
|
|
|
(
|
|
|
|
|
(editedValue, currentRow, currentIndex) => (
|
|
|
|
|
`;
|
|
|
|
|
const newBindingPrefix = `{{
|
|
|
|
|
(
|
|
|
|
|
(editedValue, currentRow, currentIndex, isNewRow) => (
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const oldBindingSuffix = (tableId: string, columnName: string) => `
|
|
|
|
|
))
|
|
|
|
|
(
|
|
|
|
|
${tableId}.columnEditableCellValue.${columnName} || "",
|
|
|
|
|
${tableId}.processedTableData[${tableId}.editableCell.index] ||
|
|
|
|
|
Object.keys(${tableId}.processedTableData[0])
|
|
|
|
|
.filter(key => ["__originalIndex__", "__primaryKey__"].indexOf(key) === -1)
|
|
|
|
|
.reduce((prev, curr) => {
|
|
|
|
|
prev[curr] = "";
|
|
|
|
|
return prev;
|
|
|
|
|
}, {}),
|
|
|
|
|
${tableId}.editableCell.index)
|
|
|
|
|
}}
|
|
|
|
|
`;
|
|
|
|
|
const newBindingSuffix = (tableId: string, columnName: string) => {
|
|
|
|
|
return `
|
|
|
|
|
))
|
|
|
|
|
(
|
|
|
|
|
(${tableId}.isAddRowInProgress ? ${tableId}.newRow.${columnName} : ${tableId}.columnEditableCellValue.${columnName}) || "",
|
|
|
|
|
${tableId}.isAddRowInProgress ? ${tableId}.newRow : (${tableId}.processedTableData[${tableId}.editableCell.index] ||
|
|
|
|
|
Object.keys(${tableId}.processedTableData[0])
|
|
|
|
|
.filter(key => ["__originalIndex__", "__primaryKey__"].indexOf(key) === -1)
|
|
|
|
|
.reduce((prev, curr) => {
|
|
|
|
|
prev[curr] = "";
|
|
|
|
|
return prev;
|
|
|
|
|
}, {})),
|
|
|
|
|
${tableId}.isAddRowInProgress ? -1 : ${tableId}.editableCell.index,
|
|
|
|
|
${tableId}.isAddRowInProgress
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
|
`;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const migrateTableWidgetV2ValidationBinding = (
|
|
|
|
|
currentDSL: DSLWidget,
|
|
|
|
|
) => {
|
|
|
|
|
return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => {
|
|
|
|
|
if (widget.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
const primaryColumns = widget.primaryColumns;
|
|
|
|
|
|
|
|
|
|
for (const column in primaryColumns) {
|
|
|
|
|
if (
|
|
|
|
|
primaryColumns.hasOwnProperty(column) &&
|
|
|
|
|
primaryColumns[column].validation &&
|
|
|
|
|
primaryColumns[column].validation.isColumnEditableCellValid &&
|
|
|
|
|
isDynamicValue(
|
|
|
|
|
primaryColumns[column].validation.isColumnEditableCellValid,
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
const propertyValue =
|
|
|
|
|
primaryColumns[column].validation.isColumnEditableCellValid;
|
|
|
|
|
|
|
|
|
|
const binding = propertyValue
|
|
|
|
|
.replace(oldBindingPrefix, "")
|
|
|
|
|
.replace(oldBindingSuffix(widget.widgetName, column), "");
|
|
|
|
|
|
|
|
|
|
primaryColumns[column].validation.isColumnEditableCellValid =
|
|
|
|
|
newBindingPrefix +
|
|
|
|
|
binding +
|
|
|
|
|
newBindingSuffix(widget.widgetName, column);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2022-12-16 04:35:51 +00:00
|
|
|
|
|
|
|
|
export const migrateTableWidgetV2SelectOption = (currentDSL: DSLWidget) => {
|
|
|
|
|
return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => {
|
|
|
|
|
if (widget.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
Object.values(
|
|
|
|
|
widget.primaryColumns as Record<
|
|
|
|
|
string,
|
|
|
|
|
{ columnType: string; selectOptions: string }
|
|
|
|
|
>,
|
|
|
|
|
)
|
|
|
|
|
.filter((column) => column.columnType === "select")
|
|
|
|
|
.forEach((column) => {
|
|
|
|
|
const selectOptions = column.selectOptions;
|
|
|
|
|
|
|
|
|
|
if (selectOptions && isDynamicValue(selectOptions)) {
|
|
|
|
|
column.selectOptions = `{{${
|
|
|
|
|
widget.widgetName
|
|
|
|
|
}.processedTableData.map((currentRow, currentIndex) => ( ${stringToJS(
|
|
|
|
|
selectOptions,
|
|
|
|
|
)}))}}`;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2022-12-30 10:52:11 +00:00
|
|
|
|
|
|
|
|
export const migrateMenuButtonDynamicItemsInsideTableWidget = (
|
|
|
|
|
currentDSL: DSLWidget,
|
|
|
|
|
) => {
|
|
|
|
|
return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => {
|
|
|
|
|
if (widget.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
const primaryColumns = widget.primaryColumns;
|
|
|
|
|
|
|
|
|
|
if (primaryColumns) {
|
|
|
|
|
for (const column in primaryColumns) {
|
|
|
|
|
if (
|
|
|
|
|
primaryColumns.hasOwnProperty(column) &&
|
|
|
|
|
primaryColumns[column].columnType === "menuButton" &&
|
|
|
|
|
!primaryColumns[column].menuItemsSource
|
|
|
|
|
) {
|
|
|
|
|
primaryColumns[column].menuItemsSource = "STATIC";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2023-02-15 11:42:46 +00:00
|
|
|
|
|
|
|
|
export const migrateColumnFreezeAttributes = (currentDSL: DSLWidget) => {
|
|
|
|
|
return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => {
|
|
|
|
|
if (widget.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
const primaryColumns = widget?.primaryColumns;
|
|
|
|
|
|
|
|
|
|
// Assign default sticky value to each column
|
|
|
|
|
if (primaryColumns) {
|
|
|
|
|
for (const column in primaryColumns) {
|
|
|
|
|
if (!primaryColumns[column].hasOwnProperty("sticky")) {
|
|
|
|
|
primaryColumns[column].sticky = StickyType.NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
widget.canFreezeColumn = false;
|
|
|
|
|
widget.columnUpdatedAt = Date.now();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2023-04-06 18:28:24 +00:00
|
|
|
|
|
|
|
|
export const migrateTableSelectOptionAttributesForNewRow = (
|
|
|
|
|
currentDSL: DSLWidget,
|
|
|
|
|
) => {
|
|
|
|
|
return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => {
|
|
|
|
|
if (widget.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
const primaryColumns = widget?.primaryColumns as ColumnPropertiesV2;
|
|
|
|
|
|
|
|
|
|
// Set default value for allowSameOptionsInNewRow
|
|
|
|
|
if (primaryColumns) {
|
|
|
|
|
Object.values(primaryColumns).forEach((column) => {
|
|
|
|
|
if (
|
|
|
|
|
column.hasOwnProperty("columnType") &&
|
|
|
|
|
column.columnType === "select"
|
|
|
|
|
) {
|
|
|
|
|
column.allowSameOptionsInNewRow = true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2023-05-05 13:55:10 +00:00
|
|
|
|
|
|
|
|
export const migrateBindingPrefixSuffixForInlineEditValidationControl = (
|
|
|
|
|
currentDSL: DSLWidget,
|
|
|
|
|
) => {
|
|
|
|
|
return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => {
|
|
|
|
|
if (widget.type === "TABLE_WIDGET_V2") {
|
|
|
|
|
const tableId = widget.widgetName;
|
|
|
|
|
|
|
|
|
|
const oldBindingPrefix = `{{((isNewRow)=>(`;
|
|
|
|
|
const newBindingPrefix = `{{
|
|
|
|
|
(
|
|
|
|
|
(isNewRow, currentIndex, currentRow) => (
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const oldBindingSuffix = `))(${tableId}.isAddRowInProgress)}}`;
|
|
|
|
|
const newBindingSuffix = `
|
|
|
|
|
))
|
|
|
|
|
(
|
|
|
|
|
${tableId}.isAddRowInProgress,
|
|
|
|
|
${tableId}.isAddRowInProgress ? -1 : ${tableId}.editableCell.index,
|
|
|
|
|
${tableId}.isAddRowInProgress ? ${tableId}.newRow : (${tableId}.processedTableData[${tableId}.editableCell.index] ||
|
|
|
|
|
Object.keys(${tableId}.processedTableData[0])
|
|
|
|
|
.filter(key => ["__originalIndex__", "__primaryKey__"].indexOf(key) === -1)
|
|
|
|
|
.reduce((prev, curr) => {
|
|
|
|
|
prev[curr] = "";
|
|
|
|
|
return prev;
|
|
|
|
|
}, {}))
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
|
`;
|
|
|
|
|
const applicableValidationNames = [
|
|
|
|
|
"min",
|
|
|
|
|
"max",
|
|
|
|
|
"regex",
|
|
|
|
|
"errorMessage",
|
|
|
|
|
"isColumnEditableCellRequired",
|
|
|
|
|
];
|
|
|
|
|
const primaryColumns = widget?.primaryColumns as ColumnPropertiesV2;
|
|
|
|
|
|
|
|
|
|
Object.values(primaryColumns).forEach((column) => {
|
|
|
|
|
if (column.hasOwnProperty("validation")) {
|
|
|
|
|
const validations = column.validation;
|
|
|
|
|
for (const validationName in validations) {
|
|
|
|
|
if (applicableValidationNames.indexOf(validationName) == -1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const validationValue = validations[validationName];
|
|
|
|
|
if (typeof validationValue !== "string") {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let compressedValidationValue = validationValue.replace(/\s/g, "");
|
|
|
|
|
compressedValidationValue = compressedValidationValue.replace(
|
|
|
|
|
oldBindingPrefix,
|
|
|
|
|
newBindingPrefix,
|
|
|
|
|
);
|
|
|
|
|
compressedValidationValue = compressedValidationValue.replace(
|
|
|
|
|
oldBindingSuffix,
|
|
|
|
|
newBindingSuffix,
|
|
|
|
|
);
|
|
|
|
|
validations[validationName] = compressedValidationValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|