Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
feat: add infinite scroll for project lists and datasets in dashboard…
Browse files Browse the repository at this point in the history
… and setting pages (#225)

* adding-avatar-system

* pr-fixes

* pr-fixes

* refactored avatar component and styles

* add space in member list

* infinite-scroll

* merge-with-main

* merge-main

* resolve-conflicts

* resolve conflict2

* rc

* fix-lists

* fix-cli

* gql-schema

* fix-cli

* fix-cli

* f-c

* Delete yarn-1.22.17.cjs

* fixes

* Update src/components/molecules/Settings/SettingPage/index.tsx

Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>

* pr-comments-fix

* F-c

* i18n-queries

* queries

* Regen yarn-lock

* refactor gql provider

* Update package.json

* remove modified yarn lock

* project-list

* project-list

* Update src/components/molecules/Common/Header/index.tsx

Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>

* Update src/components/molecules/Settings/SettingPage/index.tsx

Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>

* Update src/components/organisms/Dashboard/hooks.ts

Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>

* Update src/components/organisms/Dashboard/hooks.ts

Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>

* Update src/components/organisms/Settings/ProjectList/hooks.ts

Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>

* pr-fixing

* refactor ProjectList component

* pr-fixes2

* pr-fixes3

* pr-fixes4

* pr-fixes5

* update translation

* remove old translations

Co-authored-by: nina992 <nouralali992@gmail.com>
Co-authored-by: KaWaite <kyle.waite@outlook.com>
Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>
Co-authored-by: lby <icesunex@hotmail.com>
Co-authored-by: rot1024 <aayhrot@gmail.com>
  • Loading branch information
6 people authored Jun 6, 2022
1 parent 99c378d commit 28d377b
Show file tree
Hide file tree
Showing 31 changed files with 683 additions and 255 deletions.
2 changes: 2 additions & 0 deletions i18next-parser.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ module.exports = {
locales: ["en", "ja"],
output: "src/i18n/translations/$LOCALE.yml",
input: ["src/**/*.{ts,tsx}"],
keySeparator: false,
createOldCatalogs: false,
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,4 @@
"use-debounce": "^7.0.1",
"use-file-input": "^1.0.0"
}
}
}
106 changes: 106 additions & 0 deletions src/components/atoms/TabSection/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { useEffect, useState } from "react";

import Text from "@reearth/components/atoms/Text";
import { styled, useTheme } from "@reearth/theme";

import Divider from "../Divider";

export type MenuAlignment = "left" | "top";

export interface Props<T extends string> {
className?: string;
children?: { [m in T]?: React.ReactNode };
headerAction?: React.ReactNode;
menuAlignment?: MenuAlignment;
scrollable?: boolean;
expandedMenuIcon?: boolean;
selected?: T;
initialSelected?: T;
onChange?: (m: T) => void;
headers?: { [m in T]?: string };
}
const TabSection = <T extends string>({
className,
children,
headerAction,
menuAlignment,
scrollable,
selected,
onChange,
initialSelected,
headers,
}: Props<T>) => {
const tabs: T[] = (Object.keys(children || {}) as T[]).filter(k => !!children?.[k]);
const [selectedTab, select] = useState<T | undefined>(initialSelected ?? tabs?.[0]);
useEffect(() => {
select(selected);
}, [selected]);

const theme = useTheme();

return (
<Wrapper className={className} menuAlignment={menuAlignment}>
<TabHeader>
{tabs?.map((m: T) => (
<TabTitle
key={m}
selected={selectedTab === m}
onClick={() => {
select(m);
onChange?.(m);
}}>
<Text size="m" color={selectedTab === m ? theme.main.select : theme.main.text}>
{headers?.[m] ?? m}
</Text>
</TabTitle>
))}
{<ActionWrapper expanded={true}>{headerAction}</ActionWrapper>}
</TabHeader>
<Divider margin="0" />
<TabContent scrollable={scrollable}>
{selectedTab ? children?.[selectedTab] ?? null : null}
</TabContent>
</Wrapper>
);
};
const Wrapper = styled.div<{ menuAlignment?: MenuAlignment }>`
display: flex;
flex-flow: ${({ menuAlignment }) => (menuAlignment === "top" ? "column" : "row")} nowrap;
justify-content: stretch;
position: relative;
`;
const TabHeader = styled.div<{ menuAlignment?: MenuAlignment }>`
display: flex;
flex-flow: ${({ menuAlignment }) => (menuAlignment === "top" ? "column" : "row")} nowrap;
align-items: space-between;
gap: 24px;
padding: 0px;
width: 100%;
height: 100%;
`;

