client/app/pages/dashboards/DashboardList.jsx (190 lines of code) (raw):
import React from "react";
import cx from "classnames";
import Button from "antd/lib/button";
import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession";
import Link from "@/components/Link";
import PageHeader from "@/components/PageHeader";
import Paginator from "@/components/Paginator";
import DynamicComponent from "@/components/DynamicComponent";
import { DashboardTagsControl } from "@/components/tags-control/TagsControl";
import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList";
import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource";
import { UrlStateStorage } from "@/components/items-list/classes/StateStorage";
import * as Sidebar from "@/components/items-list/components/Sidebar";
import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTable";
import useItemsListExtraActions from "@/components/items-list/hooks/useItemsListExtraActions";
import CreateDashboardDialog from "@/components/dashboards/CreateDashboardDialog";
import Layout from "@/components/layouts/ContentWithSidebar";
import { Dashboard } from "@/services/dashboard";
import { currentUser } from "@/services/auth";
import routes from "@/services/routes";
import DashboardListEmptyState from "./components/DashboardListEmptyState";
import "./dashboard-list.css";
const sidebarMenu = [
{
key: "all",
href: "dashboards",
title: "All Dashboards",
icon: () => <Sidebar.MenuIcon icon="zmdi zmdi-view-quilt" />,
},
{
key: "my",
href: "dashboards/my",
title: "My Dashboards",
icon: () => <Sidebar.ProfileImage user={currentUser} />,
},
{
key: "favorites",
href: "dashboards/favorites",
title: "Favorites",
icon: () => <Sidebar.MenuIcon icon="fa fa-star" />,
},
];
const listColumns = [
Columns.favorites({ className: "p-r-0" }),
Columns.custom.sortable(
(text, item) => (
<React.Fragment>
<Link className="table-main-title" href={item.url} data-test={`DashboardId${item.id}`}>
{item.name}
</Link>
<DashboardTagsControl
className="d-block"
tags={item.tags}
isDraft={item.is_draft}
isArchived={item.is_archived}
/>
</React.Fragment>
),
{
title: "Name",
field: "name",
width: null,
}
),
Columns.custom((text, item) => item.user.name, { title: "Created By", width: "1%" }),
Columns.dateTime.sortable({
title: "Created At",
field: "created_at",
width: "1%",
}),
];
function DashboardListExtraActions(props) {
return <DynamicComponent name="DashboardList.Actions" {...props} />;
}
function DashboardList({ controller }) {
const {
areExtraActionsAvailable,
listColumns: tableColumns,
Component: ExtraActionsComponent,
selectedItems,
} = useItemsListExtraActions(controller, listColumns, DashboardListExtraActions);
return (
<div className="page-dashboard-list">
<div className="container">
<PageHeader
title={controller.params.pageTitle}
actions={
currentUser.hasPermission("create_dashboard") ? (
<Button block type="primary" onClick={() => CreateDashboardDialog.showModal()}>
<i className="fa fa-plus m-r-5" aria-hidden="true" />
New Dashboard
</Button>
) : null
}
/>
<Layout>
<Layout.Sidebar className="m-b-0">
<Sidebar.SearchInput
placeholder="Search Dashboards..."
label="Search dashboards"
value={controller.searchTerm}
onChange={controller.updateSearch}
/>
<Sidebar.Menu items={sidebarMenu} selected={controller.params.currentPage} />
<Sidebar.Tags url="api/dashboards/tags" onChange={controller.updateSelectedTags} showUnselectAll />
</Layout.Sidebar>
<Layout.Content>
<div data-test="DashboardLayoutContent">
{controller.isLoaded && controller.isEmpty ? (
<DashboardListEmptyState
page={controller.params.currentPage}
searchTerm={controller.searchTerm}
selectedTags={controller.selectedTags}
/>
) : (
<React.Fragment>
<div className={cx({ "m-b-10": areExtraActionsAvailable })}>
<ExtraActionsComponent selectedItems={selectedItems} />
</div>
<div className="bg-white tiled table-responsive">
<ItemsTable
items={controller.pageItems}
loading={!controller.isLoaded}
columns={tableColumns}
orderByField={controller.orderByField}
orderByReverse={controller.orderByReverse}
toggleSorting={controller.toggleSorting}
/>
<Paginator
showPageSizeSelect
totalCount={controller.totalItemsCount}
pageSize={controller.itemsPerPage}
onPageSizeChange={itemsPerPage => controller.updatePagination({ itemsPerPage })}
page={controller.page}
onChange={page => controller.updatePagination({ page })}
/>
</div>
</React.Fragment>
)}
</div>
</Layout.Content>
</Layout>
</div>
</div>
);
}
DashboardList.propTypes = {
controller: ControllerType.isRequired,
};
const DashboardListPage = itemsList(
DashboardList,
() =>
new ResourceItemsSource({
getResource({ params: { currentPage } }) {
return {
all: Dashboard.query.bind(Dashboard),
my: Dashboard.myDashboards.bind(Dashboard),
favorites: Dashboard.favorites.bind(Dashboard),
}[currentPage];
},
getItemProcessor() {
return item => new Dashboard(item);
},
}),
() => new UrlStateStorage({ orderByField: "created_at", orderByReverse: true })
);
routes.register(
"Dashboards.List",
routeWithUserSession({
path: "/dashboards",
title: "Dashboards",
render: pageProps => <DashboardListPage {...pageProps} currentPage="all" />,
})
);
routes.register(
"Dashboards.Favorites",
routeWithUserSession({
path: "/dashboards/favorites",
title: "Favorite Dashboards",
render: pageProps => <DashboardListPage {...pageProps} currentPage="favorites" />,
})
);
routes.register(
"Dashboards.My",
routeWithUserSession({
path: "/dashboards/my",
title: "My Dashboards",
render: pageProps => <DashboardListPage {...pageProps} currentPage="my" />,
})
);