Skip to content

Commit

Permalink
added empty placeholder view for datasets dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
hotzenklotz committed May 17, 2023
1 parent 790a5bf commit 133c0d5
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 107 deletions.
93 changes: 91 additions & 2 deletions frontend/javascripts/dashboard/dataset_folder_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import { APIDatasetCompact, APIUser } from "types/api_flow_types";
import DatasetCollectionContextProvider, {
useDatasetCollectionContext,
} from "./dataset/dataset_collection_context";

import DatasetView from "./dataset_view";
import { Button, Card, Col, Row } from "antd";
import { Link } from "react-router-dom";
import * as Utils from "libs/utils";
import DatasetView, { DatasetAddButton, DatasetRefreshButton } from "./dataset_view";
import { DetailsSidebar } from "./folders/details_sidebar";
import { EditFolderModal } from "./folders/edit_folder_modal";
import { FolderTreeSidebar } from "./folders/folder_tree";
import features, { getDemoDatasetUrl } from "features";
import { RenderToPortal } from "oxalis/view/layouting/portal_utils";

type Props = {
user: APIUser;
Expand Down Expand Up @@ -70,6 +74,91 @@ function DatasetFolderViewInner(props: Props) {
);
}, [context.datasets]);

const renderNoDatasetsPlaceHolder = () => {
const openPublicDatasetCard = (
<Col span={7}>
<Card bordered={false} cover={<i className="drawing drawing-empty-list-public-gallery" />}>
<Card.Meta
title="Open a Demo Dataset"
description={
<>
<p>Check out a published community dataset to experience WEBKNOSSOS in action.</p>
<a href={getDemoDatasetUrl()} target="_blank" rel="noopener noreferrer">
<Button style={{ marginTop: 30 }}>Open a Community Dataset</Button>
</a>
</>
}
/>
</Card>
</Col>
);

const uploadPlaceholderCard = (
<Col span={7}>
<Card bordered={false} cover={<i className="drawing drawing-empty-list-dataset-upload" />}>
<Card.Meta
title="Upload & Import Dataset"
description={
<>
<p>
WEBKNOSSOS supports a variety of (remote){" "}
<a
href="https://docs.webknossos.org/webknossos/data_formats.html"
target="_blank"
rel="noreferrer"
>
file formats
</a>{" "}
and is also able to convert them when necessary.
</p>
<Link to="/datasets/upload">
<Button type="primary" style={{ marginTop: 30 }}>
Open Dataset Upload & Import
</Button>
</Link>
,
</>
}
/>
</Card>
</Col>
);

const adminHeader =
Utils.isUserAdminOrDatasetManager(props.user) || Utils.isUserTeamManager(props.user) ? (
<div
className="pull-right"
style={{
display: "flex",
}}
>
<DatasetRefreshButton context={context} />
<DatasetAddButton context={context} />
</div>
) : null;

return (
<React.Fragment>
<RenderToPortal portalId="dashboard-TabBarExtraContent">{adminHeader}</RenderToPortal>;
<Row
justify="center"
style={{
padding: "20px 50px 70px",
}}
align="middle"
gutter={32}
>
{features().isWkorgInstance ? openPublicDatasetCard : null}
{Utils.isUserAdminOrDatasetManager(props.user) ? uploadPlaceholderCard : null}
</Row>
</React.Fragment>
);
};

if (context.datasets.length === 0) {
return renderNoDatasetsPlaceHolder();
}

