feat: Date column type editing for table widget (#19181)

- Integrates Date picker component inside table's date column
- Enables edit mode for date type column in table widget
- Adds all the required Property controls for date picker
- Builds the user flow for date column editing in table widget
This commit is contained in:
Souma Ghosh 2023-01-16 14:53:56 +05:30 committed by GitHub
parent 0eb0a36a8c
commit 12ea1b86ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1880 additions and 29 deletions

View File

@ -0,0 +1,813 @@
{
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 4896,
"snapColumns": 64,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0,
"bottomRow": 1030,
"containerStyle": "none",
"snapRows": 125,
"parentRowSpace": 1,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 71,
"minHeight": 1292,
"dynamicTriggerPathList": [],
"parentColumnSpace": 1,
"dynamicBindingPathList": [],
"leftColumn": 0,
"children": [
{
"boxShadow": "{{appsmith.theme.boxShadow.appBoxShadow}}",
"borderColor": "#E0DEDE",
"isVisibleDownload": true,
"iconSVG": "/static/media/icon.db8a9cbd2acd22a31ea91cc37ea2a46c.svg",
"topRow": 0,
"isSortable": true,
"type": "TABLE_WIDGET_V2",
"inlineEditingSaveOption": "ROW_LEVEL",
"animateLoading": true,
"dynamicBindingPathList": [
{
"key": "primaryColumns.status.computedValue"
},
{
"key": "accentColor"
},
{
"key": "boxShadow"
},
{
"key": "tableData"
},
{
"key": "primaryColumns.revenue.computedValue"
},
{
"key": "primaryColumns.imdb_id.computedValue"
},
{
"key": "primaryColumns.release_date.computedValue"
},
{
"key": "primaryColumns.genres.computedValue"
},
{
"key": "primaryColumns.vote_average.computedValue"
},
{
"key": "primaryColumns.tagline.computedValue"
},
{
"key": "primaryColumns._id.computedValue"
},
{
"key": "primaryColumns.title.computedValue"
},
{
"key": "primaryColumns.vote_count.computedValue"
},
{
"key": "primaryColumns.poster_path.computedValue"
},
{
"key": "primaryColumns.homepage.computedValue"
},
{
"key": "borderRadius"
},
{
"key": "primaryColumns.customColumn1.buttonColor"
},
{
"key": "primaryColumns.customColumn1.borderRadius"
},
{
"key": "primaryColumns.customColumn1.boxShadow"
},
{
"key": "primaryColumns.EditActions1.saveButtonColor"
},
{
"key": "primaryColumns.EditActions1.saveBorderRadius"
},
{
"key": "primaryColumns.EditActions1.discardBorderRadius"
},
{
"key": "primaryColumns.EditActions1.isSaveDisabled"
},
{
"key": "primaryColumns.EditActions1.isDiscardDisabled"
}
],
"leftColumn": 0,
"delimiter": ",",
"defaultSelectedRowIndex": 0,
"showInlineEditingOptionDropdown": true,
"accentColor": "{{appsmith.theme.colors.primaryColor}}",
"isVisibleFilters": true,
"isVisible": true,
"fontStyle": "",
"enableClientSideSearch": true,
"version": 1,
"textColor": "#18181b",
"totalRecordsCount": 0,
"isLoading": false,
"childStylesheet": {
"button": {
"buttonColor": "{{appsmith.theme.colors.primaryColor}}",
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"boxShadow": "none"
},
"menuButton": {
"menuColor": "{{appsmith.theme.colors.primaryColor}}",
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"boxShadow": "none"
},
"iconButton": {
"buttonColor": "{{appsmith.theme.colors.primaryColor}}",
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"boxShadow": "none"
},
"editActions": {
"saveButtonColor": "{{appsmith.theme.colors.primaryColor}}",
"saveBorderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"discardButtonColor": "{{appsmith.theme.colors.primaryColor}}",
"discardBorderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}"
}
},
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"defaultSelectedRowIndices": [
0
],
"widgetName": "Table1",
"defaultPageSize": 0,
"columnOrder": [
"status",
"revenue",
"imdb_id",
"release_date",
"genres",
"vote_average",
"tagline",
"_id",
"title",
"vote_count",
"poster_path",
"homepage",
"customColumn1",
"EditActions1"
],
"dynamicPropertyPathList": [
{
"key": "primaryColumns.EditActions1.isSaveDisabled"
},
{
"key": "primaryColumns.EditActions1.isDiscardDisabled"
}
],
"compactMode": "DEFAULT",
"displayName": "Table",
"bottomRow": 65,
"columnWidthMap": {
"task": 245,
"step": 62,
"status": 105,
"release_date": 226,
"genres": 193
},
"parentRowSpace": 10,
"hideCard": false,
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [
{
"key": "primaryColumns.release_date.onSubmit"
},
{
"key": "primaryColumns.release_date.onDateSelected"
}
],
"borderWidth": "1",
"primaryColumns": {
"status": {
"index": 2,
"width": 150,
"id": "status",
"originalId": "status",
"alias": "status",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "0.875rem",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isCellVisible": true,
"isCellEditable": false,
"isDerived": false,
"label": "status",
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"status\"]))}}",
"validation": {},
"labelColor": "#FFFFFF",
"fontStyle": "",
"cellBackground": "transparent",
"textColor": "#18181b"
},
"revenue": {
"allowCellWrapping": false,
"index": 0,
"width": 150,
"originalId": "revenue",
"id": "revenue",
"alias": "revenue",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "number",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "revenue",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"revenue\"]))}}",
"validation": {
"isColumnEditableCellRequired": true
},
"cellBackground": "transparent"
},
"imdb_id": {
"allowCellWrapping": false,
"index": 1,
"width": 150,
"originalId": "imdb_id",
"id": "imdb_id",
"alias": "imdb_id",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "imdb_id",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"imdb_id\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"release_date": {
"allowCellWrapping": false,
"index": 2,
"width": 150,
"originalId": "release_date",
"id": "release_date",
"alias": "release_date",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "date",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "release_date",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"release_date\"]))}}",
"validation": {
"minDate": "1905-12-05T00:00:00.000+05:21",
"maxDate": "2058-12-31T00:00:00.000+05:30",
"isColumnEditableCellRequired": false
},
"cellBackground": "transparent",
"onSubmit": "",
"onDateSelected": "{{showAlert('onDateSelected')}}",
"firstDayOfWeek": "0",
"timePrecision": "second",
"shortcuts": true,
"outputFormat": "YYYY-MM-DDTHH:mm:ss",
"inputFormat": "YYYY-MM-DD"
},
"genres": {
"allowCellWrapping": false,
"index": 3,
"width": 150,
"originalId": "genres",
"id": "genres",
"alias": "genres",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "genres",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"genres\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"vote_average": {
"allowCellWrapping": false,
"index": 4,
"width": 150,
"originalId": "vote_average",
"id": "vote_average",
"alias": "vote_average",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "number",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "vote_average",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"vote_average\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"tagline": {
"allowCellWrapping": false,
"index": 5,
"width": 150,
"originalId": "tagline",
"id": "tagline",
"alias": "tagline",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "tagline",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"tagline\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"_id": {
"allowCellWrapping": false,
"index": 6,
"width": 150,
"originalId": "_id",
"id": "_id",
"alias": "_id",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "_id",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"_id\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"title": {
"allowCellWrapping": false,
"index": 7,
"width": 150,
"originalId": "title",
"id": "title",
"alias": "title",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "title",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"title\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"vote_count": {
"allowCellWrapping": false,
"index": 8,
"width": 150,
"originalId": "vote_count",
"id": "vote_count",
"alias": "vote_count",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "number",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "vote_count",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"vote_count\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"poster_path": {
"allowCellWrapping": false,
"index": 9,
"width": 150,
"originalId": "poster_path",
"id": "poster_path",
"alias": "poster_path",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "poster_path",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"poster_path\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"homepage": {
"allowCellWrapping": false,
"index": 10,
"width": 150,
"originalId": "homepage",
"id": "homepage",
"alias": "homepage",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": false,
"label": "homepage",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( currentRow[\"homepage\"]))}}",
"validation": {},
"cellBackground": "transparent"
},
"customColumn1": {
"allowCellWrapping": false,
"index": 10,
"width": 150,
"originalId": "customColumn1",
"id": "customColumn1",
"alias": "customColumn1",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "iconButton",
"textColor": "#18181b",
"textSize": "0.875rem",
"fontStyle": "",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": true,
"label": "customColumn1",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "",
"validation": {},
"buttonStyle": "rgb(3, 179, 101)",
"cellBackground": "transparent",
"labelColor": "#FFFFFF",
"buttonColor": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( appsmith.theme.colors.primaryColor))}}",
"borderRadius": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( appsmith.theme.borderRadius.appBorderRadius))}}",
"boxShadow": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( 'none'))}}",
"customAlias": ""
},
"EditActions1": {
"allowCellWrapping": false,
"index": 10,
"width": 150,
"originalId": "EditActions1",
"id": "EditActions1",
"alias": "EditActions1",
"columnType": "editActions",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellEditable": false,
"isEditable": false,
"isCellVisible": true,
"isDerived": true,
"label": "Save / Discard",
"isSaveVisible": true,
"isDiscardVisible": true,
"computedValue": "",
"validation": {},
"buttonStyle": "rgb(3, 179, 101)",
"saveIconAlign": "left",
"discardIconAlign": "left",
"saveActionLabel": "Save",
"discardActionLabel": "Discard",
"saveButtonColor": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( appsmith.theme.colors.primaryColor))}}",
"discardButtonColor": "#F22B2B",
"saveBorderRadius": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( appsmith.theme.borderRadius.appBorderRadius))}}",
"discardBorderRadius": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( appsmith.theme.borderRadius.appBorderRadius))}}",
"discardButtonVariant": "TERTIARY",
"isSaveDisabled": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( !Table1.updatedRowIndices.includes(currentIndex)))}}",
"isDiscardDisabled": "{{Table1.processedTableData.map((currentRow, currentIndex) => ( !Table1.updatedRowIndices.includes(currentIndex)))}}"
}
},
"key": "ds95nyw2jg",
"isDeprecated": false,
"rightColumn": 64,
"textSize": "0.875rem",
"widgetId": "h0hd2shht7",
"tableData": [
{
"revenue": 42600000,
"imdb_id": "tt3228774",
"release_date": "2021-05-26"
},
{
"revenue": 435954000,
"imdb_id": "tt5034838",
"release_date": "2021-03-24"
},
{
"revenue": 13126737,
"imdb_id": "tt32286774",
"release_date": "2021-05-05"
}
],
"label": "Data",
"searchKey": "",
"parentId": "0",
"renderMode": "CANVAS",
"horizontalAlignment": "LEFT",
"isVisibleSearch": true,
"isVisiblePagination": true,
"cellBackground": "transparent",
"verticalAlignment": "CENTER"
},
{
"widgetName": "Text1",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b523e6f70ba6f40a10fc2c7c5b5.svg",
"searchTags": [
"typography",
"paragraph",
"label"
],
"topRow": 67,
"bottomRow": 95,
"parentRowSpace": 10,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 3,
"dynamicBindingPathList": [
{
"key": "truncateButtonColor"
},
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "{{appsmith.theme.colors.primaryColor}}",
"text": "{{JSON.stringify(Table1.updatedRow)}}",
"key": "tgzs4gzszh",
"isDeprecated": false,
"rightColumn": 19,
"textAlign": "LEFT",
"dynamicHeight": "AUTO_HEIGHT",
"widgetId": "7z3nhdsqcz",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"originalTopRow": 67,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"maxDynamicHeight": 9000,
"originalBottomRow": 95,
"fontSize": "1rem",
"minDynamicHeight": 4
},
{
"widgetName": "Text2",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b523e6f70ba6f40a10fc2c7c5b5.svg",
"searchTags": [
"typography",
"paragraph",
"label"
],
"topRow": 67,
"bottomRow": 71,
"parentRowSpace": 10,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 20,
"dynamicBindingPathList": [
{
"key": "truncateButtonColor"
},
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "{{appsmith.theme.colors.primaryColor}}",
"text": "{{JSON.stringify(Table1.updatedRows)}}",
"key": "wxnjnt7ml3",
"isDeprecated": false,
"rightColumn": 36,
"textAlign": "LEFT",
"dynamicHeight": "AUTO_HEIGHT",
"widgetId": "buu1i75k2o",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"originalTopRow": 67,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"maxDynamicHeight": 9000,
"originalBottomRow": 71,
"fontSize": "1rem",
"minDynamicHeight": 4
},
{
"widgetName": "Text3",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b523e6f70ba6f40a10fc2c7c5b5.svg",
"searchTags": [
"typography",
"paragraph",
"label"
],
"topRow": 67,
"bottomRow": 71,
"parentRowSpace": 10,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 37,
"dynamicBindingPathList": [
{
"key": "truncateButtonColor"
},
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "{{appsmith.theme.colors.primaryColor}}",
"text": "{{JSON.stringify(Table1.updatedRowIndices)}}",
"key": "wxnjnt7ml3",
"isDeprecated": false,
"rightColumn": 53,
"textAlign": "LEFT",
"dynamicHeight": "AUTO_HEIGHT",
"widgetId": "pw6uyso07g",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"maxDynamicHeight": 9000,
"fontSize": "1rem",
"minDynamicHeight": 4
}
]
}
}

