chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
import type { AppState } from "@appsmith/reducers";
|
2023-03-04 07:25:54 +00:00
|
|
|
import {
|
|
|
|
|
GridDefaults,
|
|
|
|
|
MAIN_CONTAINER_WIDGET_ID,
|
|
|
|
|
} from "constants/WidgetConstants";
|
|
|
|
|
import equal from "fast-deep-equal/es6";
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
import type { Context, PropsWithChildren } from "react";
|
2020-01-16 11:46:21 +00:00
|
|
|
import React, {
|
|
|
|
|
createContext,
|
2021-07-23 06:40:39 +00:00
|
|
|
useCallback,
|
2023-03-04 07:25:54 +00:00
|
|
|
useEffect,
|
2021-07-23 06:40:39 +00:00
|
|
|
useMemo,
|
2023-03-04 07:25:54 +00:00
|
|
|
useRef,
|
2020-01-16 11:46:21 +00:00
|
|
|
} from "react";
|
2023-03-04 07:25:54 +00:00
|
|
|
import { useSelector } from "react-redux";
|
2020-01-16 11:46:21 +00:00
|
|
|
import styled from "styled-components";
|
2023-02-03 05:47:40 +00:00
|
|
|
|
2021-08-12 05:45:38 +00:00
|
|
|
import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
|
2020-01-16 11:46:21 +00:00
|
|
|
import { calculateDropTargetRows } from "./DropTargetUtils";
|
2019-09-25 17:24:23 +00:00
|
|
|
import DragLayerComponent from "./DragLayerComponent";
|
2023-03-04 07:25:54 +00:00
|
|
|
import { useDispatch } from "react-redux";
|
2023-02-03 05:47:40 +00:00
|
|
|
import { useShowPropertyPane } from "utils/hooks/dragResizeHooks";
|
2022-11-27 17:12:00 +00:00
|
|
|
import {
|
2023-05-11 04:45:14 +00:00
|
|
|
getCurrentAppPositioningType,
|
2022-11-27 17:12:00 +00:00
|
|
|
getOccupiedSpacesSelectorForContainer,
|
|
|
|
|
previewModeSelector,
|
|
|
|
|
} from "selectors/editorSelectors";
|
2021-06-17 13:26:54 +00:00
|
|
|
import { useWidgetSelection } from "utils/hooks/useWidgetSelection";
|
2021-08-12 05:45:38 +00:00
|
|
|
import { getDragDetails } from "sagas/selectors";
|
2022-11-27 17:12:00 +00:00
|
|
|
import { useAutoHeightUIState } from "utils/hooks/autoHeightUIHooks";
|
2023-02-24 12:38:27 +00:00
|
|
|
import {
|
|
|
|
|
checkContainersForAutoHeightAction,
|
|
|
|
|
updateDOMDirectlyBasedOnAutoHeightAction,
|
|
|
|
|
} from "actions/autoHeightActions";
|
2023-04-03 06:11:10 +00:00
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
isAutoHeightEnabledForWidget,
|
|
|
|
|
isAutoHeightEnabledForWidgetWithLimits,
|
|
|
|
|
} from "widgets/WidgetUtils";
|
2023-03-23 11:41:58 +00:00
|
|
|
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
2023-05-11 04:45:14 +00:00
|
|
|
import { AppPositioningTypes } from "reducers/entityReducers/pageListReducer";
|
2019-09-22 20:25:05 +00:00
|
|
|
|
2023-02-03 05:47:40 +00:00
|
|
|
type DropTargetComponentProps = PropsWithChildren<{
|
2019-09-25 17:24:23 +00:00
|
|
|
snapColumnSpace: number;
|
2023-02-03 05:47:40 +00:00
|
|
|
widgetId: string;
|
|
|
|
|
parentId?: string;
|
2021-04-23 05:43:13 +00:00
|
|
|
noPad?: boolean;
|
2023-02-03 05:47:40 +00:00
|
|
|
bottomRow: number;
|
|
|
|
|
minHeight: number;
|
2023-03-04 07:25:54 +00:00
|
|
|
useAutoLayout?: boolean;
|
|
|
|
|
isMobile?: boolean;
|
|
|
|
|
mobileBottomRow?: number;
|
2023-05-29 04:36:19 +00:00
|
|
|
isListWidgetCanvas?: boolean;
|
2023-02-03 05:47:40 +00:00
|
|
|
}>;
|
2019-09-19 22:25:37 +00:00
|
|
|
|
2020-01-16 11:46:21 +00:00
|
|
|
const StyledDropTarget = styled.div`
|
|
|
|
|
transition: height 100ms ease-in;
|
2020-03-27 09:02:11 +00:00
|
|
|
width: 100%;
|
|
|
|
|
position: relative;
|
|
|
|
|
background: none;
|
|
|
|
|
user-select: none;
|
2021-08-12 05:45:38 +00:00
|
|
|
z-index: 1;
|
2020-01-16 11:46:21 +00:00
|
|
|
`;
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
function Onboarding() {
|
2020-05-14 06:06:20 +00:00
|
|
|
return (
|
2021-11-23 08:01:46 +00:00
|
|
|
<h2 className="absolute top-0 left-0 right-0 flex items-end h-108 justify-center text-2xl font-bold text-gray-300">
|
|
|
|
|
Drag and drop a widget here
|
|
|
|
|
</h2>
|
2020-05-14 06:06:20 +00:00
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2020-05-14 06:06:20 +00:00
|
|
|
|
2020-03-06 09:45:21 +00:00
|
|
|
/*
|
2020-01-16 11:46:21 +00:00
|
|
|
This context will provide the function which will help the draglayer and resizablecomponents trigger
|
|
|
|
|
an update of the main container's rows
|
|
|
|
|
*/
|
|
|
|
|
export const DropTargetContext: Context<{
|
2021-08-12 05:45:38 +00:00
|
|
|
updateDropTargetRows?: (
|
2022-01-25 15:28:31 +00:00
|
|
|
widgetIdsToExclude: string[],
|
2021-08-12 05:45:38 +00:00
|
|
|
widgetBottomRow: number,
|
|
|
|
|
) => number | false;
|
2020-01-16 11:46:21 +00:00
|
|
|
}> = createContext({});
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
/**
|
2023-02-03 05:47:40 +00:00
|
|
|
* This function sets the height in pixels to the provided ref to the number of rows
|
|
|
|
|
* @param ref : The ref to the dropTarget so that we can update the height
|
|
|
|
|
* @param currentRows : Number of rows to set the height
|
2022-11-27 17:12:00 +00:00
|
|
|
*/
|
2023-02-03 05:47:40 +00:00
|
|
|
const updateHeight = (
|
|
|
|
|
ref: React.MutableRefObject<HTMLDivElement | null>,
|
|
|
|
|
currentRows: number,
|
|
|
|
|
) => {
|
|
|
|
|
if (ref.current) {
|
|
|
|
|
const height = currentRows * GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
|
|
|
|
|
ref.current.style.height = `${height}px`;
|
|
|
|
|
ref.current
|
|
|
|
|
.closest(".scroll-parent")
|
|
|
|
|
?.scrollTo({ top: height, behavior: "smooth" });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-04 07:25:54 +00:00
|
|
|
function useUpdateRows(
|
|
|
|
|
bottomRow: number,
|
|
|
|
|
widgetId: string,
|
|
|
|
|
parentId?: string,
|
|
|
|
|
mobileBottomRow?: number,
|
|
|
|
|
isMobile?: boolean,
|
|
|
|
|
isAutoLayoutActive?: boolean,
|
2023-05-29 04:36:19 +00:00
|
|
|
isListWidgetCanvas?: boolean,
|
2023-03-04 07:25:54 +00:00
|
|
|
) {
|
2023-02-03 05:47:40 +00:00
|
|
|
// This gives us the number of rows
|
2023-03-04 07:25:54 +00:00
|
|
|
const snapRows = getCanvasSnapRows(
|
|
|
|
|
bottomRow,
|
|
|
|
|
mobileBottomRow,
|
|
|
|
|
isMobile,
|
|
|
|
|
isAutoLayoutActive,
|
|
|
|
|
);
|
2023-02-03 05:47:40 +00:00
|
|
|
// Put the existing snap rows in a ref.
|
|
|
|
|
const rowRef = useRef(snapRows);
|
|
|
|
|
|
|
|
|
|
const dropTargetRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
|
|
// The occupied spaces in this canvas. It is a data structure which has the rect values of each child.
|
|
|
|
|
const selectOccupiedSpaces = useCallback(
|
|
|
|
|
getOccupiedSpacesSelectorForContainer(widgetId),
|
|
|
|
|
[widgetId],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Call the selector above.
|
|
|
|
|
const occupiedSpacesByChildren = useSelector(selectOccupiedSpaces, equal);
|
|
|
|
|
/*
|
|
|
|
|
* If the parent has auto height enabled, or if the current widget is the MAIN_CONTAINER_WIDGET_ID
|
|
|
|
|
*/
|
|
|
|
|
const isParentAutoHeightEnabled = useSelector((state: AppState) => {
|
|
|
|
|
return parentId
|
2023-04-03 06:11:10 +00:00
|
|
|
? !isAutoHeightEnabledForWidgetWithLimits(
|
2023-02-03 05:47:40 +00:00
|
|
|
state.entities.canvasWidgets[parentId],
|
|
|
|
|
) &&
|
|
|
|
|
isAutoHeightEnabledForWidget(state.entities.canvasWidgets[parentId])
|
|
|
|
|
: false;
|
|
|
|
|
});
|
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
// Function which computes and updates the height of the dropTarget
|
|
|
|
|
// This is used in a context and hence in one of the children of this dropTarget
|
|
|
|
|
const updateDropTargetRows = (
|
|
|
|
|
widgetIdsToExclude: string[],
|
|
|
|
|
widgetBottomRow: number,
|
|
|
|
|
) => {
|
|
|
|
|
// Compute expected number of rows this drop target must have
|
|
|
|
|
const newRows = calculateDropTargetRows(
|
|
|
|
|
widgetIdsToExclude,
|
|
|
|
|
widgetBottomRow,
|
|
|
|
|
occupiedSpacesByChildren,
|
|
|
|
|
widgetId,
|
|
|
|
|
);
|
|
|
|
|
// If the current number of rows in the drop target is less
|
|
|
|
|
// than the expected number of rows in the drop target
|
|
|
|
|
if (rowRef.current < newRows) {
|
|
|
|
|
// Set the new value locally
|
|
|
|
|
rowRef.current = newRows;
|
|
|
|
|
// If the parent container like widget has auto height enabled
|
|
|
|
|
// We'd like to immediately update the parent's height
|
|
|
|
|
// based on the auto height computations
|
|
|
|
|
// This also updates any "dropTargets" that need to change height
|
|
|
|
|
// hence, this and the `updateHeight` function are mutually exclusive.
|
|
|
|
|
if (isParentAutoHeightEnabled && parentId) {
|
|
|
|
|
dispatch(updateDOMDirectlyBasedOnAutoHeightAction(parentId, newRows));
|
|
|
|
|
} else {
|
|
|
|
|
// Basically, we don't have auto height triggering, so the dropTarget height should be updated using
|
|
|
|
|
// the `updateHeight` function
|
|
|
|
|
// The difference here is that the `updateHeight` function only updates the "canvas" or the "dropTarget"
|
|
|
|
|
// and doesn't effect the parent container
|
|
|
|
|
|
|
|
|
|
// We can't update the height of the "Canvas" or "dropTarget" using this function
|
|
|
|
|
// in the previous if clause, because, there could be more "dropTargets" updating
|
|
|
|
|
// and this information can only be computed using auto height
|
2023-02-24 12:38:27 +00:00
|
|
|
|
2023-05-29 04:36:19 +00:00
|
|
|
if (!isAutoLayoutActive || !isListWidgetCanvas) {
|
|
|
|
|
updateHeight(dropTargetRef, rowRef.current);
|
|
|
|
|
}
|
2023-02-03 05:47:40 +00:00
|
|
|
}
|
|
|
|
|
return newRows;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
// memoizing context values
|
|
|
|
|
const contextValue = useMemo(() => {
|
|
|
|
|
return {
|
|
|
|
|
updateDropTargetRows,
|
|
|
|
|
};
|
|
|
|
|
}, [updateDropTargetRows, occupiedSpacesByChildren]);
|
|
|
|
|
|
|
|
|
|
/** EO PREPARE CONTEXT */
|
|
|
|
|
return { contextValue, dropTargetRef, rowRef };
|
2022-11-27 17:12:00 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
export function DropTargetComponent(props: DropTargetComponentProps) {
|
2022-11-27 17:12:00 +00:00
|
|
|
// Get if this is in preview mode.
|
|
|
|
|
const isPreviewMode = useSelector(previewModeSelector);
|
2023-03-23 11:41:58 +00:00
|
|
|
const isAppSettingsPaneWithNavigationTabOpen = useSelector(
|
|
|
|
|
getIsAppSettingsPaneWithNavigationTabOpen,
|
|
|
|
|
);
|
2023-05-11 04:45:14 +00:00
|
|
|
const appPositioningType: AppPositioningTypes = useSelector(
|
|
|
|
|
getCurrentAppPositioningType,
|
|
|
|
|
);
|
|
|
|
|
const isAutoLayoutActive = appPositioningType === AppPositioningTypes.AUTO;
|
2023-02-03 05:47:40 +00:00
|
|
|
const { contextValue, dropTargetRef, rowRef } = useUpdateRows(
|
2022-11-27 17:12:00 +00:00
|
|
|
props.bottomRow,
|
2023-02-03 05:47:40 +00:00
|
|
|
props.widgetId,
|
|
|
|
|
props.parentId,
|
2023-03-04 07:25:54 +00:00
|
|
|
props.mobileBottomRow,
|
|
|
|
|
props.isMobile,
|
|
|
|
|
isAutoLayoutActive,
|
2023-05-29 04:36:19 +00:00
|
|
|
props.isListWidgetCanvas,
|
2022-11-27 17:12:00 +00:00
|
|
|
);
|
2020-03-27 09:02:11 +00:00
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
// Are we currently resizing?
|
2020-01-20 09:00:37 +00:00
|
|
|
const isResizing = useSelector(
|
|
|
|
|
(state: AppState) => state.ui.widgetDragResize.isResizing,
|
2020-01-16 11:46:21 +00:00
|
|
|
);
|
2022-11-27 17:12:00 +00:00
|
|
|
// Are we currently dragging?
|
2020-02-18 19:56:58 +00:00
|
|
|
const isDragging = useSelector(
|
|
|
|
|
(state: AppState) => state.ui.widgetDragResize.isDragging,
|
|
|
|
|
);
|
2022-11-27 17:12:00 +00:00
|
|
|
// Are we changing the auto height limits by dragging the signifiers?
|
|
|
|
|
const { isAutoHeightWithLimitsChanging } = useAutoHeightUIState();
|
2020-01-16 11:46:21 +00:00
|
|
|
|
2023-02-24 12:38:27 +00:00
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
|
2021-08-12 05:45:38 +00:00
|
|
|
// dragDetails contains of info needed for a container jump:
|
|
|
|
|
// which parent the dragging widget belongs,
|
|
|
|
|
// which canvas is active(being dragged on),
|
|
|
|
|
// which widget is grabbed while dragging started,
|
|
|
|
|
// relative position of mouse pointer wrt to the last grabbed widget.
|
|
|
|
|
const dragDetails = useSelector(getDragDetails);
|
|
|
|
|
|
|
|
|
|
const { draggedOn } = dragDetails;
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
// All the widgets in this canvas
|
2021-08-02 11:16:50 +00:00
|
|
|
const childWidgets: string[] | undefined = useSelector(
|
|
|
|
|
(state: AppState) => state.entities.canvasWidgets[props.widgetId]?.children,
|
2020-01-16 11:46:21 +00:00
|
|
|
);
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
// This shows the property pane
|
2020-03-27 09:02:11 +00:00
|
|
|
const showPropertyPane = useShowPropertyPane();
|
2022-11-27 17:12:00 +00:00
|
|
|
|
2021-08-12 05:45:38 +00:00
|
|
|
const { deselectAll, focusWidget } = useWidgetSelection();
|
2022-11-27 17:12:00 +00:00
|
|
|
|
|
|
|
|
// Everytime we get a new bottomRow, or we toggle shouldScrollContents
|
|
|
|
|
// we call this effect
|
2020-03-27 09:02:11 +00:00
|
|
|
useEffect(() => {
|
2023-03-04 07:25:54 +00:00
|
|
|
const snapRows = getCanvasSnapRows(
|
|
|
|
|
props.bottomRow,
|
|
|
|
|
props.mobileBottomRow,
|
|
|
|
|
props.isMobile,
|
|
|
|
|
isAutoLayoutActive,
|
|
|
|
|
);
|
2023-02-03 05:47:40 +00:00
|
|
|
// If the current ref is not set to the new snaprows we've received (based on bottomRow)
|
|
|
|
|
if (rowRef.current !== snapRows && !isDragging && !isResizing) {
|
2022-01-13 13:21:57 +00:00
|
|
|
rowRef.current = snapRows;
|
2023-05-29 04:36:19 +00:00
|
|
|
if (!isAutoLayoutActive || !props.isListWidgetCanvas) {
|
|
|
|
|
updateHeight(dropTargetRef, snapRows);
|
|
|
|
|
}
|
2023-02-24 12:38:27 +00:00
|
|
|
|
|
|
|
|
// If we're done dragging, and the parent has auto height enabled
|
|
|
|
|
// It is possible that the auto height has not triggered yet
|
|
|
|
|
// because the user has released the mouse button but not placed the widget
|
|
|
|
|
// In these scenarios, the parent's height needs to be updated
|
|
|
|
|
// in the same way as the auto height would have done
|
|
|
|
|
if (props.parentId) {
|
|
|
|
|
dispatch(checkContainersForAutoHeightAction());
|
|
|
|
|
}
|
2021-08-12 05:45:38 +00:00
|
|
|
}
|
2023-03-04 07:25:54 +00:00
|
|
|
}, [
|
|
|
|
|
props.widgetId,
|
|
|
|
|
props.bottomRow,
|
|
|
|
|
props.mobileBottomRow,
|
|
|
|
|
props.isMobile,
|
|
|
|
|
props.parentId,
|
2023-05-29 04:36:19 +00:00
|
|
|
props.isListWidgetCanvas,
|
2023-03-04 07:25:54 +00:00
|
|
|
isDragging,
|
|
|
|
|
isResizing,
|
|
|
|
|
]);
|
2022-11-27 17:12:00 +00:00
|
|
|
|
2023-04-14 13:55:44 +00:00
|
|
|
const handleFocus = (e: React.MouseEvent<HTMLElement>) => {
|
2022-11-27 17:12:00 +00:00
|
|
|
// Making sure that we don't deselect the widget
|
|
|
|
|
// after we are done dragging the limits in auto height with limits
|
2023-04-14 13:55:44 +00:00
|
|
|
|
|
|
|
|
const selectionDiv = `div-selection-${MAIN_CONTAINER_WIDGET_ID}`;
|
|
|
|
|
const mainCanvasId = `canvas-selection-${MAIN_CONTAINER_WIDGET_ID}`;
|
|
|
|
|
const isTargetMainCanvas =
|
|
|
|
|
(e.target as HTMLDivElement).dataset.testid === selectionDiv ||
|
|
|
|
|
(e.target as HTMLDivElement).dataset.testid === mainCanvasId;
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
if (!isResizing && !isDragging && !isAutoHeightWithLimitsChanging) {
|
2023-04-14 13:55:44 +00:00
|
|
|
// Check if Target is the MainCanvas
|
|
|
|
|
if (isTargetMainCanvas) {
|
2022-11-27 17:12:00 +00:00
|
|
|
deselectAll();
|
|
|
|
|
focusWidget && focusWidget(props.widgetId);
|
|
|
|
|
showPropertyPane && showPropertyPane();
|
2023-04-14 13:55:44 +00:00
|
|
|
e.preventDefault();
|
|
|
|
|
} else {
|
|
|
|
|
// Prevent onClick from Bubbling out of the Canvas to the WidgetEditor for any other widget except the MainCanvas
|
|
|
|
|
e.stopPropagation();
|
2022-11-27 17:12:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-02-20 12:10:48 +00:00
|
|
|
// Get the height for the drop target
|
2023-02-03 05:47:40 +00:00
|
|
|
const height = `${rowRef.current * GridDefaults.DEFAULT_GRID_ROW_HEIGHT}px`;
|
2022-11-23 09:48:23 +00:00
|
|
|
|
|
|
|
|
const dropTargetStyles = {
|
2023-07-18 05:29:19 +00:00
|
|
|
height: props.isListWidgetCanvas ? (isDragging ? "100%" : "auto") : height,
|
2022-11-23 09:48:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const shouldOnboard =
|
|
|
|
|
!(childWidgets && childWidgets.length) && !isDragging && !props.parentId;
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
// The drag layer is the one with the grid dots.
|
|
|
|
|
// They need to show in certain scenarios
|
|
|
|
|
const showDragLayer =
|
|
|
|
|
((isDragging && draggedOn === props.widgetId) ||
|
|
|
|
|
isResizing ||
|
|
|
|
|
isAutoHeightWithLimitsChanging) &&
|
2023-03-04 07:25:54 +00:00
|
|
|
!isPreviewMode &&
|
2023-03-23 11:41:58 +00:00
|
|
|
!isAppSettingsPaneWithNavigationTabOpen &&
|
2023-03-04 07:25:54 +00:00
|
|
|
!props.useAutoLayout;
|
2022-11-27 17:12:00 +00:00
|
|
|
|
2023-04-14 13:55:44 +00:00
|
|
|
const isMainContainer = props.widgetId === MAIN_CONTAINER_WIDGET_ID;
|
|
|
|
|
|
2019-09-17 10:09:00 +00:00
|
|
|
return (
|
2021-07-23 06:40:39 +00:00
|
|
|
<DropTargetContext.Provider value={contextValue}>
|
2020-01-16 11:46:21 +00:00
|
|
|
<StyledDropTarget
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
className={`t--drop-target drop-target-${
|
|
|
|
|
props.parentId || MAIN_CONTAINER_WIDGET_ID
|
|
|
|
|
}`}
|
2023-04-14 13:55:44 +00:00
|
|
|
onClick={isMainContainer ? handleFocus : undefined}
|
2021-08-12 05:45:38 +00:00
|
|
|
ref={dropTargetRef}
|
2022-11-23 09:48:23 +00:00
|
|
|
style={dropTargetStyles}
|
2020-01-16 11:46:21 +00:00
|
|
|
>
|
|
|
|
|
{props.children}
|
2022-11-23 09:48:23 +00:00
|
|
|
{shouldOnboard && <Onboarding />}
|
2022-01-13 13:21:57 +00:00
|
|
|
{showDragLayer && (
|
2021-08-12 05:45:38 +00:00
|
|
|
<DragLayerComponent
|
|
|
|
|
noPad={props.noPad || false}
|
|
|
|
|
parentColumnWidth={props.snapColumnSpace}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2020-01-16 11:46:21 +00:00
|
|
|
</StyledDropTarget>
|
|
|
|
|
</DropTargetContext.Provider>
|
2019-09-17 10:09:00 +00:00
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2021-04-23 05:43:13 +00:00
|
|
|
|
2023-02-03 05:47:40 +00:00
|
|
|
export default DropTargetComponent;
|