From 6e1ffdcc72d78e7031d2696745d87c99cca30ab9 Mon Sep 17 00:00:00 2001
From: Deepak Singh <32263182+deepaksing@users.noreply.github.com>
Date: Wed, 5 Jul 2023 19:20:36 +0530
Subject: [PATCH] feat: Skeleton loading #404 (#458)
* feat: Skeleton loading #404
* fix: skeleton loading
* fix: skeleton loading
* feat: Skeleton loading #404
* fix: skeleton loading
* fix: skeleton loading
* Update CompanyPickerSkeleton.tsx
* updated changes
---
front/package.json | 1 +
front/src/index.tsx | 1 +
.../components/CompanyAccountOwnerPicker.tsx | 1 +
.../people/components/PeopleCompanyPicker.tsx | 1 +
.../components/SingleEntitySelect.tsx | 1 +
.../components/SingleEntitySelectBase.tsx | 42 ++++++-----
.../skeletons/CompanyPickerSkeleton.tsx | 31 ++++++++
.../DropdownMenuItemContainerSkeleton.tsx | 20 ++++++
.../hooks/useFilteredSearchEntityQuery.ts | 71 +++++++++++--------
front/yarn.lock | 5 ++
10 files changed, 126 insertions(+), 48 deletions(-)
create mode 100644 front/src/modules/relation-picker/components/skeletons/CompanyPickerSkeleton.tsx
create mode 100644 front/src/modules/relation-picker/components/skeletons/DropdownMenuItemContainerSkeleton.tsx
diff --git a/front/package.json b/front/package.json
index de66b1df4..c49c90d42 100644
--- a/front/package.json
+++ b/front/package.json
@@ -30,6 +30,7 @@
"react-datepicker": "^4.11.0",
"react-dom": "^18.2.0",
"react-hotkeys-hook": "^4.4.0",
+ "react-loading-skeleton": "^3.3.1",
"react-modal": "^3.16.1",
"react-router-dom": "^6.4.4",
"react-textarea-autosize": "^8.4.1",
diff --git a/front/src/index.tsx b/front/src/index.tsx
index 79c55f635..d42099078 100644
--- a/front/src/index.tsx
+++ b/front/src/index.tsx
@@ -14,6 +14,7 @@ import { UserProvider } from './providers/user/UserProvider';
import { App } from './App';
import './index.css';
+import 'react-loading-skeleton/dist/skeleton.css';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
diff --git a/front/src/modules/companies/components/CompanyAccountOwnerPicker.tsx b/front/src/modules/companies/components/CompanyAccountOwnerPicker.tsx
index 116c83f6c..cae334ded 100644
--- a/front/src/modules/companies/components/CompanyAccountOwnerPicker.tsx
+++ b/front/src/modules/companies/components/CompanyAccountOwnerPicker.tsx
@@ -59,6 +59,7 @@ export function CompanyAccountOwnerPicker({ company }: OwnProps) {
);
diff --git a/front/src/modules/relation-picker/components/SingleEntitySelect.tsx b/front/src/modules/relation-picker/components/SingleEntitySelect.tsx
index ddfbd5ac5..b8f49fe35 100644
--- a/front/src/modules/relation-picker/components/SingleEntitySelect.tsx
+++ b/front/src/modules/relation-picker/components/SingleEntitySelect.tsx
@@ -16,6 +16,7 @@ import { SingleEntitySelectBase } from './SingleEntitySelectBase';
export type EntitiesForSingleEntitySelect<
CustomEntityForSelect extends EntityForSelect,
> = {
+ loading: boolean;
selectedEntity: CustomEntityForSelect;
entitiesToSelect: CustomEntityForSelect[];
};
diff --git a/front/src/modules/relation-picker/components/SingleEntitySelectBase.tsx b/front/src/modules/relation-picker/components/SingleEntitySelectBase.tsx
index e7b8b361b..70b2b8d46 100644
--- a/front/src/modules/relation-picker/components/SingleEntitySelectBase.tsx
+++ b/front/src/modules/relation-picker/components/SingleEntitySelectBase.tsx
@@ -10,6 +10,9 @@ import { isDefined } from '@/utils/type-guards/isDefined';
import { useEntitySelectScroll } from '../hooks/useEntitySelectScroll';
+import { CompanyPickerSkeleton } from './skeletons/CompanyPickerSkeleton';
+import { DropdownMenuItemContainerSkeleton } from './skeletons/DropdownMenuItemContainerSkeleton';
+
export type EntitiesForSingleEntitySelect<
CustomEntityForSelect extends EntityForSelect,
> = {
@@ -50,24 +53,29 @@ export function SingleEntitySelectBase<
return (
- {entitiesInDropdown?.map((entity, index) => (
- onEntitySelected(entity)}
- >
-
- {entity.name}
-
- ))}
- {entitiesInDropdown?.length === 0 && (
+ {entities.loading ? (
+
+
+
+ ) : entitiesInDropdown.length === 0 ? (
No result
+ ) : (
+ entitiesInDropdown?.map((entity, index) => (
+ onEntitySelected(entity)}
+ >
+
+ {entity.name}
+
+ ))
)}
);
diff --git a/front/src/modules/relation-picker/components/skeletons/CompanyPickerSkeleton.tsx b/front/src/modules/relation-picker/components/skeletons/CompanyPickerSkeleton.tsx
new file mode 100644
index 000000000..dac861bdb
--- /dev/null
+++ b/front/src/modules/relation-picker/components/skeletons/CompanyPickerSkeleton.tsx
@@ -0,0 +1,31 @@
+import Skeleton from 'react-loading-skeleton';
+import styled from '@emotion/styled';
+
+type OwnProps = {
+ count: number;
+};
+
+export const SkeletonContainer = styled.div`
+ align-items: center;
+ display: inline-flex;
+ margin-bottom: ${({ theme }) => theme.spacing(1)};
+ position: relative;
+ width: 100%;
+`;
+
+export const SkeletonEntityName = styled.div`
+ margin-left: ${({ theme }) => theme.spacing(2)};
+ width: 100%;
+`;
+
+export function CompanyPickerSkeleton({ count }: OwnProps) {
+ const loadSkeletons = Array(count).fill(1);
+ return loadSkeletons.map((_, i) => (
+
+
+
+
+
+
+ ));
+}
diff --git a/front/src/modules/relation-picker/components/skeletons/DropdownMenuItemContainerSkeleton.tsx b/front/src/modules/relation-picker/components/skeletons/DropdownMenuItemContainerSkeleton.tsx
new file mode 100644
index 000000000..f84ce98b0
--- /dev/null
+++ b/front/src/modules/relation-picker/components/skeletons/DropdownMenuItemContainerSkeleton.tsx
@@ -0,0 +1,20 @@
+import styled from '@emotion/styled';
+
+export const DropdownMenuItemContainerSkeleton = styled.div`
+ --horizontal-padding: ${({ theme }) => theme.spacing(1.5)};
+ --vertical-padding: ${({ theme }) => theme.spacing(2)};
+
+ align-items: center;
+
+ border-radius: ${({ theme }) => theme.border.radius.sm};
+ color: ${({ theme }) => theme.font.color.secondary};
+
+ font-size: ${({ theme }) => theme.font.size.sm};
+
+ gap: ${({ theme }) => theme.spacing(2)};
+
+ height: calc(100% - 2 * var(--vertical-padding));
+
+ padding: var(--vertical-padding) var(--horizontal-padding);
+ width: calc(100% - 2 * var(--horizontal-padding));
+`;
diff --git a/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts b/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts
index dffd1b2db..13c0986fc 100644
--- a/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts
+++ b/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts
@@ -71,18 +71,19 @@ export function useFilteredSearchEntityQuery<
limit?: number;
searchFilter: string;
}): EntitiesForMultipleEntitySelect {
- const { data: selectedEntitiesData } = queryHook({
- variables: {
- where: {
- id: {
- in: selectedIds,
+ const { loading: selectedEntitiesLoading, data: selectedEntitiesData } =
+ queryHook({
+ variables: {
+ where: {
+ id: {
+ in: selectedIds,
+ },
},
- },
- orderBy: {
- [orderByField]: sortOrder,
- },
- } as QueryVariables,
- });
+ orderBy: {
+ [orderByField]: sortOrder,
+ },
+ } as QueryVariables,
+ });
const searchFilterByField = searchOnFields.map((field) => ({
[field]: {
@@ -91,7 +92,10 @@ export function useFilteredSearchEntityQuery<
},
}));
- const { data: filteredSelectedEntitiesData } = queryHook({
+ const {
+ loading: filteredSelectedEntitiesLoading,
+ data: filteredSelectedEntitiesData,
+ } = queryHook({
variables: {
where: {
AND: [
@@ -111,26 +115,27 @@ export function useFilteredSearchEntityQuery<
} as QueryVariables,
});
- const { data: entitiesToSelectData } = queryHook({
- variables: {
- where: {
- AND: [
- {
- OR: searchFilterByField,
- },
- {
- id: {
- notIn: selectedIds,
+ const { loading: entitiesToSelectLoading, data: entitiesToSelectData } =
+ queryHook({
+ variables: {
+ where: {
+ AND: [
+ {
+ OR: searchFilterByField,
},
- },
- ],
- },
- limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT,
- orderBy: {
- [orderByField]: sortOrder,
- },
- } as QueryVariables,
- });
+ {
+ id: {
+ notIn: selectedIds,
+ },
+ },
+ ],
+ },
+ limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT,
+ orderBy: {
+ [orderByField]: sortOrder,
+ },
+ } as QueryVariables,
+ });
return {
selectedEntities: (selectedEntitiesData?.searchResults ?? []).map(
@@ -142,5 +147,9 @@ export function useFilteredSearchEntityQuery<
entitiesToSelect: (entitiesToSelectData?.searchResults ?? []).map(
mappingFunction,
),
+ loading:
+ entitiesToSelectLoading ||
+ filteredSelectedEntitiesLoading ||
+ selectedEntitiesLoading,
};
}
diff --git a/front/yarn.lock b/front/yarn.lock
index 94352b3ce..ad6acc968 100644
--- a/front/yarn.lock
+++ b/front/yarn.lock
@@ -14507,6 +14507,11 @@ react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+react-loading-skeleton@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/react-loading-skeleton/-/react-loading-skeleton-3.3.1.tgz#cd6e3a626ee86c76a46c14e2379243f2f8834e1b"
+ integrity sha512-NilqqwMh2v9omN7LteiDloEVpFyMIa0VGqF+ukqp0ncVlYu1sKYbYGX9JEl+GtOT9TKsh04zCHAbavnQ2USldA==
+
react-modal@^3.16.1:
version "3.16.1"
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.1.tgz#34018528fc206561b1a5467fc3beeaddafb39b2b"