client/app/pages/groups/GroupsList.jsx (147 lines of code) (raw):

import React from "react"; import Button from "antd/lib/button"; import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import Link from "@/components/Link"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import Paginator from "@/components/Paginator"; import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { StateStorage } from "@/components/items-list/classes/StateStorage"; import LoadingState from "@/components/items-list/components/LoadingState"; import EmptyState from "@/components/items-list/components/EmptyState"; import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTable"; import CreateGroupDialog from "@/components/groups/CreateGroupDialog"; import DeleteGroupButton from "@/components/groups/DeleteGroupButton"; import wrapSettingsTab from "@/components/SettingsWrapper"; import Group from "@/services/group"; import { currentUser } from "@/services/auth"; import routes from "@/services/routes"; class GroupsList extends React.Component { static propTypes = { controller: ControllerType.isRequired, }; listColumns = [ Columns.custom( (text, group) => ( <div> <Link href={"groups/" + group.id}>{group.name}</Link> {group.type === "builtin" && <span className="label label-default m-l-10">built-in</span>} </div> ), { field: "name", width: null, } ), Columns.custom( (text, group) => ( <Button.Group> <Link.Button href={`groups/${group.id}`}>Members</Link.Button> {currentUser.isAdmin && <Link.Button href={`groups/${group.id}/data_sources`}>Data Sources</Link.Button>} </Button.Group> ), { width: "1%", className: "text-nowrap", } ), Columns.custom( (text, group) => { const canRemove = group.type !== "builtin"; return ( <DeleteGroupButton className="w-100" disabled={!canRemove} group={group} title={canRemove ? null : "Cannot delete built-in group"} onClick={() => this.onGroupDeleted()}> Delete </DeleteGroupButton> ); }, { width: "1%", className: "text-nowrap p-l-0", isAvailable: () => currentUser.isAdmin, } ), ]; createGroup = () => { CreateGroupDialog.showModal().onClose(group => Group.create(group).then(newGroup => navigateTo(`groups/${newGroup.id}`)) ); }; onGroupDeleted = () => { this.props.controller.updatePagination({ page: 1 }); this.props.controller.update(); }; render() { const { controller } = this.props; return ( <div data-test="GroupList"> {currentUser.isAdmin && ( <div className="m-b-15"> <Button type="primary" onClick={this.createGroup}> <i className="fa fa-plus m-r-5" aria-hidden="true" /> New Group </Button> </div> )} {!controller.isLoaded && <LoadingState className="" />} {controller.isLoaded && controller.isEmpty && <EmptyState className="" />} {controller.isLoaded && !controller.isEmpty && ( <div className="table-responsive"> <ItemsTable items={controller.pageItems} columns={this.listColumns} showHeader={false} context={this.actions} 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> )} </div> ); } } const GroupsListPage = wrapSettingsTab( "Groups.List", { permission: "list_users", title: "Groups", path: "groups", order: 3, }, itemsList( GroupsList, () => new ResourceItemsSource({ isPlainList: true, getRequest() { return {}; }, getResource() { return Group.query.bind(Group); }, }), () => new StateStorage({ orderByField: "name", itemsPerPage: 10 }) ) ); routes.register( "Groups.List", routeWithUserSession({ path: "/groups", title: "Groups", render: pageProps => <GroupsListPage {...pageProps} currentPage="groups" />, }) );