View File

@ -0,0 +1,366 @@
const dsl = require("../../../../../fixtures/Table/DateCellEditingDSL.json");
const commonlocators = require("../../../../../locators/commonlocators.json");
const widgetsPage = require("../../../../../locators/Widgets.json");
import { ObjectsRegistry } from "../../../../../support/Objects/Registry";
import { PROPERTY_SELECTOR } from "../../../../../locators/WidgetLocators";
const agHelper = ObjectsRegistry.AggregateHelper;
describe("Table widget date column inline editing functionality", () => {
before(() => {
cy.addDsl(dsl);
});
it("1. should check that edit check box is enabled for date type column in the columns list", () => {
cy.openPropertyPane("tablewidgetv2");
cy.get(
`[data-rbd-draggable-id="release_date"] .t--card-checkbox input`,
).should("not.be.disabled");
});
it("2. should check that date cell edit mode can be turned on", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-general .t--property-control-editable",
).should("exist");
cy.get(
".t--property-pane-section-general .t--property-control-editable input[type=checkbox]+span",
).click();
cy.get(
`${commonlocators.TableV2Head} [data-header="release_date"] svg`,
).should("exist");
});
it("3. should check that user can edit date in table cell", () => {
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick();
cy.get(".bp3-dateinput-popover").should("exist");
cy.get(".t--inlined-cell-editor").should("exist");
cy.get(".bp3-dateinput-popover [aria-label='Mon May 17 2021']").click();
cy.get(".bp3-dateinput-popover").should("not.exist");
cy.get(".t--inlined-cell-editor").should("not.exist");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).should("contain", "2021-05-17T00:00:00");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(".bp3-dateinput-popover").should("exist");
cy.get(".t--inlined-cell-editor").should("exist");
cy.get(`${commonlocators.textWidget}`)
.first()
.click();
cy.get(".bp3-dateinput-popover").should("not.exist");
cy.get(".t--inlined-cell-editor").should("not.exist");
cy.get(
`[type='CANVAS_WIDGET'] .t--widget-textwidget ${commonlocators.textWidget} span`,
).should(
"contain",
`{"revenue":42600000,"imdb_id":"tt3228774","release_date":"2021-05-17"}`,
);
cy.get(
`[type='CANVAS_WIDGET'] .t--widget-textwidget+.t--widget-textwidget ${commonlocators.textWidget} span`,
).should(
"contain",
`[{"index":0,"updatedFields":{"release_date":"2021-05-17"},"allFields":{"revenue":42600000,"imdb_id":"tt3228774","release_date":"2021-05-17"}}]`,
);
cy.get(
`[type='CANVAS_WIDGET'] .t--widget-textwidget+.t--widget-textwidget+.t--widget-textwidget ${commonlocators.textWidget} span`,
).should("contain", "[0]");
});
it("4. should check that changing property pane display format for date column changes date display format", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-displayformat .bp3-popover-target")
.last()
.click();
cy.get(".t--dropdown-option")
.children()
.contains("Do MMM YYYY")
.click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).should("contain", "17th May 2021");
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-displayformat .bp3-popover-target")
.last()
.click();
cy.get(".t--dropdown-option")
.children()
.contains("DD/MM/YYYY")
.click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).should("contain", "17/05/2021");
});
it("5. should check that changing property pane first day of week changes the date picker starting day", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-firstdayofweek .t--code-editor-wrapper")
.last()
.click()
.type("{backspace}1");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(
".bp3-datepicker .DayPicker .DayPicker-Months .DayPicker-WeekdaysRow div:first-child abbr",
).should("contain", "Mo");
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-firstdayofweek .t--code-editor-wrapper")
.last()
.click()
.type("{backspace}5");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(
".bp3-datepicker .DayPicker .DayPicker-Months .DayPicker-WeekdaysRow div:first-child abbr",
).should("contain", "Fr");
});
it.skip("6. should check that changing property pane time precision changes the date picker time precision", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-timeprecision .bp3-popover-target")
.last()
.click();
cy.get(".t--dropdown-option")
.children()
.contains("Minute")
.click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(".bp3-timepicker-input-row .bp3-timepicker-hour").should("exist");
cy.get(".bp3-timepicker-input-row .bp3-timepicker-minute").should("exist");
cy.get(".bp3-timepicker-input-row .bp3-timepicker-second").should(
"not.exist",
);
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-timeprecision .bp3-popover-target")
.last()
.click();
cy.get(".t--dropdown-option")
.children()
.contains("None")
.click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(".bp3-timepicker-input-row").should("not.exist");
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(".t--property-control-timeprecision .bp3-popover-target")
.last()
.click();
cy.get(".t--dropdown-option")
.children()
.contains("Second")
.click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(".bp3-timepicker-input-row .bp3-timepicker-hour").should("exist");
cy.get(".bp3-timepicker-input-row .bp3-timepicker-minute").should("exist");
cy.get(".bp3-timepicker-input-row .bp3-timepicker-second").should("exist");
});
it("7. should check visible property control functionality", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-general .t--property-control-visible",
).should("exist");
cy.get(
".t--property-pane-section-general .t--property-control-visible input[type=checkbox]+span",
).click();
cy.get(
`${commonlocators.TableV2Head} [data-header="release_date"] .hidden-header`,
).should("exist");
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-general .t--property-control-visible input[type=checkbox]+span",
).click();
cy.get(
`${commonlocators.TableV2Head} [data-header="release_date"] .draggable-header`,
).should("exist");
});
it("8. should check Show Shortcuts property control functionality", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-datesettings .t--property-control-showshortcuts",
).should("exist");
cy.get(
".t--property-pane-section-datesettings .t--property-control-showshortcuts input[type=checkbox]+span",
).click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(`.bp3-dateinput-popover .bp3-daterangepicker-shortcuts`).should(
"not.exist",
);
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-datesettings .t--property-control-showshortcuts",
).should("exist");
cy.get(
".t--property-pane-section-datesettings .t--property-control-showshortcuts input[type=checkbox]+span",
).click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3)`,
).dblclick({
force: true,
});
cy.get(`.bp3-dateinput-popover .bp3-daterangepicker-shortcuts`).should(
"exist",
);
});
it("9. should check min date and max date property control functionality", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-validation .t--property-control-mindate",
).should("exist");
cy.get(
".t--property-pane-section-validation .t--property-control-maxdate",
).should("exist");
cy.get(
".t--property-pane-section-validation .t--property-control-mindate div:last-child .bp3-popover-wrapper",
)
.click()
.clear()
.type("2022-05-05T00:00:10.1010+05:30{enter}");
cy.get(
".t--property-pane-section-validation .t--property-control-maxdate div:last-child .bp3-popover-wrapper",
)
.click()
.clear()
.type("2022-05-30T00:00:10.1010+05:30{enter}");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) .td:nth-child(3)`,
).realHover();
cy.get(`.t--editable-cell-icon`)
.first()
.click({
force: true,
});
cy.get(
".bp3-transition-container .bp3-popover .bp3-popover-content",
).should("contain", "Date out of range");
cy.get(
".t--property-pane-section-validation .t--property-control-mindate div:last-child .bp3-popover-wrapper",
)
.click()
.clear()
.type("{enter}");
cy.get(
".t--property-pane-section-validation .t--property-control-maxdate div:last-child .bp3-popover-wrapper",
)
.click()
.clear()
.type("{enter}");
});
it("10. should check property pane Required toggle functionality", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("release_date");
cy.get(
".t--property-pane-section-validation .t--property-control-required",
).should("exist");
cy.get(
".t--property-pane-section-validation .t--property-control-required input[type=checkbox]+span",
).click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) .td:nth-child(3)`,
).realHover();
cy.get(`.t--editable-cell-icon`)
.first()
.click({
force: true,
});
cy.get(".bp3-dateinput-popover [aria-label='Wed May 26 2021']").click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) .td:nth-child(3)`,
).realHover();
cy.get(`.t--editable-cell-icon`)
.first()
.click({
force: true,
});
cy.get(".bp3-dateinput-popover [aria-label='Wed May 26 2021']").click();
cy.get(
".bp3-transition-container .bp3-popover .bp3-popover-content",
).should("exist");
cy.get(
".bp3-transition-container .bp3-popover .bp3-popover-content",
).should("contain", "This field is required");
cy.get(".bp3-dateinput-popover [aria-label='Wed May 26 2021']").click();
cy.get(
".bp3-transition-container .bp3-popover .bp3-popover-content",
).should("not.exist");
});
it("11. should check date cells behave as expected when adding a new row to table", () => {
cy.openPropertyPane("tablewidgetv2");
cy.get(".t--property-pane-back-btn").click();
cy.get(
".t--property-pane-section-addingarow .t--property-control-allowaddingarow input[type=checkbox]+span",
).click();
cy.get(".t--add-new-row").click();
cy.get(".bp3-datepicker").should("not.exist");
cy.get(".t--inlined-cell-editor")
.should("have.css", "border")
.and("eq", "1px solid rgb(255, 255, 255)");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3) input`,
).should("have.value", "");
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3) input`,
).click();
cy.get(".bp3-datepicker").should("exist");
cy.get(".t--inlined-cell-editor")
.should("have.css", "border")
.and("not.eq", "none")
.and("not.eq", "1px solid rgb(255, 255, 255)");
cy.get(
".bp3-datepicker .DayPicker .DayPicker-Body .DayPicker-Week:nth-child(2) .DayPicker-Day:first-child",
).click();
cy.get(
`${commonlocators.TableV2Row} .tr:nth-child(1) div:nth-child(3) input`,
).should("not.have.value", "");
});
});