const TabTitle = styled.div<{ selected?: boolean }>`
cursor: pointer;
user-select: none;
border-bottom: 2px solid ${({ selected, theme }) => (selected ? theme.main.select : "none")};
opacity: ${({ selected }) => (selected ? "1" : "0.7")};
`;

const ActionWrapper = styled.div<{ expanded?: boolean }>`
flex: ${props => (props.expanded ? "1" : null)};
display: flex;
flex-direction: row-reverse;
align-items: flex-start;
margin-block-start: -13px;
`;
const TabContent = styled.div<{ scrollable?: boolean }>`
flex: auto;
display: flex;
flex-flow: column nowrap;
justify-content: stretch;
overflow-x: hidden;
overflow-y: ${({ scrollable }) => (scrollable ? "auto" : "hidden")};
-webkit-overflow-scrolling: touch;
`;

export default TabSection;
10 changes: 0 additions & 10 deletions src/components/molecules/Common/AssetModal/AssetContainer/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ export type Asset = {
contentType: string;
};

function handleScroll(
{ currentTarget }: React.UIEvent<HTMLDivElement, UIEvent>,
onLoadMore?: () => void,
) {
if (currentTarget.scrollTop + currentTarget.clientHeight >= currentTarget.scrollHeight) {
onLoadMore?.();
}
}

