Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: custom widget #28926

Merged
merged 47 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
33cd4f7
init
Nov 13, 2023
01bdf8d
widget properties and search wildcard
Nov 14, 2023
4b563a5
property controls
Nov 15, 2023
8d77e94
redo add event control and feature flagging
Nov 17, 2023
c6272ca
widget builder
Nov 20, 2023
25ae180
reset css
Nov 20, 2023
cafe6a3
reset css
Nov 20, 2023
a7bef4c
more changes to widget builder
Nov 21, 2023
d84c7d9
changes
Nov 21, 2023
036f97c
mode changes to default DSL
Nov 21, 2023
42d0c4c
more changes
Nov 23, 2023
5d47432
more changes
Nov 30, 2023
50d8777
debugger
Dec 1, 2023
e689971
width issues
Dec 1, 2023
f10c988
overlay issue
Dec 6, 2023
8796670
Debugger improvements & autocomplete
sbalaji1192 Dec 14, 2023
8047720
checking changes
sbalaji1192 Dec 14, 2023
a0bd861
temp changes to unblock babel issue
sbalaji1192 Dec 14, 2023
8b7c0b6
help tooltips
sbalaji1192 Dec 14, 2023
cddd1bd
more changes
sbalaji1192 Dec 14, 2023
e0581f2
checkin
sbalaji1192 Dec 17, 2023
d860814
final changes
sbalaji1192 Dec 17, 2023
866234c
Merge branch 'release' into feat/custom-widget
Dec 17, 2023
63c59c2
more changes
sbalaji1192 Dec 18, 2023
daabb79
css fixes
sbalaji1192 Dec 18, 2023
ec7e878
more changes
sbalaji1192 Dec 18, 2023
5cbff3a
uncheck yarn.lock changes
sbalaji1192 Dec 18, 2023
7468535
more changes
sbalaji1192 Dec 20, 2023
6773cc1
internationalization
sbalaji1192 Dec 21, 2023
ec91861
lift builder connection up
sbalaji1192 Dec 21, 2023
cb894b6
Merge branch 'release' into feat/custom-widget
sbalaji1192 Dec 21, 2023
15e1f92
autocomplete & console try catch
sbalaji1192 Dec 25, 2023
611d2e5
Merge branch 'release' into feat/custom-widget
sbalaji1192 Dec 25, 2023
02480d8
unit tests
sbalaji1192 Dec 25, 2023
d7e2969
more unit tests
sbalaji1192 Dec 26, 2023
fca401b
minor changes
sbalaji1192 Dec 26, 2023
27ac856
API update: theme
sbalaji1192 Dec 26, 2023
0479154
Merge branch 'release' into feat/custom-widget
Dec 27, 2023
447a18f
type fix
sbalaji1192 Dec 27, 2023
30bba5b
CR fixes
sbalaji1192 Dec 27, 2023
7a45f29
encodeURIComponent
sbalaji1192 Dec 27, 2023
91144e0
file typo
sbalaji1192 Dec 27, 2023
b575677
cypress fix
sbalaji1192 Dec 27, 2023
fc1b2be
cypress fix
sbalaji1192 Dec 27, 2023
0a3234e
jest fix
sbalaji1192 Dec 27, 2023
fc52e82
remove comment
sbalaji1192 Dec 27, 2023
9081be3
jest fix
sbalaji1192 Dec 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/client/craco.common.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,11 @@ module.exports = {
ignoreWarnings: [
function ignoreSourcemapsloaderWarnings(warning) {
return (
warning.module &&
(warning.module &&
warning.module.resource.includes("node_modules") &&
warning.details &&
warning.details.includes("source-map-loader")
warning.details.includes("source-map-loader")) ||
warning.module.resource.includes("/node_modules/@babel/standalone/babel.js")
);
},
],
Expand Down
29 changes: 0 additions & 29 deletions app/client/generators/widget/templates/index.js.hbs
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
import Widget from "./widget";
import IconSVG from "./icon.svg";

export const CONFIG = {
type: Widget.getWidgetType(),
name: "{{name}}", // The display name which will be made in uppercase and show in the widgets panel ( can have spaces )
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
features: {
dynamicHeight: {
sectionIndex: 0, // Index of the property pane "General" section
active: false,
},
},
defaults: {
widgetName: "{{name}}",
rows: 1,
columns: 3,
version: 1,
},
properties: {
derived: Widget.getDerivedPropertiesMap(),
default: Widget.getDefaultPropertiesMap(),
meta: Widget.getMetaPropertiesMap(),
contentConfig: Widget.getPropertyPaneContentConfig(),
styleConfig: Widget.getPropertyPaneStyleConfig(),
autocompleteDefinitions: Widget.getAutocompleteDefinitions()
},
};

export default Widget;
42 changes: 35 additions & 7 deletions app/client/generators/widget/templates/widget/index.js.hbs
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
import React from "react";

import type { DerivedPropertiesMap } from "WidgetProvider/factory";

import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
import { DerivedPropertiesMap } from "WidgetProvider/factory";

import {{name}}Component from "../component";

import IconSVG from "../icon.svg";

class {{suffixed name}} extends BaseWidget<{{suffixed name}}Props, WidgetState> {
static type = "{{widgetTypeFormat name}}";

static getConfig() {
return {
name: "{{name}}", // The display name which will be made in uppercase and show in the widgets panel ( can have spaces )
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
};
}

static getFeatures() {
return {
dynamicHeight: {
sectionIndex: 0, // Index of the property pane "General" section
active: false,
},
};
}

static getDefaults() {
return {
widgetName: "{{name}}",
rows: 1,
columns: 3,
version: 1,
};
}

static getPropertyPaneContentConfig() {
return [];
}
Expand All @@ -26,15 +58,11 @@ class {{suffixed name}} extends BaseWidget<{{suffixed name}}Props, WidgetState>
return {};
}

getPageView() {
getWidgetView() {
return <{{name}}Component />;
}

static getWidgetType(): string {
return "{{widgetTypeFormat name}}";
}
}

export interface {{suffixed name}}Props extends WidgetProps {}

export default {{suffixed name}};
export default {{suffixed name}};
2 changes: 2 additions & 0 deletions app/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.441.0",
"@aws-sdk/lib-storage": "^3.441.0",
"@babel/standalone": "^7.23.6",
"@blueprintjs/core": "^3.43.0",
"@blueprintjs/datetime": "^3.23.6",
"@blueprintjs/icons": "3.22.0",
Expand Down Expand Up @@ -77,6 +78,7 @@
"@shared/dsl": "workspace:^",
"@tanstack/virtual-core": "^3.0.0-beta.18",
"@tinymce/tinymce-react": "^3.13.0",
"@types/babel__standalone": "^7.1.7",
"@types/google.maps": "^3.51.0",
"@types/react-page-visibility": "^6.4.1",
"@types/web": "^0.0.99",
Expand Down
4 changes: 4 additions & 0 deletions app/client/src/WidgetProvider/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export interface WidgetBaseConfiguration {
searchTags?: string[];
tags?: WidgetTags[];
needsHeightForContent?: boolean;

// Flag to tell platform to disaplay this widget when search key
// is not matching any widget.
isSearchWildcard?: boolean;
}

export type WidgetDefaultProps = Partial<WidgetProps> & WidgetConfigProps;
Expand Down
1 change: 1 addition & 0 deletions app/client/src/WidgetProvider/factory/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class WidgetFactory {
iconSVG: config.iconSVG,
isCanvas: config.isCanvas,
needsHeightForContent: config.needsHeightForContent,
isSearchWildcard: config.isSearchWildcard,
};

WidgetFactory.widgetConfigMap.set(widget.type, Object.freeze(_config));
Expand Down
13 changes: 13 additions & 0 deletions app/client/src/ce/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
BUILDER_PATCH_PATH,
BUILDER_PATH,
BUILDER_PATH_DEPRECATED,
CUSTOM_WIDGETS_EDITOR_ID_PATH,
CUSTOM_WIDGETS_EDITOR_ID_PATH_CUSTOM,
PROFILE,
SETUP,
SIGNUP_SUCCESS_URL,
Expand Down Expand Up @@ -74,6 +76,7 @@ import WidgetBuilder from "pages/WidgetBuilder";
import { getAdminSettingsPath } from "@appsmith/utils/BusinessFeatures/adminSettingsHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import CustomWidgetBuilderLoader from "pages/Editor/CustomWidgetBuilder/loader";

export const SentryRoute = Sentry.withSentryRouting(Route);

Expand Down Expand Up @@ -127,6 +130,16 @@ export function Routes() {
/>
<SentryRoute component={EditorLoader} path={BUILDER_PATH_DEPRECATED} />
<SentryRoute component={AppViewerLoader} path={VIEWER_PATH_DEPRECATED} />
<SentryRoute
component={CustomWidgetBuilderLoader}
exact
path={CUSTOM_WIDGETS_EDITOR_ID_PATH}
/>
<SentryRoute
component={CustomWidgetBuilderLoader}
exact
path={CUSTOM_WIDGETS_EDITOR_ID_PATH_CUSTOM}
/>
{/*
* Note: When making changes to the order of these paths
* Be sure to check if it is sync with the order of checks in getUpdatedRoute helper method
Expand Down
104 changes: 104 additions & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2315,4 +2315,108 @@ export const PARTIAL_IMPORT_EXPORT = {
};

export const DATASOURCE_SECURELY_TITLE = () => "Secure & fast connection";

export const CUSTOM_WIDGET_FEATURE = {
addEvent: {
addCTA: () => "Add",
cancelCTA: () => "Cancel",
addEventCTA: () => "Add Event",
nameLabel: () => "Name",
errors: {
restricted: () => "Event name is restricted",
duplicate: () => "Event name already exists",
},
},
editSource: {
editSourceCTA: () => "Edit source",
goToSourceCTA: () => "Go to source editor",
},
builder: {
header: () => "Custom Widget Builder",
close: () => "Close",
connectionLost: () =>
"Connection lost because the custom widget was deselected. Please reselect this widget to continue editing.",
editor: {
css: {
contextTooltip: () => "You can use following css variables",
placeholder: () =>
"/* you can access your string properties of your model using `var(--appsmith-model-<property-name>)`*/",
},
html: {
placeholder: () =>
"<!-- no need to write html, head, body tags, it is handled by the widget -->",
},
js: {
placeholder: () =>
"// no need to write window onLoad, it is handled by the widget",
},
},
},
templateKey: {
blank: () => "Blank",
react: () => "React",
vue: () => "Vue",
},
template: {
modal: {
header: () => "Are you sure?",
body: () =>
"This will replace the current changes in the HTML, CSS and JS files.",
successCTA: () => "Replace",
cancelCTA: () => "Cancel",
},
buttonCTA: () => "Templates",
revert: () => "Revert to Original",
},
layout: {
tab: () => "Tabs",
split: () => "Splits",
},
referrences: {
title: () => "Referrences",
tooltip: {
open: () => "Open references",
close: () => "Close references",
},
liveModel: {
helpMessage: [
() => "- Use `appsmith.model` to access your model in javascript",
() =>
"- Use `appsmith.updateModel()` to update your model from javascript",
],
label: () => "Live Model",
},
events: {
helpMessage: [
() =>
"- Use `appsmith.triggerEvent(&lt;EVENT_NAME&gt;)` to trigger an event",
() =>
"- `appsmith.triggerEvent()` also accepts context data as second arg",
],
label: () => "Events",
emptyMessage: () =>
"You haven’t created any events. Return to the app editor to add events to this custom widget.",
},
help: {
message: () =>
"Learn how custom widgets work, and how to access data from the rest of your app within this widget.",
buttonCTA: () => "Documentation",
},
},
debugger: {
title: () => "Console",
emptyMessage: () => "Errors and logs will appear here",
helpDropdown: {
stackoverflow: () => "Search StackOverflow",
},
},
preview: {
eventFired: () => "Event fired:",
modelUpdated: () => "Model updated",
},
};