return (
<div
style={{
Expand Down
157 changes: 52 additions & 105 deletions frontend/javascripts/dashboard/dataset_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
Tooltip,
Alert,
Select,
Card,
} from "antd";
import {
LoadingOutlined,
Expand All @@ -29,7 +28,7 @@ import type { APIJob, APIDatasetCompact, APIUser, FolderItem } from "types/api_f
import DatasetTable from "dashboard/advanced_dataset/dataset_table";
import * as Utils from "libs/utils";
import { CategorizationSearch } from "oxalis/view/components/categorization_label";
import features, { getDemoDatasetUrl } from "features";
import features from "features";
import Persistence from "libs/persistence";
import { getJobs } from "admin/admin_rest_api";
import dayjs from "dayjs";
Expand All @@ -47,7 +46,6 @@ import { PricingEnforcedButton } from "components/pricing_enforcers";
import { PricingPlanEnum } from "admin/organization/pricing_plan_utils";
import { MenuProps } from "rc-menu";
import { ItemType } from "antd/lib/menu/hooks/useItems";
import Meta from "antd/lib/card/Meta";

type Props = {
user: APIUser;
Expand Down Expand Up @@ -115,6 +113,7 @@ function DatasetView(props: Props) {
getJobs().then((newJobs) => setJobs(newJobs));
}
}, []);

useEffect(() => {
let interval: ReturnType<typeof setInterval> | null = null;

Expand All @@ -126,6 +125,7 @@ function DatasetView(props: Props) {

return () => (interval != null ? clearInterval(interval) : undefined);
}, []);

useEffect(() => {
persistence.persist({
searchQuery: searchQuery || "",
Expand Down Expand Up @@ -164,10 +164,6 @@ function DatasetView(props: Props) {
);
}

const margin = {
marginRight: 5,
};

const createFilteringModeRadio = (key: DatasetFilteringMode, label: string) => (
<Radio
onChange={() => {
Expand Down Expand Up @@ -223,7 +219,6 @@ function DatasetView(props: Props) {
) : (
searchBox
);
const showLoadingIndicator = context.isLoading || context.isChecking;

const adminHeader = (
<div
Expand All @@ -234,37 +229,12 @@ function DatasetView(props: Props) {
>
{isUserAdminOrDatasetManagerOrTeamManager ? (
<React.Fragment>
<Tooltip
title={
showLoadingIndicator ? "Refreshing the dataset list." : "Refresh the dataset list."
}
>
<Dropdown.Button
menu={{ onClick: context.checkDatasets, items: refreshMenuItems }}
style={margin}
onClick={() => context.fetchDatasets()}
disabled={context.isChecking}
>
{showLoadingIndicator ? <LoadingOutlined /> : <ReloadOutlined />} Refresh
</Dropdown.Button>
</Tooltip>

<Link
to={
context.activeFolderId != null && (folder == null || folder.isEditable)
? `/datasets/upload?to=${context.activeFolderId}`
: "/datasets/upload"
}
style={margin}
>
<Button type="primary" icon={<PlusOutlined />}>
Add Dataset
</Button>
</Link>
<DatasetRefreshButton context={context} />
<DatasetAddButton context={context} />
{context.activeFolderId != null && (
<PricingEnforcedButton
disabled={folder != null && !folder.isEditable}
style={margin}
style={{ marginRight: 5 }}
icon={<PlusOutlined />}
onClick={() =>
context.activeFolderId != null &&
Expand Down Expand Up @@ -318,6 +288,44 @@ function DatasetView(props: Props) {
);
}

export function DatasetRefreshButton({ context }: { context: DatasetCollectionContextValue }) {
const showLoadingIndicator = context.isLoading || context.isChecking;

return (
<Tooltip
title={showLoadingIndicator ? "Refreshing the dataset list." : "Refresh the dataset list."}
>
<Dropdown.Button
menu={{ onClick: context.checkDatasets, items: refreshMenuItems }}
style={{ marginRight: 5 }}
onClick={() => context.fetchDatasets()}
disabled={context.isChecking}
>
{showLoadingIndicator ? <LoadingOutlined /> : <ReloadOutlined />} Refresh
</Dropdown.Button>
</Tooltip>
);
}

export function DatasetAddButton({ context }: { context: DatasetCollectionContextValue }) {
const { data: folder } = useFolderQuery(context.activeFolderId);

return (
<Link
to={
context.activeFolderId != null && (folder == null || folder.isEditable)
? `/datasets/upload?to=${context.activeFolderId}`
: "/datasets/upload"
}
style={{ marginRight: 5 }}
>
<Button type="primary" icon={<PlusOutlined />}>
Add Dataset
</Button>
</Link>
);
}

const SEARCH_OPTIONS = [
{ label: "Search everywhere", value: "everywhere" },
{ label: "Search current folder", value: "folder" },
Expand Down Expand Up @@ -485,85 +493,24 @@ function renderPlaceholder(
}

if (searchQuery) {
return searchQuery.length >= MINIMUM_SEARCH_QUERY_LENGTH ? "No datasets found." : null;
return searchQuery.length >= MINIMUM_SEARCH_QUERY_LENGTH
? "No datasets match your search."
: null;
}

const openPublicDatasetCard = (
<Col span={7}>
<Card bordered={false} cover={<i className="drawing drawing-empty-list-public-gallery" />}>
<Meta
title="Open a Demo Dataset"
description={
<>
<p>Check out a published community dataset to experience WEBKNOSSOS in action.</p>
<a href={getDemoDatasetUrl()} target="_blank" rel="noopener noreferrer">
<Button style={{ marginTop: 30 }}>Open a Community Dataset</Button>
</a>
</>
}
/>
</Card>
</Col>
);

const uploadPlaceholderCard = (
<Col span={7}>
<Card bordered={false} cover={<i className="drawing drawing-empty-list-dataset-upload" />}>
<Meta
title="Upload & Import Dataset"
description={
<>
<p>
WEBKNOSSOS supports a variety of (remote){" "}
<a
href="https://docs.webknossos.org/webknossos/data_formats.html"
target="_blank"
rel="noreferrer"
>
file formats
</a>{" "}
and is also able to convert them when necessary.
</p>
<Link to="/datasets/upload">
<Button type="primary" style={{ marginTop: 30 }}>
Open Dataset Upload & Import
</Button>
</Link>
,
</>
}
/>
</Card>
</Col>
);

const emptyListHintText = Utils.isUserAdminOrDatasetManager(user)
? "There are no datasets in this folder. Import one or move a dataset from another folder."
: "There are no datasets in this folder. Please ask an admin or dataset manager to import a dataset or to grant you permissions to add datasets to this folder.";

return (
<Row
justify="center"
<div
style={{
padding: "20px 50px 70px",
marginTop: 24,
textAlign: "center",
}}
align="middle"
>
<Col span={24}>
<Row gutter={32} justify="center" align="bottom">
{features().isWkorgInstance ? openPublicDatasetCard : null}
{Utils.isUserAdminOrDatasetManager(user) ? uploadPlaceholderCard : null}
</Row>
<div
style={{
marginTop: 24,
textAlign: "center",
}}
>
{emptyListHintText}
</div>
</Col>
</Row>
{emptyListHintText}
</div>
);
}

Expand Down

0 comments on commit 133c0d5

Please sign in to comment.