PromucFlow_constructor/app/client/src/widgets/TableWidgetV2/widget/utilities.ts

957 lines
26 KiB
TypeScript
Raw Normal View History

import { Colors } from "constants/Colors";
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
import {
FontStyleTypes,
RenderMode,
RenderModes,
} from "constants/WidgetConstants";
import _, { filter, isBoolean, isObject, uniq, without } from "lodash";
import tinycolor from "tinycolor2";
import {
CellAlignmentTypes,
CellLayoutProperties,
ColumnProperties,
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
StickyType,
TableColumnProps,
TableStyles,
VerticalAlignmentTypes,
} from "../component/Constants";
import {
ColumnTypes,
DEFAULT_BUTTON_COLOR,
DEFAULT_COLUMN_WIDTH,
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
TABLE_COLUMN_ORDER_KEY,
ORIGINAL_INDEX_KEY,
} from "../constants";
import { SelectColumnOptionsValidations } from "./propertyUtils";
import { TableWidgetProps } from "../constants";
import { get } from "lodash";
import { getNextEntityName } from "utils/AppsmithUtils";
import {
combineDynamicBindings,
getDynamicBindings,
} from "utils/DynamicBindingUtils";
import { ButtonVariantTypes } from "components/constants";
import { dateFormatOptions } from "widgets/constants";
import moment from "moment";
import { Stylesheet } from "entities/AppTheming";
import { getKeysFromSourceDataForEventAutocomplete } from "widgets/MenuButtonWidget/widget/helper";
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
import log from "loglevel";
type TableData = Array<Record<string, unknown>>;
/*
* When the table data changes we need to find the new index of the
* selectedRow by using the primary key
*/
export const getOriginalRowIndex = (
prevTableData: TableData,
tableData: TableData,
selectedRowIndex: number | undefined,
primaryColumnId: string,
) => {
let primaryKey = "";
let index = -1;
if (
!_.isNil(selectedRowIndex) &&
prevTableData &&
prevTableData[selectedRowIndex]
) {
primaryKey = prevTableData[selectedRowIndex][primaryColumnId] as string;
}
if (!!primaryKey && tableData) {
const selectedRow = tableData.find(
(row) => row[primaryColumnId] === primaryKey,
);
if (selectedRow) {
index = selectedRow[ORIGINAL_INDEX_KEY] as number;
}
}
return index;
};
export const getSelectRowIndex = (
prevTableData: TableData,
tableData: TableData,
defaultSelectedRowIndex: string | number | number[] | undefined,
selectedRowIndex: number | undefined,
primaryColumnId: string | undefined,
) => {
let index = _.isNumber(defaultSelectedRowIndex)
? defaultSelectedRowIndex
: -1;
if (
selectedRowIndex !== -1 &&
!_.isNil(selectedRowIndex) &&
primaryColumnId
) {
index = getOriginalRowIndex(
prevTableData,
tableData,
selectedRowIndex,
primaryColumnId,
);
}
return index;
};
export const getSelectRowIndices = (
prevTableData: TableData,
tableData: TableData,
defaultSelectedRowIndices: string | number | number[] | undefined,
selectedRowIndices: number[] | undefined,
primaryColumnId: string | undefined,
) => {
let indices: number[];
if (primaryColumnId && _.isArray(selectedRowIndices)) {
indices = selectedRowIndices;
} else if (_.isArray(defaultSelectedRowIndices)) {
indices = defaultSelectedRowIndices;
} else {
indices = [];
}
if (primaryColumnId) {
return indices
.map((index: number) =>
getOriginalRowIndex(prevTableData, tableData, index, primaryColumnId),
)
.filter((index) => index !== -1);
} else {
return indices;
}
};
//TODO(Balaji): we shouldn't replace special characters
export const removeSpecialChars = (value: string, limit?: number) => {
const separatorRegex = /\W+/;
return value
.split(separatorRegex)
.join("_")
.slice(0, limit || 30);
};
/*
* Function to get list of columns from the tabledata
*/
export const getAllTableColumnKeys = (
tableData?: Array<Record<string, unknown>>,
) => {
const columnKeys: Set<string> = new Set();
if (_.isArray(tableData)) {
tableData.forEach((row) => {
Object.keys(row).forEach((key) => {
columnKeys.add(key);
});
});
}
return Array.from(columnKeys);
};
export function getTableStyles(props: TableStyles) {
return {
textColor: props.textColor,
textSize: props.textSize,
fontStyle: props.fontStyle,
cellBackground: props.cellBackground,
verticalAlignment: props.verticalAlignment,
horizontalAlignment: props.horizontalAlignment,
};
}
export function escapeString(str: string) {
/*
* Match all the unescaped `"`
* match `"` that follows any character except `\`. ([^\\]\")
*/
return str.replace(/[^\\]"/g, (match) => {
return match.substr(0, match.length - 1) + `\"`;
});
}
export function getDefaultColumnProperties(
id: string,
sanitizedId: string,
index: number,
widgetName: string,
isDerived?: boolean,
columnType?: string,
): ColumnProperties {
const columnProps = {
allowCellWrapping: false,
index: index,
width: DEFAULT_COLUMN_WIDTH,
originalId: id,
id: sanitizedId,
alias: id,
horizontalAlignment: CellAlignmentTypes.LEFT,
verticalAlignment: VerticalAlignmentTypes.CENTER,
columnType: columnType || ColumnTypes.TEXT,
textColor: Colors.THUNDER,
textSize: "0.875rem",
fontStyle: FontStyleTypes.REGULAR,
enableFilter: true,
enableSort: true,
isVisible: true,
isDisabled: false,
isCellEditable: false,
isEditable: false,
isCellVisible: true,
isDerived: !!isDerived,
label: id,
isSaveVisible: true,
isDiscardVisible: true,
computedValue: isDerived
? ""
: `{{${widgetName}.processedTableData.map((currentRow, currentIndex) => ( currentRow["${escapeString(
id,
)}"]))}}`,
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
sticky: StickyType.NONE,
validation: {},
};
return columnProps;
}
/*
* Function to extract derived columns from the primary columns
*/
export function getDerivedColumns(
primaryColumns: Record<string, ColumnProperties>,
): Record<string, ColumnProperties> {
const derivedColumns: Record<string, ColumnProperties> = {};
if (primaryColumns) {
Object.keys(primaryColumns).forEach((columnId) => {
if (primaryColumns[columnId] && primaryColumns[columnId].isDerived) {
derivedColumns[columnId] = primaryColumns[columnId];
}
});
}
return derivedColumns;
}
export const getPropertyValue = (
value: any,
index: number,
preserveCase = false,
isSourceData = false,
) => {
if (value && isObject(value) && !Array.isArray(value)) {
return value;
}
if (value && Array.isArray(value) && value[index]) {
const getValueForSourceData = (value: any, index: number) => {
return Array.isArray(value[index]) ? value[index] : value;
};
return isSourceData
? getValueForSourceData(value, index)
: preserveCase
? value[index].toString()
: value[index].toString().toUpperCase();
} else if (value) {
return preserveCase ? value.toString() : value.toString().toUpperCase();
} else {
return value;
}
};
export const getBooleanPropertyValue = (value: unknown, index: number) => {
if (isBoolean(value)) {
return value;
}
if (Array.isArray(value) && isBoolean(value[index])) {
return value[index];
}
return !!value;
};
export const getArrayPropertyValue = (value: unknown, index: number) => {
if (Array.isArray(value) && value.length > 0) {
if (Array.isArray(value[0])) {
// value is array of arrays of label value
return value[index];
} else {
// value is array of label value
return value;
}
} else {
return value;
}
};
export const getCellProperties = (
columnProperties: ColumnProperties,
rowIndex: number,
) => {
if (columnProperties) {
return {
horizontalAlignment: getPropertyValue(
columnProperties.horizontalAlignment,
rowIndex,
),
verticalAlignment: getPropertyValue(
columnProperties.verticalAlignment,
rowIndex,
),
cellBackground: getPropertyValue(
columnProperties.cellBackground,
rowIndex,
),
buttonColor: getPropertyValue(columnProperties.buttonColor, rowIndex),
buttonLabel: getPropertyValue(
columnProperties.buttonLabel,
rowIndex,
true,
),
menuButtonLabel: getPropertyValue(
columnProperties.menuButtonLabel,
rowIndex,
true,
),
iconName: getPropertyValue(columnProperties.iconName, rowIndex, true),
menuButtoniconName: getPropertyValue(
columnProperties.menuButtoniconName,
rowIndex,
true,
),
menuItemsSource: getPropertyValue(
columnProperties.menuItemsSource,
rowIndex,
true,
),
sourceData: getPropertyValue(
columnProperties.sourceData,
rowIndex,
false,
true,
),
configureMenuItems: columnProperties.configureMenuItems,
buttonVariant: getPropertyValue(
columnProperties.buttonVariant,
rowIndex,
true,
),
borderRadius: getPropertyValue(
columnProperties.borderRadius,
rowIndex,
true,
),
boxShadow: getPropertyValue(columnProperties.boxShadow, rowIndex, true),
iconButtonStyle: getPropertyValue(
columnProperties.iconButtonStyle,
rowIndex,
true,
),
textSize: getPropertyValue(columnProperties.textSize, rowIndex),
textColor: getPropertyValue(columnProperties.textColor, rowIndex),
fontStyle: getPropertyValue(columnProperties.fontStyle, rowIndex), //Fix this
isVisible: getBooleanPropertyValue(columnProperties.isVisible, rowIndex),
isDisabled: getBooleanPropertyValue(
columnProperties.isDisabled,
rowIndex,
),
isCellVisible: getBooleanPropertyValue(
columnProperties.isCellVisible,
rowIndex,
),
displayText: getPropertyValue(
columnProperties.displayText,
rowIndex,
true,
),
iconAlign: getPropertyValue(columnProperties.iconAlign, rowIndex, true),
isCompact: getPropertyValue(columnProperties.isCompact, rowIndex),
menuColor: getPropertyValue(columnProperties.menuColor, rowIndex, true),
menuItems: getPropertyValue(columnProperties.menuItems, rowIndex),
menuVariant: getPropertyValue(
columnProperties.menuVariant,
rowIndex,
true,
),
isCellEditable: getBooleanPropertyValue(
columnProperties.isCellEditable,
rowIndex,
),
allowCellWrapping: getBooleanPropertyValue(
columnProperties.allowCellWrapping,
rowIndex,
),
// EditActions related properties
saveButtonVariant: getPropertyValue(
columnProperties.saveButtonVariant,
rowIndex,
true,
),
saveButtonColor: getPropertyValue(
columnProperties.saveButtonColor,
rowIndex,
true,
),
saveIconAlign: getPropertyValue(
columnProperties.saveIconAlign,
rowIndex,
true,
),
saveBorderRadius: getPropertyValue(
columnProperties.saveBorderRadius,
rowIndex,
true,
),
saveActionLabel: getPropertyValue(
columnProperties.saveActionLabel,
rowIndex,
true,
),
saveActionIconName: getPropertyValue(
columnProperties.saveActionIconName,
rowIndex,
true,
),
isSaveVisible: getBooleanPropertyValue(
columnProperties.isSaveVisible,
rowIndex,
),
isSaveDisabled: getBooleanPropertyValue(
columnProperties.isSaveDisabled,
rowIndex,
),
discardButtonVariant: getPropertyValue(
columnProperties.discardButtonVariant,
rowIndex,
true,
),
discardButtonColor: getPropertyValue(
columnProperties.discardButtonColor,
rowIndex,
true,
),
discardIconAlign: getPropertyValue(
columnProperties.discardIconAlign,
rowIndex,
true,
),
discardBorderRadius: getPropertyValue(
columnProperties.discardBorderRadius,
rowIndex,
true,
),
discardActionLabel: getPropertyValue(
columnProperties.discardActionLabel,
rowIndex,
true,
),
discardActionIconName: getPropertyValue(
columnProperties.discardActionIconName,
rowIndex,
true,
),
isDiscardVisible: getBooleanPropertyValue(
columnProperties.isDiscardVisible,
rowIndex,
),
isDiscardDisabled: getBooleanPropertyValue(
columnProperties.isDiscardDisabled,
rowIndex,
),
imageSize: getPropertyValue(columnProperties.imageSize, rowIndex, true),
isFilterable: getBooleanPropertyValue(
columnProperties.isFilterable,
rowIndex,
),
serverSideFiltering: getBooleanPropertyValue(
columnProperties.serverSideFiltering,
rowIndex,
),
placeholderText: getPropertyValue(
columnProperties.placeholderText,
rowIndex,
true,
),
resetFilterTextOnClose: getPropertyValue(
columnProperties.resetFilterTextOnClose,
rowIndex,
),
inputFormat: getPropertyValue(
columnProperties.inputFormat,
rowIndex,
true,
),
outputFormat: getPropertyValue(
columnProperties.outputFormat,
rowIndex,
true,
),
shortcuts: getBooleanPropertyValue(columnProperties.shortcuts, rowIndex),
selectOptions: getArrayPropertyValue(
columnProperties.selectOptions,
rowIndex,
),
timePrecision: getPropertyValue(
columnProperties.timePrecision,
rowIndex,
true,
),
} as CellLayoutProperties;
}
return {} as CellLayoutProperties;
};
const EdtiableColumnTypes: string[] = [
ColumnTypes.TEXT,
ColumnTypes.NUMBER,
ColumnTypes.SELECT,
ColumnTypes.CHECKBOX,
ColumnTypes.SWITCH,
ColumnTypes.DATE,
];
export function isColumnTypeEditable(columnType: string) {
return EdtiableColumnTypes.includes(columnType);
}
/*
* Nested propeties are not validated when application is refreshed
* TODO(Balai): Should confirm and create an issue to address this.
*/
export function getSelectColumnTypeOptions(value: unknown) {
const result = SelectColumnOptionsValidations(value, {}, _);
return result.parsed;
}
/**
* returns selected row bg color
*
* if the color is dark, use 80% lighter color for selected row
* if color is light, use 10% darker color for selected row
*
* @param accentColor
*/
export const getSelectedRowBgColor = (accentColor: string) => {
const tinyAccentColor = tinycolor(accentColor);
const brightness = tinycolor(accentColor)
.greyscale()
.getBrightness();
const percentageBrightness = (brightness / 255) * 100;
let nextBrightness = 0;
switch (true) {
case percentageBrightness > 70:
nextBrightness = 10;
break;
case percentageBrightness > 50:
nextBrightness = 35;
break;
case percentageBrightness > 50:
nextBrightness = 55;
break;
default:
nextBrightness = 60;
}
if (brightness > 180) {
return tinyAccentColor.darken(10).toString();
} else {
return tinyAccentColor.lighten(nextBrightness).toString();
}
};
/**
* this is a getter function to get stylesheet value of the property from the config
*
* @param props
* @param propertyPath
* @param widgetStylesheet
* @returns
*/
export const getStylesheetValue = (
props: TableWidgetProps,
propertyPath: string,
widgetStylesheet?: Stylesheet,
) => {
const propertyName = propertyPath.split(".").slice(-1)[0];
const columnName = propertyPath.split(".").slice(-2)[0];
const columnType = get(props, `primaryColumns.${columnName}.columnType`);
return get(widgetStylesheet, `childStylesheet.${columnType}.${propertyName}`);
};
export const reorderColumns = (
columns: Record<string, ColumnProperties>,
columnOrder: string[],
) => {
const newColumnsInOrder: Record<string, ColumnProperties> = {};
uniq(columnOrder).forEach((id: string, index: number) => {
if (columns[id]) newColumnsInOrder[id] = { ...columns[id], index };
});
const remaining = without(
Object.keys(columns),
...Object.keys(newColumnsInOrder),
);
const len = Object.keys(newColumnsInOrder).length;
if (remaining && remaining.length > 0) {
remaining.forEach((id: string, index: number) => {
newColumnsInOrder[id] = { ...columns[id], index: len + index };
});
}
return newColumnsInOrder;
};
export const getEditActionColumnProperties = () => ({
isSaveVisible: true,
isDiscardVisible: true,
saveIconAlign: "left",
discardIconAlign: "left",
saveActionLabel: "Save",
discardActionLabel: "Discard",
saveButtonColor: Colors.GREEN,
discardButtonColor: Colors.GREEN,
});
export const getEditActionColumnDynamicProperties = (widgetName: string) => ({
isSaveDisabled: `{{${widgetName}.processedTableData.map((currentRow, currentIndex) => ( !${widgetName}.updatedRowIndices.includes(currentIndex)))}}`,
isDiscardDisabled: `{{${widgetName}.processedTableData.map((currentRow, currentIndex) => ( !${widgetName}.updatedRowIndices.includes(currentIndex)))}}`,
});
export const createColumn = (props: TableWidgetProps, baseName: string) => {
const columns = props.primaryColumns || {};
const columnsArray = Object.values(columns);
const columnIds = columnsArray.map((column) => column.originalId);
const newColumnName = getNextEntityName(baseName, columnIds);
const lastItemIndex = columnsArray
.map((column) => column.index)
.sort()
.pop();
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
const nextIndex = lastItemIndex ? lastItemIndex + 1 : columnIds.length;
return {
...getDefaultColumnProperties(
newColumnName,
newColumnName,
nextIndex,
props.widgetName,
true,
),
buttonStyle: DEFAULT_BUTTON_COLOR,
isDisabled: false,
...getTableStyles(props),
};
};
export const createEditActionColumn = (props: TableWidgetProps) => {
const themeProps: Record<string, string> = {};
if (props.childStylesheet[ColumnTypes.EDIT_ACTIONS]) {
Object.entries(props.childStylesheet[ColumnTypes.EDIT_ACTIONS]).forEach(
([key, value]) => {
const { jsSnippets, stringSegments } = getDynamicBindings(
value as string,
);
const js = combineDynamicBindings(jsSnippets, stringSegments);
themeProps[
key
] = `{{${props.widgetName}.processedTableData.map((currentRow, currentIndex) => ( ${js}))}}`;
},
);
}
const column = {
...createColumn(props, "EditActions"),
...getEditActionColumnProperties(),
...themeProps,
columnType: ColumnTypes.EDIT_ACTIONS,
label: "Save / Discard",
discardButtonVariant: ButtonVariantTypes.TERTIARY,
discardButtonColor: Colors.DANGER_SOLID,
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
sticky: StickyType.RIGHT,
};
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
const columnOrder = [...(props.columnOrder || [])];
const editActionDynamicProperties = getEditActionColumnDynamicProperties(
props.widgetName,
);
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
const rightColumnIndex = columnOrder
.map((column) => props.primaryColumns[column])
.filter((col) => col.sticky !== StickyType.RIGHT).length;
columnOrder.splice(rightColumnIndex, 0, column.id);
return [
{
propertyPath: `primaryColumns.${column.id}`,
propertyValue: {
...column,
...editActionDynamicProperties,
},
},
{
propertyPath: `columnOrder`,
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
propertyValue: columnOrder,
},
...Object.entries(editActionDynamicProperties).map(([key, value]) => ({
propertyPath: `primaryColumns.${column.id}.${key}`,
propertyValue: value,
isDynamicPropertyPath: true,
})),
];
};
export const getColumnType = (
tableData: Array<Record<string, unknown>>,
columnKey: string,
): string => {
if (!_.isArray(tableData) || tableData.length === 0 || !columnKey) {
return ColumnTypes.TEXT;
}
let columnValue: unknown = null,
row = 0;
const maxRowsToCheck = 5;
/*
In below while loop we are trying to get a non-null value from
subsequent rows in case first few rows are null
Limited to checking upto maxRowsToCheck
*/
while (_.isNil(columnValue) && row < maxRowsToCheck) {
if (!_.isNil(tableData?.[row]?.[columnKey])) {
columnValue = tableData[row][columnKey];
break;
}
row++;
}
if (_.isNil(columnValue)) {
return ColumnTypes.TEXT;
}
switch (typeof columnValue) {
case "number":
return ColumnTypes.NUMBER;
case "boolean":
return ColumnTypes.CHECKBOX;
case "string":
return dateFormatOptions.some(({ value: format }) =>
moment(columnValue as string, format, true).isValid(),
)
? ColumnTypes.DATE
: ColumnTypes.TEXT;
default:
return ColumnTypes.TEXT;
}
};
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
export const generateLocalNewColumnOrderFromStickyValue = (
columnOrder: string[],
columnName: string,
sticky?: string,
leftOrder?: string[],
rightOrder?: string[],
) => {
let newColumnOrder = [...columnOrder];
newColumnOrder = without(newColumnOrder, columnName);
let columnIndex = -1;
if (sticky === StickyType.LEFT && leftOrder) {
columnIndex = leftOrder.length;
} else if (sticky === StickyType.RIGHT && rightOrder) {
columnIndex =
rightOrder.length !== 0
? columnOrder.indexOf(rightOrder[0]) - 1
: columnOrder.length - 1;
} else {
if (leftOrder?.includes(columnName)) {
columnIndex = leftOrder.length - 1;
} else if (rightOrder?.includes(columnName)) {
columnIndex =
rightOrder.length !== 0
? columnOrder.indexOf(rightOrder[0])
: columnOrder.length - 1;
}
}
newColumnOrder.splice(columnIndex, 0, columnName);
return newColumnOrder;
};
/**
* Function to get new column order when there is a change in column's sticky value.
*/
export const generateNewColumnOrderFromStickyValue = (
primaryColumns: Record<string, ColumnProperties>,
columnOrder: string[],
columnName: string,
sticky?: string,
) => {
let newColumnOrder = [...columnOrder];
newColumnOrder = without(newColumnOrder, columnName);
let columnIndex;
if (sticky === StickyType.LEFT) {
columnIndex = columnOrder
.map((column) => primaryColumns[column])
.filter((column) => column.sticky === StickyType.LEFT).length;
} else if (sticky === StickyType.RIGHT) {
columnIndex =
columnOrder
.map((column) => primaryColumns[column])
.filter((column) => column.sticky !== StickyType.RIGHT).length - 1;
} else {
/**
* This block will manage the column order when column is unfrozen.
* Unfreezing can happen in CANVAS or PAGE mode.
* Logic:
* --> If the column is unfrozen when its on the left, then it should be unfrozen after the last left frozen column.
* --> If the column is unfrozen when its on the right, then it should be unfrozen before the first right frozen column.
*/
columnIndex = -1;
const staleStickyValue = primaryColumns[columnName].sticky;
if (staleStickyValue === StickyType.LEFT) {
columnIndex = columnOrder
.map((column) => primaryColumns[column])
.filter(
(column) =>
column.sticky === StickyType.LEFT && column.id !== columnName,
).length;
} else if (staleStickyValue === StickyType.RIGHT) {
columnIndex = columnOrder
.map((column) => primaryColumns[column])
.filter((column) => column.sticky !== StickyType.RIGHT).length;
}
}
newColumnOrder.splice(columnIndex, 0, columnName);
return newColumnOrder;
};
export const getSourceDataAndCaluclateKeysForEventAutoComplete = (
props: TableWidgetProps,
): unknown => {
const { __evaluation__, primaryColumns } = props;
const primaryColumnKeys = primaryColumns ? Object.keys(primaryColumns) : [];
const columnName = primaryColumnKeys?.length ? primaryColumnKeys[0] : "";
const evaluatedColumns: any = __evaluation__?.evaluatedValues?.primaryColumns;
if (evaluatedColumns) {
const result = getKeysFromSourceDataForEventAutocomplete(
evaluatedColumns[columnName]?.sourceData || [],
);
return result;
} else {
return {};
}
};
feat: added column freeze and unfreeze functionality to table widget (#18757) **PRD**: https://www.notion.so/appsmith/Ability-to-freeze-columns-dd118f7ed2e14e008ee305056b79874a?d=300f4968889244da9f737e1bfd8c06dc#2ddaf28e10a0475cb69f1af77b938d0b This PR adds the following features to the table widget: - Freeze the columns to the left or right of the table.(Both canvas and page view mode). - Unfreeze the frozen columns. (Both canvas and page view mode). - Columns that are left frozen, will get unfrozen at a position after the last left frozen column. (Both canvas and page view mode). - Columns that are right frozen, will get unfrozen at a position before the first right frozen column. (Both canvas and page view mode). - Column order can be persisted in the Page view mode. - Users can also unfreeze the columns that are frozen by the developers. - Columns that are frozen cannot be reordered(Both canvas and page view mode) - **Property pane changes (Columns property)**: - If the column is frozen to the left then that column should appear at top of the list. - If the column is frozen to the right then that column should appear at the bottom of the list. - The columns that are frozen cannot be moved or re-ordered in the list. They remain fixed in their position. - In-Page mode, If there is a change in frozen or unfrozen columns in multiple tables then the order of columns and frozen and unfrozen columns should get persisted on refresh i.e. changes should get persisted across refreshes.
2023-02-15 11:42:46 +00:00
export const deleteLocalTableColumnOrderByWidgetId = (widgetId: string) => {
try {
const localData = localStorage.getItem(TABLE_COLUMN_ORDER_KEY);
if (localData) {
const localColumnOrder = JSON.parse(localData);
delete localColumnOrder[widgetId];
localStorage.setItem(
TABLE_COLUMN_ORDER_KEY,
JSON.stringify(localColumnOrder),
);
}
} catch (e) {
log.debug("Error in reading local data", e);
}
};
export const fetchSticky = (
columnId: string,
primaryColumns: Record<string, ColumnProperties>,
renderMode: RenderMode,
widgetId?: string,
): StickyType | undefined => {
if (renderMode === RenderModes.PAGE && widgetId) {
const localTableColumnOrder = getColumnOrderByWidgetIdFromLS(widgetId);
if (localTableColumnOrder) {
const { leftOrder, rightOrder } = localTableColumnOrder;
if (leftOrder.indexOf(columnId) > -1) {
return StickyType.LEFT;
} else if (rightOrder.indexOf(columnId) > -1) {
return StickyType.RIGHT;
} else {
return StickyType.NONE;
}
} else {
return get(primaryColumns, `${columnId}`).sticky;
}
}
if (renderMode === RenderModes.CANVAS) {
return get(primaryColumns, `${columnId}`).sticky;
}
};
export const updateAndSyncTableLocalColumnOrders = (
columnName: string,
leftOrder: string[],
rightOrder: string[],
sticky?: StickyType,
) => {
if (sticky === StickyType.LEFT) {
leftOrder.push(columnName);
if (rightOrder) {
rightOrder = without(rightOrder, columnName);
}
} else if (sticky === StickyType.RIGHT) {
rightOrder.unshift(columnName);
// When column is frozen to right from left. Remove the column name from leftOrder
if (leftOrder) {
leftOrder = without(leftOrder, columnName);
}
} else {
// remove column from both orders:
leftOrder = without(leftOrder, columnName);
rightOrder = without(rightOrder, columnName);
}
return { leftOrder, rightOrder };
};
export const getColumnOrderByWidgetIdFromLS = (widgetId: string) => {
const localTableWidgetColumnOrder = localStorage.getItem(
TABLE_COLUMN_ORDER_KEY,
);
if (localTableWidgetColumnOrder) {
try {
const parsedTableWidgetColumnOrder = JSON.parse(
localTableWidgetColumnOrder,
);
if (parsedTableWidgetColumnOrder[widgetId]) {
const {
columnOrder,
columnUpdatedAt,
leftOrder,
rightOrder,
} = parsedTableWidgetColumnOrder[widgetId];
return {
columnOrder,
columnUpdatedAt,
leftOrder,
rightOrder,
};
}
} catch (e) {
log.debug("Unable to parse local column order:", { e });
}
}
};
export const getAllStickyColumnsCount = (columns: TableColumnProps[]) => {
return (
filter(columns, { sticky: StickyType.LEFT }).length +
filter(columns, { sticky: StickyType.RIGHT }).length
);
};