diff --git a/app/client/src/components/designSystems/appsmith/TableCompactMode.tsx b/app/client/src/components/designSystems/appsmith/TableCompactMode.tsx
new file mode 100644
index 0000000000..1e34e60891
--- /dev/null
+++ b/app/client/src/components/designSystems/appsmith/TableCompactMode.tsx
@@ -0,0 +1,135 @@
+import React from "react";
+import {
+ Popover,
+ Classes,
+ PopoverInteractionKind,
+ Position,
+ Icon,
+ Tooltip,
+} from "@blueprintjs/core";
+import { IconWrapper } from "constants/IconConstants";
+import styled from "styled-components";
+import { Colors } from "constants/Colors";
+import { ReactComponent as CompactIcon } from "assets/icons/control/compact.svg";
+import { TableIconWrapper } from "components/designSystems/appsmith/TableStyledWrappers";
+
+const DropDownWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ background: white;
+ z-index: 1;
+ border-radius: 4px;
+ border: 1px solid ${Colors.ATHENS_GRAY};
+ padding: 8px;
+`;
+
+const OptionWrapper = styled.div<{ selected?: boolean }>`
+ display: flex;
+ width: calc(100% - 20px);
+ justify-content: space-between;
+ align-items: center;
+ height: 32px;
+ box-sizing: border-box;
+ padding: 8px;
+ color: ${Colors.OXFORD_BLUE};
+ opacity: ${props => (props.selected ? 1 : 0.7)};
+ min-width: 200px;
+ cursor: pointer;
+ margin-bottom: 4px;
+ background: ${props => (props.selected ? Colors.POLAR : Colors.WHITE)};
+ border-left: ${props => (props.selected ? "4px solid #29CCA3" : "none")};
+ border-radius: 4px;
+ .option-title {
+ font-weight: 500;
+ font-size: 14px;
+ line-height: 24px;
+ }
+ &:hover {
+ background: ${Colors.POLAR};
+ }
+`;
+
+export enum CompactModeTypes {
+ SHORT = "SHORT",
+ DEFAULT = "DEFAULT",
+}
+
+export type CompactMode = keyof typeof CompactModeTypes;
+
+type CompactModeItem = {
+ title: string;
+ value: CompactMode;
+};
+
+const CompactModes: CompactModeItem[] = [
+ {
+ title: "Short",
+ value: CompactModeTypes.SHORT,
+ },
+ {
+ title: "Default",
+ value: CompactModeTypes.DEFAULT,
+ },
+];
+
+interface TableCompactModeProps {
+ compactMode?: CompactMode;
+ updateCompactMode: (mode: CompactMode) => void;
+}
+
+const TableCompactMode = (props: TableCompactModeProps) => {
+ const [selected, selectMenu] = React.useState(false);
+ return (
+
{
+ selectMenu(false);
+ }}
+ >
+ {
+ selectMenu(!selected);
+ }}
+ >
+
+
+
+
+
+
+
+ {CompactModes.map((item: CompactModeItem, index: number) => {
+ return (
+ {
+ props.updateCompactMode(item.value);
+ }}
+ className={Classes.POPOVER_DISMISS}
+ >
+ {item.title}
+
+ );
+ })}
+
+
+ );
+};
+
+export default TableCompactMode;
diff --git a/app/client/src/components/designSystems/appsmith/TableHeader.tsx b/app/client/src/components/designSystems/appsmith/TableHeader.tsx
index ca493d35ff..cdfa58473e 100644
--- a/app/client/src/components/designSystems/appsmith/TableHeader.tsx
+++ b/app/client/src/components/designSystems/appsmith/TableHeader.tsx
@@ -12,6 +12,9 @@ import SearchComponent from "components/designSystems/appsmith/SearchComponent";
import TableColumnsVisibility from "components/designSystems/appsmith/TableColumnsVisibility";
import { ReactTableColumnProps } from "components/designSystems/appsmith/ReactTableComponent";
import TableDataDownload from "components/designSystems/appsmith/TableDataDownload";
+import TableCompactMode, {
+ CompactMode,
+} from "components/designSystems/appsmith/TableCompactMode";
import { Colors } from "constants/Colors";
const PageNumberInputWrapper = styled(NumericInput)`
@@ -72,6 +75,8 @@ interface TableHeaderProps {
searchTableData: (searchKey: any) => void;
serverSidePaginationEnabled: boolean;
displayColumnActions: boolean;
+ compactMode?: CompactMode;
+ updateCompactMode: (compactMode: CompactMode) => void;
width: number;
}
@@ -99,6 +104,10 @@ const TableHeader = (props: TableHeaderProps) => {
updateHiddenColumns={props.updateHiddenColumns}
/>
)}
+
{props.serverSidePaginationEnabled && (
diff --git a/app/client/src/components/designSystems/appsmith/TableStyledWrappers.tsx b/app/client/src/components/designSystems/appsmith/TableStyledWrappers.tsx
index 0c611eef5d..c4ce903f25 100644
--- a/app/client/src/components/designSystems/appsmith/TableStyledWrappers.tsx
+++ b/app/client/src/components/designSystems/appsmith/TableStyledWrappers.tsx
@@ -1,8 +1,13 @@
import styled from "styled-components";
import { Colors } from "constants/Colors";
-import { TABLE_SIZES } from "components/designSystems/appsmith/Table";
+import { TableSizes } from "components/designSystems/appsmith/Table";
-export const TableWrapper = styled.div<{ width: number; height: number }>`
+export const TableWrapper = styled.div<{
+ width: number;
+ height: number;
+ tableSizes: TableSizes;
+ tableRowHeight?: number;
+}>`
width: 100%;
height: 100%;
background: white;
@@ -24,7 +29,8 @@ export const TableWrapper = styled.div<{ width: number; height: number }>`
position: relative;
overflow-y: auto;
/* Subtracting 9px to handling widget padding */
- height: ${props => props.height - TABLE_SIZES.TABLE_HEADER_HEIGHT - 9}px;
+ height: ${props =>
+ props.height - props.tableSizes.TABLE_HEADER_HEIGHT - 9}px;
.thead,
.tbody {
overflow: hidden;
@@ -77,8 +83,14 @@ export const TableWrapper = styled.div<{ width: number; height: number }>`
background: ${Colors.ATHENS_GRAY_DARKER};
}
.td {
- height: 52px;
- line-height: 52px;
+ height: ${props =>
+ props.tableRowHeight
+ ? props.tableRowHeight
+ : props.tableSizes.ROW_HEIGHT}px;
+ line-height: ${props =>
+ props.tableRowHeight
+ ? props.tableRowHeight
+ : props.tableSizes.ROW_HEIGHT}px;
padding: 0 10px;
}
}
@@ -263,7 +275,7 @@ export const TableHeaderWrapper = styled.div<{
width: number;
}>`
display: flex;
- align-items: center;
+ align-items: flex-end;
width: 100%;
border-bottom: 1px solid ${Colors.GEYSER_LIGHT};
min-width: ${props =>
@@ -276,7 +288,7 @@ export const TableHeaderWrapper = styled.div<{
export const CommonFunctionsMenuWrapper = styled.div`
display: flex;
align-items: center;
- height: 100%;
+ height: 60px;
`;
export const RowWrapper = styled.div`
diff --git a/app/client/src/components/designSystems/appsmith/TableUtilities.tsx b/app/client/src/components/designSystems/appsmith/TableUtilities.tsx
index 2853d5edf3..7db3a0e1c5 100644
--- a/app/client/src/components/designSystems/appsmith/TableUtilities.tsx
+++ b/app/client/src/components/designSystems/appsmith/TableUtilities.tsx
@@ -347,7 +347,9 @@ export const renderCell = (
) => {
switch (columnType) {
case ColumnTypes.IMAGE:
- if (!isString(value)) {
+ if (!value) {
+ return ;
+ } else if (!isString(value)) {
return (
Invalid Image
@@ -384,7 +386,9 @@ export const renderCell = (
);
case ColumnTypes.VIDEO:
const youtubeRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
- if (isString(value) && youtubeRegex.test(value)) {
+ if (!value) {
+ return ;
+ } else if (isString(value) && youtubeRegex.test(value)) {
return (
diff --git a/app/client/src/pages/Editor/QueryEditor/Table.tsx b/app/client/src/pages/Editor/QueryEditor/Table.tsx
index 2d169b64ae..73fe171adc 100644
--- a/app/client/src/pages/Editor/QueryEditor/Table.tsx
+++ b/app/client/src/pages/Editor/QueryEditor/Table.tsx
@@ -5,6 +5,8 @@ import {
} from "components/designSystems/appsmith/TableStyledWrappers";
import { useTable, useFlexLayout } from "react-table";
import styled from "styled-components";
+import { CompactModeTypes } from "components/designSystems/appsmith/TableCompactMode";
+import { TABLE_SIZES } from "components/designSystems/appsmith/Table";
interface TableProps {
data: Record[];
@@ -59,7 +61,11 @@ const Table = (props: TableProps) => {
);
return (
-
+
{headerGroups.map((headerGroup: any, index: number) => (
diff --git a/app/client/src/pages/Editor/WidgetsEditor.tsx b/app/client/src/pages/Editor/WidgetsEditor.tsx
index 2f519af90e..b0c27a46c6 100644
--- a/app/client/src/pages/Editor/WidgetsEditor.tsx
+++ b/app/client/src/pages/Editor/WidgetsEditor.tsx
@@ -78,7 +78,8 @@ const WidgetsEditor = () => {
if (!isFetchingPage && window.location.hash.length > 0) {
const widgetIdFromURLHash = window.location.hash.substr(1);
flashElementById(widgetIdFromURLHash);
- selectWidget(widgetIdFromURLHash);
+ if (document.getElementById(widgetIdFromURLHash))
+ selectWidget(widgetIdFromURLHash);
}
}, [isFetchingPage, selectWidget]);
diff --git a/app/client/src/pages/organization/settings.tsx b/app/client/src/pages/organization/settings.tsx
index d38fd8a85d..220077320b 100644
--- a/app/client/src/pages/organization/settings.tsx
+++ b/app/client/src/pages/organization/settings.tsx
@@ -2,6 +2,8 @@ import React, { useEffect } from "react";
import { connect } from "react-redux";
import { Icon } from "@blueprintjs/core";
import { TableWrapper } from "components/designSystems/appsmith/TableStyledWrappers";
+import { CompactModeTypes } from "components/designSystems/appsmith/TableCompactMode";
+import { TABLE_SIZES } from "components/designSystems/appsmith/Table";
import { AppState } from "reducers";
import {
getAllUsers,
@@ -265,7 +267,11 @@ export const OrgSettings = (props: PageProps) => {
{props.isFetchAllUsers && props.isFetchAllRoles ? (
) : (
-
+
{headerGroups.map((headerGroup: any, index: number) => (
diff --git a/app/client/src/widgets/TableWidget.tsx b/app/client/src/widgets/TableWidget.tsx
index 3d8ae2310f..237ff7fa8a 100644
--- a/app/client/src/widgets/TableWidget.tsx
+++ b/app/client/src/widgets/TableWidget.tsx
@@ -20,6 +20,10 @@ import {
BASE_WIDGET_VALIDATION,
} from "utils/ValidationFactory";
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
+import {
+ CompactMode,
+ CompactModeTypes,
+} from "components/designSystems/appsmith/TableCompactMode";
import { TriggerPropertiesMap } from "utils/WidgetFactory";
import Skeleton from "components/utils/Skeleton";
import moment from "moment";
@@ -245,8 +249,10 @@ class TableWidget extends BaseWidget
{
}
if (isValidDate) {
tableRow[accessor] = moment(value).format(format);
- } else {
+ } else if (value) {
tableRow[accessor] = "Invalid Value";
+ } else {
+ tableRow[accessor] = "";
}
break;
case ColumnTypes.TIME:
@@ -259,8 +265,10 @@ class TableWidget extends BaseWidget {
}
if (isValidTime) {
tableRow[accessor] = moment(value).format("HH:mm");
- } else {
+ } else if (value) {
tableRow[accessor] = "Invalid Value";
+ } else {
+ tableRow[accessor] = "";
}
break;
default:
@@ -289,12 +297,22 @@ class TableWidget extends BaseWidget {
super.updateWidgetMetaProperty("pageNo", pageNo);
}
const { componentWidth, componentHeight } = this.getComponentDimensions();
- const pageSize = Math.floor(
+ const tableSizes =
+ TABLE_SIZES[this.props.compactMode || CompactModeTypes.DEFAULT];
+ let pageSize = Math.floor(
(componentHeight -
- TABLE_SIZES.TABLE_HEADER_HEIGHT -
- TABLE_SIZES.COLUMN_HEADER_HEIGHT) /
- TABLE_SIZES.ROW_HEIGHT,
+ tableSizes.TABLE_HEADER_HEIGHT -
+ tableSizes.COLUMN_HEADER_HEIGHT) /
+ tableSizes.ROW_HEIGHT,
);
+ if (
+ componentHeight -
+ (tableSizes.TABLE_HEADER_HEIGHT +
+ tableSizes.COLUMN_HEADER_HEIGHT +
+ tableSizes.ROW_HEIGHT * pageSize) >
+ 10
+ )
+ pageSize += 1;
if (pageSize !== this.props.pageSize) {
super.updateWidgetMetaProperty("pageSize", pageSize);
@@ -354,6 +372,10 @@ class TableWidget extends BaseWidget {
this.disableDrag(disable);
}}
searchTableData={this.handleSearchTable}
+ compactMode={this.props.compactMode}
+ updateCompactMode={(compactMode: CompactMode) => {
+ super.updateWidgetMetaProperty("compactMode", compactMode);
+ }}
sortTableColumn={(column: string, asc: boolean) => {
this.resetSelectedRowIndex();
super.updateWidgetMetaProperty("sortedColumn", {
@@ -467,6 +489,7 @@ export interface TableWidgetProps extends WidgetProps {
columnNameMap?: { [key: string]: string };
columnTypeMap?: { [key: string]: { type: string; format: string } };
columnSizeMap?: { [key: string]: number };
+ compactMode?: CompactMode;
sortedColumn?: {
column: string;
asc: boolean;
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java
index fb564f5ae5..fcefe3d151 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java
@@ -1,6 +1,7 @@
package com.appsmith.external.plugins;
import com.appsmith.external.models.ActionConfiguration;
+import com.appsmith.external.models.ActionExecutionResult;
import com.appsmith.external.models.DatasourceConfiguration;
import com.appsmith.external.models.DatasourceTestResult;
import org.pf4j.ExtensionPoint;
@@ -20,7 +21,7 @@ public interface PluginExecutor extends ExtensionPoint {
* @param actionConfiguration : These are the configurations which have been used to create an Action from a Datasource.
* @return ActionExecutionResult : This object is returned to the user which contains the result values from the execution.
*/
- Mono