export const WIDGET_PANEL_EMPTY_MESSAGE = () =>
"We couldn’t find any widgets called";

export const HTTP_PROTOCOL_INPUT_PLACEHOLDER = () => `Select HTTP Protocol`;
8 changes: 8 additions & 0 deletions app/client/src/ce/constants/routes/appRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export const INTEGRATION_EDITOR_PATH = `/datasources/:selectedTab`;

export const WIDGETS_EDITOR_BASE_PATH = `/widgets`;
export const WIDGETS_EDITOR_ID_PATH = `${WIDGETS_EDITOR_BASE_PATH}/:widgetIds`;

/*
* CUSTOM WIDGET BUILDER PATHS
*/
export const CUSTOM_WIDGETS_EDITOR_ID_PATH = `${BUILDER_PATH}${WIDGETS_EDITOR_ID_PATH}/builder`;
export const CUSTOM_WIDGETS_EDITOR_ID_PATH_CUSTOM = `${BUILDER_CUSTOM_PATH}${WIDGETS_EDITOR_ID_PATH}/builder`;
/* */

export const API_EDITOR_BASE_PATH = `/api`;
export const API_EDITOR_ID_PATH = `${API_EDITOR_BASE_PATH}/:apiId`;
export const API_EDITOR_ID_ADD_PATH = `${API_EDITOR_BASE_PATH}/:apiId/add`;
Expand Down
8 changes: 8 additions & 0 deletions app/client/src/ce/pages/common/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
VIEWER_CUSTOM_PATH,
BUILDER_CUSTOM_PATH,
BASE_URL,
CUSTOM_WIDGETS_EDITOR_ID_PATH,
CUSTOM_WIDGETS_EDITOR_ID_PATH_CUSTOM,
} from "constants/routes";
import Navigation from "pages/AppViewer/Navigation";
import type { RouteComponentProps } from "react-router";
Expand All @@ -29,6 +31,12 @@ export const Routes = () => {
<Route component={undefined} path={USER_AUTH_URL} />
<Route path={SETUP} />
<Route path={SIGNUP_SUCCESS_URL} />
<Route component={undefined} exact path={CUSTOM_WIDGETS_EDITOR_ID_PATH} />
<Route
component={undefined}
exact
path={CUSTOM_WIDGETS_EDITOR_ID_PATH_CUSTOM}
/>
<Route component={AppEditorHeader} path={BUILDER_PATH_DEPRECATED} />
<Route component={Navigation} path={VIEWER_PATH_DEPRECATED} />
<Route component={AppEditorHeader} path={BUILDER_PATH} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const EditorModes = {
JAVASCRIPT: "javascript",
GRAPHQL: "graphql",
GRAPHQL_WITH_BINDING: "graphql-js",
HTMLMIXED: "htmlmixed",
CSS: "css",
...editorSQLModes,
} as const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
checkIfCursorInsideBinding,
isCursorOnEmptyToken,
} from "components/editorComponents/CodeEditor/codeEditorUtils";
import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
import { isEmpty, isString } from "lodash";
import type { getAllDatasourceTableKeys } from "@appsmith/selectors/entitiesSelector";
import {
Expand Down Expand Up @@ -45,10 +44,9 @@ export const bindingHintHelper: HintHelper = (editor: CodeMirror.Editor) => {
CodemirrorTernService.setEntityInformation(editor, entityInformation);
}

const entityType = entityInformation?.entityType;
let shouldShow = false;

if (entityType === ENTITY_TYPE.JSACTION) {
if (additionalData.isJsEditor) {
if (additionalData?.enableAIAssistance) {
shouldShow = !isAISlashCommand(editor);
} else {
Expand Down
Loading
Loading