import React, { PureComponent } from 'react'; import { autoBindMethodsForReact } from 'class-autobind-decorator'; import { AUTOBIND_CFG } from '../../../common/constants'; import Modal, { ModalProps } from '../base/modal'; import ModalBody from '../base/modal-body'; import ModalHeader from '../base/modal-header'; import ModalFooter from '../base/modal-footer'; import Tree from '../export-requests/tree'; import { isRequest, Request } from '../../../models/request'; import { isRequestGroup, RequestGroup } from '../../../models/request-group'; import * as models from '../../../models'; import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request'; import { Child } from '../sidebar/sidebar-children'; export interface Node { doc: Request | GrpcRequest | RequestGroup; children: Node[]; collapsed: boolean; totalRequests: number; selectedRequests: number; } interface Props extends ModalProps { childObjects: Child[]; handleExportRequestsToFile: Function; } interface State { treeRoot: Node | null; } @autoBindMethodsForReact(AUTOBIND_CFG) class ExportRequestsModal extends PureComponent { modal: Modal | null = null; state: State = { treeRoot: null, } setModalRef(modal: Modal) { if (modal != null) { this.modal = modal; } } show() { this.modal?.show(); this.createTree(); } hide() { this.modal?.hide(); } handleExport() { const { treeRoot } = this.state; if (treeRoot == null || treeRoot.selectedRequests === 0) { return; } const exportedRequestIds = this.getSelectedRequestIds(treeRoot); this.props.handleExportRequestsToFile(exportedRequestIds); this.hide(); } getSelectedRequestIds(node: Node): string[] { const docIsRequest = isRequest(node.doc) || isGrpcRequest(node.doc); if (docIsRequest && node.selectedRequests === node.totalRequests) { return [node.doc._id]; } const requestIds: string[] = []; for (const child of node.children) { const reqIds = this.getSelectedRequestIds(child); requestIds.push(...reqIds); } return requestIds; } createTree() { const { childObjects } = this.props; const children: Node[] = childObjects.map(child => this.createNode(child)); const totalRequests = children .map(child => child.totalRequests) .reduce((acc, totalRequests) => acc + totalRequests, 0); // @ts-expect-error -- TSCONVERSION missing property const rootFolder: RequestGroup = { ...models.requestGroup.init(), _id: 'all', type: models.requestGroup.type, name: 'All requests', parentId: '', modified: 0, created: 0, }; this.setState({ treeRoot: { doc: rootFolder, collapsed: false, children: children, totalRequests: totalRequests, selectedRequests: totalRequests, // Default select all }, }); } createNode(item: Record): Node { const children: Node[] = item.children.map(child => this.createNode(child)); let totalRequests = children .map(child => child.totalRequests) .reduce((acc, totalRequests) => acc + totalRequests, 0); const docIsRequest = isRequest(item.doc) || isGrpcRequest(item.doc); if (docIsRequest) { totalRequests++; } return { doc: item.doc, collapsed: false, children: children, totalRequests: totalRequests, selectedRequests: totalRequests, // Default select all }; } handleSetRequestGroupCollapsed(requestGroupId: string, isCollapsed: boolean) { const { treeRoot } = this.state; if (treeRoot == null) { return; } const found = this.setRequestGroupCollapsed(treeRoot, isCollapsed, requestGroupId); if (!found) { return; } this.setState({ treeRoot: { ...treeRoot }, }); } handleSetItemSelected(itemId: string, isSelected: boolean) { const { treeRoot } = this.state; if (treeRoot == null) { return; } const found = this.setItemSelected(treeRoot, isSelected, itemId); if (!found) { return; } this.setState({ treeRoot: { ...treeRoot }, }); } setRequestGroupCollapsed(node: Node, isCollapsed: boolean, requestGroupId: string) { if (!isRequestGroup(node.doc)) { return false; } if (node.doc._id === requestGroupId) { node.collapsed = isCollapsed; return true; } for (const child of node.children) { const found = this.setRequestGroupCollapsed(child, isCollapsed, requestGroupId); if (found) { return true; } } return false; } setItemSelected(node: Node, isSelected: boolean, id?: string) { if (id == null || node.doc._id === id) { // Switch the flags of all children in this subtree. for (const child of node.children) { this.setItemSelected(child, isSelected); } node.selectedRequests = isSelected ? node.totalRequests : 0; return true; } for (const child of node.children) { const found = this.setItemSelected(child, isSelected, id); if (found) { node.selectedRequests = node.children .map(ch => ch.selectedRequests) .reduce((acc, selected) => acc + selected, 0); return true; } } return false; } render() { const { treeRoot } = this.state; const isExportDisabled = treeRoot != null ? treeRoot.selectedRequests === 0 : false; return ( Select Requests to Export
); } } export default ExportRequestsModal;