View File

@ -141,7 +141,7 @@ describe("Table widget inline editing functionality", () => {
},
{
columnType: "Date",
expected: "be.disabled",
expected: "not.be.disabled",
},
{
columnType: "Image",
@ -198,7 +198,7 @@ describe("Table widget inline editing functionality", () => {
},
{
columnType: "Date",
expected: "not.exist",
expected: "exist",
},
{
columnType: "Image",
@ -765,7 +765,7 @@ describe("Table widget inline editing functionality", () => {
cy.get(commonlocators.textWidgetContainer).should("contain.text", -1);
});
it.only("27. should check if updatedRowIndex is getting updated for multi row update mode", () => {
it("27. should check if updatedRowIndex is getting updated for multi row update mode", () => {
cy.dragAndDropToCanvas("textwidget", { x: 400, y: 400 });
cy.get(".t--widget-textwidget").should("exist");
cy.updateCodeInput(

View File

@ -74,7 +74,7 @@ describe("Table Widget text wrapping functionality", function() {
});
});
it("4. should check that cell wrapping option is only available for plain text, number, date and URL", () => {
it("4. should check that cell wrapping option is only available for plain text, number and URL", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("email");
[
@ -92,7 +92,7 @@ describe("Table Widget text wrapping functionality", function() {
},
{
columnType: "Date",
expected: "exist",
expected: "not.exist",
},
{
columnType: "Image",
@ -127,11 +127,11 @@ describe("Table Widget text wrapping functionality", function() {
});
});
it("5. should check that plain text, number, date and URL column is getting wrapped when cell wrapping is enabled", () => {
it("5. should check that plain text, number and URL column is getting wrapped when cell wrapping is enabled", () => {
cy.openPropertyPane("tablewidgetv2");
cy.editColumn("id");
["URL", "Number", "Date", "Plain Text"].forEach((data, i) => {
["URL", "Number", "Plain Text"].forEach((data, i) => {
cy.get(commonlocators.changeColType)
.last()
.click();

View File

@ -57,7 +57,7 @@ describe("Table widget inline editing validation functionality", () => {
.contains("Date")
.click();
cy.wait("@updateLayout");
cy.get(".t--property-pane-section-collapse-validation").should("not.exist");
cy.get(".t--property-pane-section-collapse-validation").should("exist");
cy.get(commonlocators.changeColType)
.last()
.click();

View File

@ -167,6 +167,15 @@ class DatePickerComponent extends React.Component<
return _date.isValid() ? _date.toDate() : undefined;
};
getConditionalPopoverProps = (props: DatePickerComponentProps) => {
if (typeof props.isPopoverOpen === "boolean") {
return {
isOpen: props.isPopoverOpen,
};
}
return {};
};
render() {
const {
compactMode,
@ -357,6 +366,14 @@ class DatePickerComponent extends React.Component<
usePortal: !this.props.withoutPortal,
canEscapeKeyClose: true,
portalClassName: `${DATEPICKER_POPUP_CLASSNAME}-${this.props.widgetId}`,
onClose: this.props.onPopoverClosed,
/*
Conditional popover props are the popover props that should not be sent to
DateInput in any way if they are not applicable.
Here isOpen prop if sent in any way will interfere with the normal functionality
of Date Picker widget's popover but is required for Table Widget's date cell popover
*/
...this.getConditionalPopoverProps(this.props),
}}
shortcuts={this.props.shortcuts}
showActionsBar
@ -404,6 +421,9 @@ class DatePickerComponent extends React.Component<
isValid = false;
}
}
if (!isValid && this.props?.onDateOutOfRange) {
this.props.onDateOutOfRange();
}
return isValid;
};
@ -474,6 +494,9 @@ interface DatePickerComponentProps extends ComponentProps {
labelTooltip?: string;
onFocus?: () => void;
onBlur?: () => void;
onPopoverClosed?: (e: unknown) => void;
isPopoverOpen?: boolean;
onDateOutOfRange?: () => void;
}
interface DatePickerComponentState {

View File

@ -15,6 +15,7 @@ import {
MenuItemsSource,
} from "widgets/MenuButtonWidget/constants";
import { ColumnTypes } from "../constants";
import { TimePrecision } from "widgets/DatePickerWidget2/constants";
export type TableSizes = {
COLUMN_HEADER_HEIGHT: number;
@ -182,6 +183,13 @@ export interface ImageCellProperties {
imageSize?: ImageSize;
}
export interface DateCellProperties {
inputFormat: string;
outputFormat: string;
shortcuts: boolean;
timePrecision?: TimePrecision;
}
export interface BaseCellProperties {
horizontalAlignment?: CellAlignment;
verticalAlignment?: VerticalAlignment;
@ -206,6 +214,7 @@ export interface CellLayoutProperties
MenuButtonCellProperties,
SelectCellProperties,
ImageCellProperties,
DateCellProperties,
BaseCellProperties {}
export interface TableColumnMetaProps {
@ -264,6 +273,8 @@ export interface ColumnStyleProperties {
export interface DateColumnProperties {
outputFormat?: string;
inputFormat?: string;
shortcuts?: boolean;
timePrecision?: TimePrecision;
}
export interface ColumnEditabilityProperties {
@ -276,6 +287,8 @@ export interface ColumnEditabilityProperties {
isEditableCellRequired?: boolean;
min?: number;
max?: number;
minDate?: string;
maxDate?: string;
};
}

View File

@ -0,0 +1,357 @@
import React, { useMemo, useRef, useState } from "react";
import {
ALIGN_ITEMS,
VerticalAlignment,
EDITABLE_CELL_PADDING_OFFSET,
TABLE_SIZES,
} from "../Constants";
import DateComponent from "widgets/DatePickerWidget2/component";
import { TimePrecision } from "widgets/DatePickerWidget2/constants";
import { RenderDefaultPropsType } from "./PlainTextCell";
import styled from "styled-components";
import { EditableCellActions } from "widgets/TableWidgetV2/constants";
import { ISO_DATE_FORMAT } from "constants/WidgetValidation";
import moment from "moment";
import { BasicCell } from "./BasicCell";
import { Colors } from "constants/Colors";
import ErrorTooltip from "components/editorComponents/ErrorTooltip";
import {
createMessage,
INPUT_WIDGET_DEFAULT_VALIDATION_ERROR,
} from "@appsmith/constants/messages";
type DateComponentProps = RenderDefaultPropsType &
editPropertyType & {
accentColor?: string;
borderRadius?: string;
boxShadow?: string;
closeOnSelection: boolean;
maxDate: string;
minDate: string;
onDateChange?: string;
shortcuts: boolean;
timePrecision: TimePrecision;
inputFormat: string;
outputFormat: string;
onDateSave: (
rowIndex: number,
alias: string,
value: string,
onSubmit?: string,
) => void;
onDateSelectedString: string;
firstDayOfWeek?: number;
isRequired: boolean;
updateNewRowValues: (
alias: string,
value: unknown,
parsedValue: unknown,
) => void;
};
const COMPONENT_DEFAULT_VALUES = {
maxDate: "2121-12-31T18:29:00.000Z",
minDate: "1920-12-31T18:30:00.000Z",
timePrecision: TimePrecision.MINUTE,
};
type editPropertyType = {
alias: string;
onDateSelectedString: string;
rowIndex: number;
};
const DEFAULT_BORDER_RADIUS = "0";
const Container = styled.div<{
isCellEditMode?: boolean;
verticalAlignment?: VerticalAlignment;
cellBackground?: string;
}>`
height: 100%;
width: 100%;
display: flex;
align-items: ${(props) =>
props.verticalAlignment && ALIGN_ITEMS[props.verticalAlignment]};
`;
const FOCUS_CLASS = "has-focus";
const Wrapper = styled.div<{
accentColor: string;
compactMode: string;
allowCellWrapping?: boolean;
verticalAlignment?: VerticalAlignment;
textSize?: string;
isEditableCellValid: boolean;
paddedInput: boolean;
}>`
padding: 1px;
border: 1px solid
${(props) => (!props.isEditableCellValid ? Colors.DANGER_SOLID : "#fff")};
background: #fff;
position: absolute;
width: ${(props) =>
props.paddedInput
? `calc(100% - ${EDITABLE_CELL_PADDING_OFFSET}px)`
: "100%"};
left: 50%;
transform: translate(-50%, 0);
overflow: hidden;
border-radius: 3px;
display: flex;
height: ${(props) => {
if (props.allowCellWrapping) {
return props.paddedInput
? `calc(100% - ${EDITABLE_CELL_PADDING_OFFSET}px)`
: "100%";
} else {
return props.paddedInput
? `${TABLE_SIZES[props.compactMode].ROW_HEIGHT -
EDITABLE_CELL_PADDING_OFFSET}px`
: `${TABLE_SIZES[props.compactMode].ROW_HEIGHT}px`;
}
}};
${(props) => {
switch (props.verticalAlignment) {
case "TOP":
return `top: 0;`;
case "BOTTOM":
return `bottom: 0;`;
case "CENTER":
return `
top: calc(50% - (${TABLE_SIZES[props.compactMode].ROW_HEIGHT}/2)px);
`;
}
}}
&&&&& {
.bp3-input,
.bp3-input:focus {
border: none;
/*
* using !important since underlying
* component styles has !important
*/
box-shadow: none !important;
padding: 0px 5px 0px 6px;
font-size: ${(props) => props.textSize};
background: transparent;
color: inherit;
}
}
&.${FOCUS_CLASS} {
${(props) =>
props.isEditableCellValid && `border: 1px solid ${props.accentColor}`}
}
`;
export const DateCell = (props: DateComponentProps) => {
const {
accentColor,
alias,
allowCellWrapping,
borderRadius,
cellBackground,
columnType,
compactMode,
disabledEditIcon,
disabledEditIconMessage,
firstDayOfWeek,
fontStyle,
hasUnsavedChanges,
horizontalAlignment,
inputFormat,
isCellDisabled,
isCellEditable,
isCellEditMode,
isCellVisible,
isHidden,
isNewRow,
isRequired,
maxDate,
minDate,
onDateSave,
onDateSelectedString,
outputFormat,
rowIndex,
shortcuts,
tableWidth,
textColor,
textSize,
timePrecision,
toggleCellEditMode,
updateNewRowValues,
validationErrorMessage,
value,
verticalAlignment,
widgetId,
} = props;
const [hasFocus, setHasFocus] = useState(false);
const [isValid, setIsValid] = useState(true);
const [showRequiredError, setShowRequiredError] = useState(false);
const contentRef = useRef<HTMLDivElement>(null);
const valueInISOFormat = useMemo(() => {
if (typeof value !== "string") return "";
if (moment(value, ISO_DATE_FORMAT, true).isValid()) {
return value;
}
const valueInSelectedFormat = moment(value, props.outputFormat, true);
if (valueInSelectedFormat.isValid()) {
return valueInSelectedFormat.format(ISO_DATE_FORMAT);
}
return value;
}, [value, props.outputFormat]);
const onDateSelected = (date: string) => {
if (isNewRow) {
updateNewRowValues(alias, date, date);
return;
}
if (isRequired && !date) {
setIsValid(false);
setShowRequiredError(true);
return;
}
setIsValid(true);
setShowRequiredError(false);
setHasFocus(false);
const formattedDate = date ? moment(date).format(inputFormat) : "";
onDateSave(rowIndex, alias, formattedDate, onDateSelectedString);
};
const onDateCellEdit = () => {
setHasFocus(true);
if (isRequired && !value) {
setIsValid(false);
setShowRequiredError(true);
}
toggleCellEditMode(true, rowIndex, alias, value);
};
const onPopoverClosed = () => {
setHasFocus(false);
setIsValid(true);
toggleCellEditMode(
false,
rowIndex,
alias,
value,
"",
EditableCellActions.DISCARD,
);
};
const onDateOutOfRange = () => {
setIsValid(false);
setShowRequiredError(false);
};
const onDateInputFocus = () => {
if (isNewRow) {
setHasFocus(true);
}
};
let editor;
if (isCellEditMode) {
editor = (
<Wrapper
accentColor={accentColor}
allowCellWrapping={allowCellWrapping}
className={`${
hasFocus ? FOCUS_CLASS : ""
} t--inlined-cell-editor ${!isValid &&
"t--inlined-cell-editor-has-error"}`}
compactMode={compactMode}
isEditableCellValid={isValid}
paddedInput
textSize={textSize}
verticalAlignment={verticalAlignment}
>
<ErrorTooltip
isOpen={showRequiredError && !isValid}
message={
validationErrorMessage ||
createMessage(INPUT_WIDGET_DEFAULT_VALIDATION_ERROR)
}
>
<DateComponent
accentColor={accentColor}
borderRadius={borderRadius || DEFAULT_BORDER_RADIUS}
closeOnSelection
compactMode
dateFormat={outputFormat}
datePickerType="DATE_PICKER"
firstDayOfWeek={firstDayOfWeek}
isDisabled={!isNewRow}
isLoading={false}
/*
* Reason for using `undefined`
* https://github.com/appsmithorg/appsmith/pull/19181#discussion_r1066871100
**/
isPopoverOpen={isNewRow ? undefined : true}
labelText=""
maxDate={maxDate || COMPONENT_DEFAULT_VALUES.maxDate}
minDate={minDate || COMPONENT_DEFAULT_VALUES.minDate}
onDateOutOfRange={onDateOutOfRange}
onDateSelected={onDateSelected}
onFocus={onDateInputFocus}
onPopoverClosed={onPopoverClosed}
selectedDate={valueInISOFormat}
shortcuts={shortcuts}
timePrecision={
timePrecision || COMPONENT_DEFAULT_VALUES.timePrecision
}
widgetId={widgetId}
/>
</ErrorTooltip>
</Wrapper>
);
}
return (
<Container
cellBackground={cellBackground}
className="t--table-text-cell"
isCellEditMode={isCellEditMode}
verticalAlignment={verticalAlignment}
>
<BasicCell
accentColor={accentColor}
allowCellWrapping={allowCellWrapping}
cellBackground={cellBackground}
columnType={columnType}
compactMode={compactMode}
disabledEditIcon={disabledEditIcon}
disabledEditIconMessage={disabledEditIconMessage}
fontStyle={fontStyle}
hasUnsavedChanges={hasUnsavedChanges}
horizontalAlignment={horizontalAlignment}
isCellDisabled={isCellDisabled}
isCellEditMode={isCellEditMode}
isCellEditable={isCellEditable}
isCellVisible={isCellVisible}
isHidden={isHidden}
onEdit={onDateCellEdit}
ref={contentRef}
tableWidth={tableWidth}
textColor={textColor}
textSize={textSize}
value={value}
verticalAlignment={verticalAlignment}
/>
{editor}
</Container>
);
};

View File

@ -87,7 +87,9 @@ import { SwitchCell } from "../component/cellComponents/SwitchCell";
import { SelectCell } from "../component/cellComponents/SelectCell";
import { CellWrapper } from "../component/TableStyledWrappers";
import { Stylesheet } from "entities/AppTheming";
import { DateCell } from "../component/cellComponents/DateCell";
import { MenuItem, MenuItemsSource } from "widgets/MenuButtonWidget/constants";
import { TimePrecision } from "widgets/DatePickerWidget2/constants";
const ReactTableComponent = lazy(() =>
retryPromise(() => import("../component")),
@ -1840,6 +1842,59 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
/>
);
case ColumnTypes.DATE:
return (
<DateCell
accentColor={this.props.accentColor}
alias={props.cell.column.columnProperties.alias}
borderRadius={this.props.borderRadius}
cellBackground={cellProperties.cellBackground}
closeOnSelection
columnType={column.columnType}
compactMode={compactMode}
disabledEditIcon={
shouldDisableEdit || this.props.isAddRowInProgress
}
disabledEditIconMessage={disabledEditMessage}
firstDayOfWeek={props.cell.column.columnProperties.firstDayOfWeek}
fontStyle={cellProperties.fontStyle}
hasUnsavedChanges={cellProperties.hasUnsavedChanges}
horizontalAlignment={cellProperties.horizontalAlignment}
inputFormat={cellProperties.inputFormat}
isCellDisabled={cellProperties.isCellDisabled}
isCellEditMode={isCellEditMode}
isCellEditable={isCellEditable}
isCellVisible={cellProperties.isCellVisible ?? true}
isEditableCellValid={this.isColumnCellValid(alias)}
isHidden={isHidden}
isNewRow={isNewRow}
isRequired={
props.cell.column.columnProperties.validation
.isColumnEditableCellRequired
}
maxDate={props.cell.column.columnProperties.validation.maxDate}
minDate={props.cell.column.columnProperties.validation.minDate}
onCellTextChange={this.onCellTextChange}
onDateSave={this.onDateSave}
onDateSelectedString={
props.cell.column.columnProperties.onDateSelected
}
outputFormat={cellProperties.outputFormat}
rowIndex={rowIndex}
shortcuts={cellProperties.shortcuts}
tableWidth={this.getComponentDimensions().componentWidth}
textColor={cellProperties.textColor}
textSize={cellProperties.textSize}
timePrecision={cellProperties.timePrecision || TimePrecision.NONE}
toggleCellEditMode={this.toggleCellEditMode}
updateNewRowValues={this.updateNewRowValues}
validationErrorMessage="This field is required"
value={props.cell.value}
verticalAlignment={cellProperties.verticalAlignment}
widgetId={this.props.widgetId}
/>
);
default:
let validationErrorMessage;
@ -1989,6 +2044,35 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
}
};
onDateSave = (
rowIndex: number,
alias: string,
value: string,
onSubmit?: string,
) => {
if (this.isColumnCellValid(alias)) {
this.updateTransientTableData({
[ORIGINAL_INDEX_KEY]: this.getRowOriginalIndex(rowIndex),
[alias]: value,
});
if (onSubmit && this.props.editableCell?.column) {
this.onColumnEvent({
rowIndex: rowIndex,
action: onSubmit,
triggerPropertyName: "onSubmit",
eventType: EventType.ON_SUBMIT,
row: {
...this.props.filteredTableData[rowIndex],
[this.props.editableCell.column]: value,
},
});
}
this.clearEditableCell();
}
};
clearEditableCell = (skipTimeout?: boolean) => {
const clear = () => {
this.props.updateWidgetMetaProperty("editableCell", defaultEditableCell);

View File

@ -174,7 +174,7 @@ export default {
},
{
propertyName: "inputFormat",
label: "Original Date Format",
label: "Date Format",
helpText: "Date format of incoming data to the column",
controlType: "DROP_DOWN",
options: [
@ -265,7 +265,7 @@ export default {
hidden: (props: TableWidgetProps, propertyPath: string) => {
const baseProperty = getBasePropertyPath(propertyPath);
const columnType = get(props, `${baseProperty}.columnType`, "");
return columnType !== "date";
return columnType !== ColumnTypes.DATE;
},
dependencies: ["primaryColumns", "columnOrder"],
isBindProperty: true,
@ -303,7 +303,7 @@ export default {
},
{
propertyName: "outputFormat",
label: "Display Date Format",
label: "Display Format",
helpText: "Date format to be shown to users",
controlType: "DROP_DOWN",
customJSControl: "TABLE_COMPUTE_VALUE",
@ -394,7 +394,7 @@ export default {
hidden: (props: TableWidgetProps, propertyPath: string) => {
const baseProperty = getBasePropertyPath(propertyPath);
const columnType = get(props, `${baseProperty}.columnType`, "");
return columnType !== "date";
return columnType !== ColumnTypes.DATE;
},
dependencies: ["primaryColumns", "columnType"],
isBindProperty: true,

View File

@ -0,0 +1,57 @@
import { ValidationTypes } from "constants/WidgetValidation";
import { ColumnTypes, TableWidgetProps } from "widgets/TableWidgetV2/constants";
import { get } from "lodash";
import {
allowedFirstDayOfWeekRange,
showByColumnType,
} from "../../propertyUtils";
import { AutocompleteDataType } from "utils/autocomplete/CodemirrorTernService";
export default {
sectionName: "Date Settings",
hidden: (props: TableWidgetProps, propertyPath: string) => {
if (showByColumnType(props, propertyPath, [ColumnTypes.IMAGE], true)) {
return false;
} else {
const columnType = get(props, `${propertyPath}.columnType`, "");
const isEditable = get(props, `${propertyPath}.isEditable`, "");
return columnType !== ColumnTypes.DATE || !isEditable;
}
},
children: [
{
propertyName: "firstDayOfWeek",
label: "First Day Of Week",
helpText: "Defines the first day of the week for calendar",
controlType: "INPUT_TEXT",
defaultValue: "0",
inputType: "NUMBER",
isBindProperty: true,
isTriggerProperty: false,
dependencies: ["primaryColumns", "columnType"],
validation: {
type: ValidationTypes.FUNCTION,
params: {
fnString: allowedFirstDayOfWeekRange.toString(),
expected: {
type:
"0 : sunday\n1 : monday\n2 : tuesday\n3 : wednesday\n4 : thursday\n5 : friday\n6 : saturday",
example: "0",
autocompleteDataType: AutocompleteDataType.STRING,
},
},
},
},
{
propertyName: "shortcuts",
label: "Show Shortcuts",
helpText: "Choose to show shortcut menu",
controlType: "SWITCH",
isJSConvertible: false,
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
dependencies: ["primaryColumns", "columnType"],
},
],
};

View File

@ -4,6 +4,7 @@ import {
getBasePropertyPath,
showByColumnType,
hideByColumnType,
getColumnPath,
} from "../../propertyUtils";
export default {
@ -20,7 +21,8 @@ export default {
columnType === ColumnTypes.NUMBER ||
columnType === ColumnTypes.CHECKBOX ||
columnType === ColumnTypes.SWITCH ||
columnType === ColumnTypes.SELECT
columnType === ColumnTypes.SELECT ||
columnType === ColumnTypes.DATE
) || !isEditable
);
}
@ -133,5 +135,19 @@ export default {
filterText: "",
}),
},
{
propertyName: "onDateSelected",
label: "onDateSelected",
helpText: "Triggers an action when a date is selected in the calendar",
controlType: "ACTION_SELECTOR",
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: true,
dependencies: ["primaryColumns"],
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = getColumnPath(propertyPath);
return hideByColumnType(props, path, [ColumnTypes.DATE], true);
},
},
],
};

View File

@ -99,7 +99,6 @@ export default {
ColumnTypes.TEXT,
ColumnTypes.NUMBER,
ColumnTypes.URL,
ColumnTypes.DATE,
]);
},
},
@ -234,7 +233,6 @@ export const GeneralStyle = {
},
},
},
{
propertyName: "imageSize",
dependencies: ["primaryColumns", "columnType"],

View File

@ -3,6 +3,7 @@ import { get } from "lodash";
import { hideByColumnType } from "../../propertyUtils";
import commonValidations from "./Validations/Common";
import numberTypeValidations from "./Validations/Number";
import dateTypeValidations from "./Validations/Date";
export default {
sectionName: "Validation",
@ -14,10 +15,14 @@ export default {
hideByColumnType(
props,
propertyPath,
[ColumnTypes.TEXT, ColumnTypes.NUMBER],
[ColumnTypes.TEXT, ColumnTypes.NUMBER, ColumnTypes.DATE],
true,
)
);
},
children: [...numberTypeValidations, ...commonValidations],
children: [
...numberTypeValidations,
...dateTypeValidations,
...commonValidations,
],
};

View File

@ -1,4 +1,9 @@
import { ValidationTypes } from "constants/WidgetValidation";
import { TableWidgetProps, ColumnTypes } from "widgets/TableWidgetV2/constants";
import {
showByColumnType,
getColumnPath,
} from "widgets/TableWidgetV2/widget/propertyUtils";
export default [
{
@ -11,6 +16,11 @@ export default [
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.REGEX },
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = getColumnPath(propertyPath);
return showByColumnType(props, path, [ColumnTypes.DATE], true);
},
},
{
propertyName: "validation.isColumnEditableCellValid",
@ -27,6 +37,10 @@ export default [
default: true,
},
},
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = getColumnPath(propertyPath);
return showByColumnType(props, path, [ColumnTypes.DATE], true);
},
},
{
propertyName: "validation.errorMessage",
@ -38,6 +52,10 @@ export default [
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.TEXT },
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = getColumnPath(propertyPath);
return showByColumnType(props, path, [ColumnTypes.DATE], true);
},
},
{
propertyName: "validation.isColumnEditableCellRequired",

View File

@ -0,0 +1,36 @@
import { ColumnTypes, TableWidgetProps } from "widgets/TableWidgetV2/constants";
import {
getColumnPath,
hideByColumnType,
} from "widgets/TableWidgetV2/widget/propertyUtils";
export default [
{
propertyName: "validation.minDate",
helpText: "Sets the minimum allowed date",
label: "Min Date",
controlType: "DATE_PICKER",
placeholderText: "1",
isBindProperty: true,
isTriggerProperty: false,
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = getColumnPath(propertyPath);
return hideByColumnType(props, path, [ColumnTypes.DATE], true);
},
dependencies: ["primaryColumns"],
},
{
propertyName: "validation.maxDate",
helpText: "Sets the maximum allowed value",
label: "Max Date",
controlType: "DATE_PICKER",
placeholderText: "100",
isBindProperty: true,
isTriggerProperty: false,
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = getColumnPath(propertyPath);
return hideByColumnType(props, path, [ColumnTypes.DATE], true);
},
dependencies: ["primaryColumns"],
},
];

View File

@ -1,6 +1,9 @@
import { ValidationTypes } from "constants/WidgetValidation";
import { ColumnTypes, TableWidgetProps } from "widgets/TableWidgetV2/constants";
import { hideByColumnType } from "widgets/TableWidgetV2/widget/propertyUtils";
import {
hideByColumnType,
getColumnPath,
} from "widgets/TableWidgetV2/widget/propertyUtils";
export default [
{
@ -16,11 +19,7 @@ export default [
params: { default: -Infinity },
},
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = propertyPath
.split(".")
.slice(0, 2)
.join(".");
const path = getColumnPath(propertyPath);
return hideByColumnType(props, path, [ColumnTypes.NUMBER], true);
},
dependencies: ["primaryColumns"],
@ -38,11 +37,7 @@ export default [
params: { default: Infinity },
},
hidden: (props: TableWidgetProps, propertyPath: string) => {
const path = propertyPath
.split(".")
.slice(0, 2)
.join(".");
const path = getColumnPath(propertyPath);
return hideByColumnType(props, path, [ColumnTypes.NUMBER], true);
},
dependencies: ["primaryColumns"],

View File

@ -15,6 +15,7 @@ import Color from "./Color";
import BorderAndShadow from "./BorderAndShadow";
import Validations from "./Validation";
import Select from "./Select";
import DateProperties from "./DateProperties";
import { updateCustomColumnAliasOnLabelChange } from "../../propertyUtils";
export default {
@ -31,6 +32,7 @@ export default {
DiscardButtonproperties,
Select,
Events,
DateProperties,
],
styleChildren: [
GeneralStyle,

View File

@ -8,6 +8,7 @@ import {
uniqueColumnAliasValidation,
updateCustomColumnAliasOnLabelChange,
selectColumnOptionsValidation,
allowedFirstDayOfWeekRange,
} from "./propertyUtils";
import _ from "lodash";
import { ColumnTypes, TableWidgetProps } from "../constants";
@ -950,3 +951,37 @@ describe("updateCustomColumnAliasOnLabelChange", () => {
]);
});
});
describe("allowedFirstDayOfWeekRange", () => {
it("should return valid object value is within 0 to 6", () => {
expect(allowedFirstDayOfWeekRange(4)).toEqual({
isValid: true,
parsed: 4,
messages: [],
});
});
it("should return valid object value is within 0 to 6", () => {
expect(allowedFirstDayOfWeekRange(0)).toEqual({
isValid: true,
parsed: 0,
messages: [],
});
});
it("should return invalid object when value is not within 0 to 6", () => {
expect(allowedFirstDayOfWeekRange(8)).toEqual({
isValid: false,
parsed: 0,
messages: ["Number should be between 0-6."],
});
});
it("should return invalid object when value is not within 0 to 6", () => {
expect(allowedFirstDayOfWeekRange(-2)).toEqual({
isValid: false,
parsed: 0,
messages: ["Number should be between 0-6."],
});
});
});

View File

@ -643,6 +643,16 @@ export const updateCustomColumnAliasOnLabelChange = (
}
};
export const allowedFirstDayOfWeekRange = (value: number) => {
const allowedValues = [0, 1, 2, 3, 4, 5, 6];
const isValid = allowedValues.includes(Number(value));
return {
isValid: isValid,
parsed: isValid ? Number(value) : 0,
messages: isValid ? [] : ["Number should be between 0-6."],
};
};
export const hideByMenuItemsSource = (
props: TableWidgetProps,
propertyPath: string,
@ -895,3 +905,9 @@ export function selectColumnOptionsValidation(
messages: [_message],
};
}
export const getColumnPath = (propPath: string) =>
propPath
.split(".")
.slice(0, 2)
.join(".");

View File

@ -468,14 +468,30 @@ export const getCellProperties = (
rowIndex,
true,
),
resetFilterTextOnClose: getBooleanPropertyValue(
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;
@ -487,6 +503,7 @@ const EdtiableColumnTypes: string[] = [
ColumnTypes.SELECT,
ColumnTypes.CHECKBOX,
ColumnTypes.SWITCH,
ColumnTypes.DATE,
];
export function isColumnTypeEditable(columnType: string) {