/* * Copyright 2018 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import * as React from 'react'; import { DataList, DataListItem, DataListItemRow, DataListCell, DataListToggle, DataListContent, DataListItemCells, Level, LevelItem, Button, DataListAction, DataListActionVisibility, Dropdown, DropdownPosition, DropdownItem, KebabToggle } from '@patternfly/react-core'; import { css } from '@patternfly/react-styles'; import { Remove2Icon, RepositoryIcon, ShareAltIcon, EditAltIcon } from '@patternfly/react-icons'; import { HttpResponse } from '../../account-service/account.service'; import { AccountServiceContext } from '../../account-service/AccountServiceContext'; import { PermissionRequest } from "./PermissionRequest"; import { ShareTheResource } from "./ShareTheResource"; import { Permission, Resource } from "./resource-model"; import { Msg } from '../../widgets/Msg'; import { ResourcesTableState, ResourcesTableProps, AbstractResourcesTable } from './AbstractResourceTable'; import { EditTheResource } from './EditTheResource'; import { ContentAlert } from '../ContentAlert'; import EmptyMessageState from '../../widgets/EmptyMessageState'; import { ContinueCancelModal } from '../../widgets/ContinueCancelModal'; export interface CollapsibleResourcesTableState extends ResourcesTableState { isRowOpen: boolean[]; contextOpen: boolean[]; isModalActive: boolean; } export class ResourcesTable extends AbstractResourcesTable { static contextType = AccountServiceContext; context: React.ContextType; public constructor(props: ResourcesTableProps, context: React.ContextType) { super(props); this.context = context; this.state = { isRowOpen: [], contextOpen: [], isModalActive: false, permissions: new Map() } } private onToggle = (row: number): void => { const newIsRowOpen: boolean[] = this.state.isRowOpen; newIsRowOpen[row] = !newIsRowOpen[row]; if (newIsRowOpen[row]) this.fetchPermissions(this.props.resources.data[row], row); this.setState({ isRowOpen: newIsRowOpen }); }; private onContextToggle = (row: number, isOpen: boolean): void => { if (this.state.isModalActive) return; const data = this.props.resources.data; const contextOpen = this.state.contextOpen; contextOpen[row] = isOpen; if (isOpen) { const index = row > data.length ? row - data.length - 1 : row; this.fetchPermissions(data[index], index); } this.setState({ contextOpen }); } private fetchPermissions(resource: Resource, row: number): void { this.context!.doGet(`/resources/${resource._id}/permissions`) .then((response: HttpResponse) => { const newPermissions: Map = new Map(this.state.permissions); newPermissions.set(row, response.data || []); this.setState({ permissions: newPermissions }); }); } private removeShare(resource: Resource, row: number): Promise { const permissions = this.state.permissions.get(row)!.map(a => ({ username: a.username, scopes: [] })); return this.context!.doPut(`/resources/${resource._id}/permissions`, permissions) .then(() => { ContentAlert.success(Msg.localize('unShareSuccess')); }); } public render(): React.ReactNode { if (this.props.resources.data.length === 0) { return ( ); } return ( // invisible toggle allows headings to line up properly , , , ]} /> {this.props.resources.data.map((resource: Resource, row: number) => ( this.onToggle(row)} isExpanded={this.state.isRowOpen[row]} id={'resourceToggle-' + row} aria-controls="ex-expand1" /> , {this.getClientName(resource.client)} , {resource.shareRequests.length > 0 && this.fetchPermissions(resource, row)} > } ]} /> this.setState({ isModalActive: true })} toggle={ this.onContextToggle(row + this.props.resources.data.length + 1, isOpen)} />} isOpen={this.state.contextOpen[row + this.props.resources.data.length + 1]} dropdownItems={[ { this.setState({ isModalActive: false }, () => { this.onContextToggle(row + this.props.resources.data.length + 1, false); this.fetchPermissions(resource, row + this.props.resources.data.length + 1); }); }} > { (toggle: () => void) => ( ) } , { this.setState({ isModalActive: false }, () => { this.onContextToggle(row + this.props.resources.data.length + 1, false); this.fetchPermissions(resource, row + this.props.resources.data.length + 1); }); }} > { (toggle: () => void) => ( ) } , void) => ( )} modalTitle="unShare" modalMessage="unShareAllConfirm" onClose={() => this.setState({ isModalActive: false }, () => { this.onContextToggle(row + this.props.resources.data.length + 1, false); }) } onContinue={() => this.removeShare(resource, row) .then(() => this.fetchPermissions(resource, row + this.props.resources.data.length + 1))} /> ]} /> this.fetchPermissions(resource, row)} > { (toggle: () => void) => ( ) } this.onContextToggle(row, isOpen)} />} onSelect={() => this.setState({ isModalActive: true })} isOpen={this.state.contextOpen[row]} dropdownItems={[ { this.setState({ isModalActive: false }, () => { this.onContextToggle(row, false); this.fetchPermissions(resource, row); }); }} > { (toggle: () => void) => ( ) } , void) => ( )} modalTitle="unShare" modalMessage='unShareAllConfirm' onClose={() => this.setState({ isModalActive: false }, () => { this.onContextToggle(row, false); }) } onContinue={() => this.removeShare(resource, row).then(() => this.fetchPermissions(resource, row))} /> ]} /> {this.sharedWithUsersMessage(row)} ))} ); } }