export default ({
isMultipleSelectable,
selectedAssets,
Expand Down Expand Up @@ -112,7 +103,6 @@ export default ({
iconChoice,
deleteModalVisible,
sortOptions,
handleScroll,
setLayoutType,
handleUploadToAsset,
handleReverse,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from "react";
import { useIntl } from "react-intl";

import Button from "@reearth/components/atoms/Button";
import Divider from "@reearth/components/atoms/Divider";
Expand All @@ -9,8 +8,10 @@ import Loading from "@reearth/components/atoms/Loading";
import SearchBar from "@reearth/components/atoms/SearchBar";
import Text from "@reearth/components/atoms/Text";
import AssetDeleteModal from "@reearth/components/molecules/Common/AssetModal/AssetDeleteModal";
import { useT } from "@reearth/i18n";
import { styled } from "@reearth/theme";
import { metricsSizes } from "@reearth/theme/metrics";
import { handleScroll } from "@reearth/util/handleScroll";

import AssetCard from "../AssetCard";
import AssetListItem from "../AssetListItem";
Expand Down Expand Up @@ -73,13 +74,12 @@ const AssetContainer: React.FC<Props> = ({
onSortChange,
onSearch,
}) => {
const intl = useIntl();
const t = useT();
const {
layoutType,
iconChoice,
deleteModalVisible,
sortOptions,
handleScroll,
setLayoutType,
handleUploadToAsset,
handleReverse,
Expand All @@ -103,7 +103,7 @@ const AssetContainer: React.FC<Props> = ({
<Flex justify={onRemove ? "flex-end" : "center"}>
<Button
large
text={intl.formatMessage({ defaultMessage: "Upload file" })}
text={t("Upload file")}
icon="upload"
type="button"
buttonType={onRemove ? "secondary" : "primary"}
Expand All @@ -112,7 +112,7 @@ const AssetContainer: React.FC<Props> = ({
{onRemove && (
<Button
large
text={intl.formatMessage({ defaultMessage: "Delete" })}
text={t("Delete")}
icon="bin"
type="button"
buttonType="secondary"
Expand Down Expand Up @@ -159,13 +159,10 @@ const AssetContainer: React.FC<Props> = ({
<Template align="center" justify="center">
<TemplateText size="m" otherProperties={{ textAlign: "center" }}>
{searchTerm
? intl.formatMessage({
defaultMessage: "No assets match your search.",
})
: intl.formatMessage({
defaultMessage:
"You haven't uploaded any assets yet. Click the upload button above and select a compatible file from your computer.",
})}
? t("No assets match your search.")
: t(
"You haven't uploaded any assets yet. Click the upload button above and select a compatible file from your computer.",
)}
</TemplateText>
</Template>
) : (
Expand Down
6 changes: 3 additions & 3 deletions src/components/molecules/Common/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface Props {
onChangeTeam?: (teamId: string) => void;
modalShown?: boolean;
openModal?: () => void;
handleModalClose?: (r?: boolean | undefined) => void;
onModalClose?: (r?: boolean) => void;
dashboard?: boolean;
}

Expand All @@ -45,7 +45,7 @@ const Header: React.FC<Props> = ({
onChangeTeam,
modalShown,
openModal,
handleModalClose,
onModalClose,
dashboard,
}) => {
return (
Expand All @@ -69,7 +69,7 @@ const Header: React.FC<Props> = ({
/>
<WorkspaceCreationModal
open={modalShown}
onClose={handleModalClose}
onClose={onModalClose}
onSubmit={onCreateTeam}
/>
</>
Expand Down
28 changes: 25 additions & 3 deletions src/components/molecules/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
import React from "react";

import Loading from "@reearth/components/atoms/Loading";
import { styled } from "@reearth/theme";
import { handleScroll } from "@reearth/util/handleScroll";

export * from "./types";

export type Props = {
className?: string;
header?: React.ReactNode;
isLoading?: boolean;
hasMoreProjects?: boolean;
onGetMoreProjects?: () => void;
};

const Dashboard: React.FC<Props> = ({ className, header, children }) => {
const Dashboard: React.FC<Props> = ({
className,
header,
children,
isLoading,
hasMoreProjects,
onGetMoreProjects,
}) => {
return (
<Wrapper className={className}>
<Wrapper
className={className}
onScroll={e => {
!isLoading && hasMoreProjects && handleScroll(e, onGetMoreProjects);
}}>
{header}
<Content>{children}</Content>
<Content>
{children}
{isLoading && hasMoreProjects && <StyledLoading relative />}
</Content>
</Wrapper>
);
};
Expand All @@ -29,5 +48,8 @@ const Content = styled.div`
display: flex;
flex-wrap: wrap;
`;
const StyledLoading = styled(Loading)`
margin: 52px auto;
`;

export default Dashboard;
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export type Item = {

export type Props = {
items: Item[];
isLoading?: boolean;
hasMore?: boolean;
removeDatasetSchema?: (schemaId: string) => void;
onGetMoreDataSets?: () => void;
};

const DatasetList: React.FC<Props> = ({ items, removeDatasetSchema }) => {
Expand All @@ -27,6 +30,7 @@ const Wrapper = styled.div`
display: grid;
grid-template-columns: 250px 250px 250px;
grid-gap: 20px;
overflow: auto;
`;

export default DatasetList;
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,15 @@ const ProjectCell: React.FC<Props> = ({ project, onSelect }) => {
</Desc>
</DescriptionWrapper>
)}
<Public status={project.status} />
<StatusWrapper>
<Public status={project.status} size={"md"} />
{project.isArchived && (
<ArchiveStatus>
<StatusCircle />
<Text size={"m"}>Archived</Text>
</ArchiveStatus>
)}
</StatusWrapper>
</Wrapper>
</StyledWrapper>
);
Expand All @@ -73,6 +81,8 @@ const Wrapper = styled.div<{ isHover?: boolean }>`
cursor: pointer;
height: 100%;
background-color: ${props => (props.isHover ? props.theme.main.lightTransparentBg : "")};
border: 1px solid
${props => (props.isHover ? props.theme.main.select : props.theme.main.lightTransparentBg)};
display: flex;
flex-direction: column;
justify-content: space-between;
Expand All @@ -98,9 +108,30 @@ const Desc = styled(Text)`
overflow: hidden;
text-overflow: ellipsis;
`;
const StatusWrapper = styled.div`
display: flex;
flex-direction: row;
justify-content: flex-start;
margin: 8px;
`;

const Public = styled(PublicationStatus)`
color: ${props => props.theme.projectCell.description};
margin: 8px;
`;

const ArchiveStatus = styled.div`
display: flex;
align-items: center;
margin: auto ${metricsSizes["s"]}px auto ${metricsSizes["s"]}px;
`;

const StatusCircle = styled.div`
width: 9px;
height: 9px;
background: ${props => props.theme.notification.infoBg};
border-radius: 50px;
margin: auto ${metricsSizes["s"]}px auto 0;
`;

export default ProjectCell;
Loading

0 comments on commit 28d377b

Please sign in to comment.