Skip to content
Snippets Groups Projects
Commit c0ef15c8 authored by Ramesh Kumar's avatar Ramesh Kumar
Browse files

TMSS-473: Added 'Create Blueprint' features to Scheduling Unit list.

Added row selection feature for ViewTable component.
Added CustomDialog component to show confirmaton, warning, error and info messages.
parent 5dc70e51
Branches
Tags
1 merge request!288Resolve TMSS-473
import React, {useRef, useState } from "react"; import React, {useRef, useState } from "react";
import { useSortBy, useTable, useFilters, useGlobalFilter, useAsyncDebounce, usePagination } from 'react-table' import { useSortBy, useTable, useFilters, useGlobalFilter, useAsyncDebounce, usePagination, useRowSelect } from 'react-table'
import matchSorter from 'match-sorter' import matchSorter from 'match-sorter'
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
...@@ -15,13 +15,15 @@ import { Button } from "react-bootstrap"; ...@@ -15,13 +15,15 @@ import { Button } from "react-bootstrap";
import { InputNumber } from "primereact/inputnumber"; import { InputNumber } from "primereact/inputnumber";
let tbldata =[], filteredData = [] ; let tbldata =[], filteredData = [] ;
let selectedRows = [];
let isunittest = false; let isunittest = false;
let showTopTotal = true; let showTopTotal = true;
let showGlobalFilter = true; let showGlobalFilter = true;
let showColumnFilter = true; let showColumnFilter = true;
let allowColumnSelection = true; let allowColumnSelection = true;
let allowRowSelection = false;
let columnclassname =[]; let columnclassname =[];
let parentCallbackFunction; let parentCallbackFunction, parentCBonSelection;
// Define a default UI for filtering // Define a default UI for filtering
function GlobalFilter({ function GlobalFilter({
...@@ -406,6 +408,7 @@ const defaultColumn = React.useMemo( ...@@ -406,6 +408,7 @@ const defaultColumn = React.useMemo(
setHiddenColumns, setHiddenColumns,
gotoPage, gotoPage,
setPageSize, setPageSize,
selectedFlatRows,
} = useTable( } = useTable(
{ {
columns, columns,
...@@ -419,7 +422,8 @@ const defaultColumn = React.useMemo( ...@@ -419,7 +422,8 @@ const defaultColumn = React.useMemo(
useFilters, useFilters,
useGlobalFilter, useGlobalFilter,
useSortBy, useSortBy,
usePagination usePagination,
useRowSelect
); );
React.useEffect(() => { React.useEffect(() => {
setHiddenColumns( setHiddenColumns(
...@@ -479,6 +483,15 @@ const defaultColumn = React.useMemo( ...@@ -479,6 +483,15 @@ const defaultColumn = React.useMemo(
parentCallbackFunction(filteredData); parentCallbackFunction(filteredData);
} }
/* Select only rows than can be selected. This is required when ALL is selected */
selectedRows = _.filter(selectedFlatRows, selectedRow => { return (selectedRow.original.canSelect===undefined || selectedRow.original.canSelect)});
/* Take only the original values passed to the component */
selectedRows = _.map(selectedRows, 'original');
/* Callback the parent function if available to pass the selected records on selection */
if (parentCBonSelection) {
parentCBonSelection(selectedRows)
}
return ( return (
<> <>
<div id="block_container"> <div id="block_container">
...@@ -525,9 +538,11 @@ const defaultColumn = React.useMemo( ...@@ -525,9 +538,11 @@ const defaultColumn = React.useMemo(
/> />
} }
</div> </div>
{ showTopTotal && { showTopTotal && filteredData.length === data.length &&
<div className="total_records_top_label"> <label >Total records ({data.length})</label></div> <div className="total_records_top_label"> <label >Total records ({data.length})</label></div>
} }
{ showTopTotal && filteredData.length < data.length &&
<div className="total_records_top_label" ><label >Filtered {filteredData.length} from {data.length}</label></div>}
</div> </div>
<div className="tmss-table table_container"> <div className="tmss-table table_container">
...@@ -575,7 +590,10 @@ const defaultColumn = React.useMemo( ...@@ -575,7 +590,10 @@ const defaultColumn = React.useMemo(
</table> </table>
</div> </div>
<div className="pagination p-grid" > <div className="pagination p-grid" >
<div className="total_records_bottom_label" ><label >Total records ({data.length})</label></div> {filteredData.length === data.length &&
<div className="total_records_bottom_label" ><label >Total records ({data.length})</label></div>}
{filteredData.length < data.length &&
<div className="total_records_bottom_label" ><label >Filtered {filteredData.length} from {data.length}</label></div>}
<div> <div>
<Paginator rowsPerPageOptions={[10,25,50,100]} first={currentpage} rows={currentrows} totalRecords={rows.length} onPageChange={onPagination}></Paginator> <Paginator rowsPerPageOptions={[10,25,50,100]} first={currentpage} rows={currentrows} totalRecords={rows.length} onPageChange={onPagination}></Paginator>
</div> </div>
...@@ -612,12 +630,14 @@ function ViewTable(props) { ...@@ -612,12 +630,14 @@ function ViewTable(props) {
// Data to show in table // Data to show in table
tbldata = props.data; tbldata = props.data;
parentCallbackFunction = props.filterCallback; parentCallbackFunction = props.filterCallback;
parentCBonSelection = props.onRowSelection;
isunittest = props.unittest; isunittest = props.unittest;
columnclassname = props.columnclassname; columnclassname = props.columnclassname;
showTopTotal = props.showTopTotal===undefined?true:props.showTopTotal; showTopTotal = props.showTopTotal===undefined?true:props.showTopTotal;
showGlobalFilter = props.showGlobalFilter===undefined?true:props.showGlobalFilter; showGlobalFilter = props.showGlobalFilter===undefined?true:props.showGlobalFilter;
showColumnFilter = props.showColumnFilter===undefined?true:props.showColumnFilter; showColumnFilter = props.showColumnFilter===undefined?true:props.showColumnFilter;
allowColumnSelection = props.allowColumnSelection===undefined?true:props.allowColumnSelection; allowColumnSelection = props.allowColumnSelection===undefined?true:props.allowColumnSelection;
allowRowSelection = props.allowRowSelection===undefined?false:props.allowRowSelection;
// Default Header to show in table and other columns header will not show until user action on UI // Default Header to show in table and other columns header will not show until user action on UI
let defaultheader = props.defaultcolumns; let defaultheader = props.defaultcolumns;
let optionalheader = props.optionalcolumns; let optionalheader = props.optionalcolumns;
...@@ -632,6 +652,33 @@ function ViewTable(props) { ...@@ -632,6 +652,33 @@ function ViewTable(props) {
let defaultdataheader = Object.keys(defaultheader[0]); let defaultdataheader = Object.keys(defaultheader[0]);
let optionaldataheader = Object.keys(optionalheader[0]); let optionaldataheader = Object.keys(optionalheader[0]);
/* If allowRowSelection property is true for the component, add checkbox column as 1st column.
If the record has property to select, enable the checkbox */
if (allowRowSelection) {
columns.push({
Header: ({ getToggleAllRowsSelectedProps }) => { return (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} style={{width:'15px', height:'15px'}}/>
</div>
)},
id:'Select',
accessor: props.keyaccessor,
Cell: ({ row }) => { return (
<div>
{(row.original.canSelect===undefined || row.original.canSelect) &&
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} style={{width:'15px', height:'15px'}}/>
}
{row.original.canSelect===false &&
<input type="checkbox" checked={false} disabled style={{width:'15px', height:'15px'}}></input>
}
</div>
)},
disableFilters: true,
disableSortBy: true,
isVisible: defaultdataheader.includes(props.keyaccessor),
});
}
if(props.showaction === 'true') { if(props.showaction === 'true') {
columns.push({ columns.push({
Header: 'Action', Header: 'Action',
......
...@@ -16,26 +16,44 @@ export class CustomDialog extends Component { ...@@ -16,26 +16,44 @@ export class CustomDialog extends Component {
} }
render() { render() {
const isConfirmDialog = this.props.type==='confirmation'; const isConfirm = this.props.type.toLowerCase()==='confirmation';
const isWarning = this.props.type.toLowerCase()==='warning';
const isSuccess = this.props.type.toLowerCase()==='success';
// const isError = this.props.type.toLowerCase()==='error';
let iconClass = isConfirm?"pi-question-circle pi-warning":(isWarning?"pi-info-circle pi-warning": (isSuccess?"pi-check-circle pi-success":"pi-times-circle pi-danger"));
return ( return (
<div className="p-grid" data-testid="confirm_dialog"> <div className="p-grid" data-testid="confirm_dialog">
<Dialog header={this.props.header} visible={this.props.visible} style={{width: '25vw'}} inputId="confirm_dialog" <Dialog header={this.props.header} visible={this.props.visible} style={{width: this.props.width?this.props.width:'25vw'}}
inputId="confirm_dialog"
modal={true} onHide={this.props.onClose} modal={true} onHide={this.props.onClose}
footer={<div> footer={<div>
{isConfirmDialog && {/* Action buttons based on 'type' props. If 'actions' passed as props, then type is ignored */}
{!this.props.actions &&
<>
{isConfirm &&
<Button key="back" onClick={this.props.onCancel} label="No" /> <Button key="back" onClick={this.props.onCancel} label="No" />
} }
<Button key="submit" type="primary" onClick={this.props.onSubmit} label={isConfirmDialog?'Yes':'Ok'} /> <Button key="submit" type="primary" onClick={this.props.onSubmit?this.props.onSubmit:this.props.onClose} label={isConfirm?'Yes':'Ok'} />
</>
}
{/* Action button based on the 'actions' props */}
{this.props.actions && this.props.actions.map((action, index) => {
return (
<Button key={action.id} label={action.title} onClick={action.callback} />);
})}
</div> </div>
} > } >
<div className="p-grid"> <div className="p-grid">
<div className="col-lg-2 col-md-2 col-sm-2"> <div className="col-lg-2 col-md-2 col-sm-2">
<span style={{position: 'absolute', top: '50%', '-ms-transform': 'translateY(-50%)', transform: 'translateY(-50%)'}}> <span style={{position: 'absolute', top: '50%', '-ms-transform': 'translateY(-50%)', transform: 'translateY(-50%)'}}>
<i className="pi pi-question-circle pi-large pi-warning"></i> <i className={`pi pi-large ${iconClass}`}></i>
</span> </span>
</div> </div>
<div className="col-lg-10 col-md-10 col-sm-10"> <div className="col-lg-10 col-md-10 col-sm-10">
{this.props.message} {/* Display message passed */}
{this.props.message?this.props.message:""}
{/* Render subcomponent passed as function */}
{this.props.content?this.props.content():""}
</div> </div>
</div> </div>
</Dialog> </Dialog>
......
...@@ -42,7 +42,7 @@ export default ({ title, subTitle, actions, ...props}) => { ...@@ -42,7 +42,7 @@ export default ({ title, subTitle, actions, ...props}) => {
{(actions || []).map((action, index) =>{ {(actions || []).map((action, index) =>{
if (action.type === 'button') { if (action.type === 'button') {
return ( return (
<button className="p-link" key={index}> <button className="p-link" key={index} title={action.title || ''}>
<i className={`fa ${action.icon}`} <i className={`fa ${action.icon}`}
onMouseOver={(e) => onButtonMouseOver(e, action)} onMouseOver={(e) => onButtonMouseOver(e, action)}
onClick={(e) => onButtonClick(e, action)} /> onClick={(e) => onButtonClick(e, action)} />
......
...@@ -56,6 +56,8 @@ class SchedulingUnitList extends Component{ ...@@ -56,6 +56,8 @@ class SchedulingUnitList extends Component{
}], }],
defaultSortColumn: [{id: "Name", desc: false}], defaultSortColumn: [{id: "Name", desc: false}],
} }
this.onRowSelection = this.onRowSelection.bind(this);
this.reloadData = this.reloadData.bind(this);
} }
async getSchedulingUnitList () { async getSchedulingUnitList () {
...@@ -86,6 +88,7 @@ class SchedulingUnitList extends Component{ ...@@ -86,6 +88,7 @@ class SchedulingUnitList extends Component{
blueP['created_at'] = moment(blueP['created_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); blueP['created_at'] = moment(blueP['created_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss");
blueP['updated_at'] = moment(blueP['updated_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); blueP['updated_at'] = moment(blueP['updated_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss");
blueP.project = project.name; blueP.project = project.name;
blueP.canSelect = false;
return blueP; return blueP;
}); });
output.push(...blueprintdata); output.push(...blueprintdata);
...@@ -95,11 +98,13 @@ class SchedulingUnitList extends Component{ ...@@ -95,11 +98,13 @@ class SchedulingUnitList extends Component{
scheduleunit['created_at'] = moment(scheduleunit['created_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); scheduleunit['created_at'] = moment(scheduleunit['created_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss");
scheduleunit['updated_at'] = moment(scheduleunit['updated_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); scheduleunit['updated_at'] = moment(scheduleunit['updated_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss");
scheduleunit.project = project.name; scheduleunit.project = project.name;
scheduleunit.canSelect = true;
output.push(scheduleunit); output.push(scheduleunit);
} }
this.setState({ this.setState({
scheduleunit: output, isLoading: false scheduleunit: output, isLoading: false
}); });
this.selectedRows = [];
}) })
} }
} }
...@@ -109,6 +114,22 @@ class SchedulingUnitList extends Component{ ...@@ -109,6 +114,22 @@ class SchedulingUnitList extends Component{
} }
/**
* Callback function passed to ViewTable component to pass back the selected rows.
* @param {Array} selectedRows - Subset of data passed to the ViewTable component based on selection.
*/
onRowSelection(selectedRows) {
this.selectedRows = selectedRows;
}
/**
* Funtion to reload data. This function can be called from the implementing component.
*/
reloadData() {
this.setState({isLoading: true});
this.getSchedulingUnitList();
}
render(){ render(){
if (this.state.isLoading) { if (this.state.isLoading) {
return <AppLoader/> return <AppLoader/>
...@@ -139,6 +160,8 @@ class SchedulingUnitList extends Component{ ...@@ -139,6 +160,8 @@ class SchedulingUnitList extends Component{
paths={this.state.paths} paths={this.state.paths}
unittest={this.state.unittest} unittest={this.state.unittest}
tablename="scheduleunit_list" tablename="scheduleunit_list"
allowRowSelection={this.props.allowRowSelection}
onRowSelection = {this.onRowSelection}
/> />
:<div>No scheduling unit found </div> :<div>No scheduling unit found </div>
} }
......
...@@ -17,6 +17,7 @@ import Stations from './Stations'; ...@@ -17,6 +17,7 @@ import Stations from './Stations';
import { Redirect } from 'react-router-dom'; import { Redirect } from 'react-router-dom';
import { CustomDialog } from '../../layout/components/CustomDialog'; import { CustomDialog } from '../../layout/components/CustomDialog';
import { CustomPageSpinner } from '../../components/CustomPageSpinner'; import { CustomPageSpinner } from '../../components/CustomPageSpinner';
import { Growl } from 'primereact/components/growl/Growl';
class ViewSchedulingUnit extends Component{ class ViewSchedulingUnit extends Component{
constructor(props){ constructor(props){
...@@ -77,7 +78,7 @@ class ViewSchedulingUnit extends Component{ ...@@ -77,7 +78,7 @@ class ViewSchedulingUnit extends Component{
"Status":"filter-input-100" "Status":"filter-input-100"
}], }],
stationGroup: [], stationGroup: [],
dialog: {header: 'Confirm', detail: 'Blueprint(s) already exist for this Scheduling Unit. Do you want to create another one?'}, dialog: {header: 'Confirm', detail: 'Do you want to create a Scheduling Unit Blueprint?'},
dialogVisible: false dialogVisible: false
} }
this.actions = []; this.actions = [];
...@@ -153,7 +154,7 @@ class ViewSchedulingUnit extends Component{ ...@@ -153,7 +154,7 @@ class ViewSchedulingUnit extends Component{
if (this.props.match.params.type === 'draft') { if (this.props.match.params.type === 'draft') {
this.actions.unshift({icon: 'fa-edit', title: 'Click to edit', props : { pathname:`/schedulingunit/edit/${ this.props.match.params.id}`} this.actions.unshift({icon: 'fa-edit', title: 'Click to edit', props : { pathname:`/schedulingunit/edit/${ this.props.match.params.id}`}
}); });
this.actions.unshift({icon:'fa-stamp',title: '', type:'button', this.actions.unshift({icon:'fa-stamp', title: 'Create Blueprint', type:'button',
actOn:'click', props : { callback: this.checkAndCreateBlueprint}, actOn:'click', props : { callback: this.checkAndCreateBlueprint},
}); });
} else { } else {
...@@ -176,25 +177,36 @@ class ViewSchedulingUnit extends Component{ ...@@ -176,25 +177,36 @@ class ViewSchedulingUnit extends Component{
return ScheduleService.getSchedulingUnitBlueprintById(id) return ScheduleService.getSchedulingUnitBlueprintById(id)
} }
/**
* Checks if the draft scheduling unit has existing blueprints and alerts. If confirms to create, creates blueprint.
*/
checkAndCreateBlueprint() { checkAndCreateBlueprint() {
if (this.state.scheduleunit) { if (this.state.scheduleunit) {
let dialog = this.state.dialog;
if (this.state.scheduleunit.scheduling_unit_blueprints.length>0) { if (this.state.scheduleunit.scheduling_unit_blueprints.length>0) {
this.setState({dialogVisible: true}); dialog.detail = "Blueprint(s) already exist for this Scheduling Unit. Do you want to create another one?";
} else {
this.setState({dialogVisible: false});
this.createBlueprintTree();
} }
dialog.actions = [{id: 'yes', title: 'Yes', callback: this.createBlueprintTree},
{id: 'no', title: 'No', callback: this.closeDialog}];
this.setState({dialogVisible: true, dialog: dialog});
} }
} }
/**
* Funtion called to create blueprint on confirmation.
*/
createBlueprintTree() { createBlueprintTree() {
this.setState({dialogVisible: false, showSpinner: true}); this.setState({dialogVisible: false, showSpinner: true});
ScheduleService.createSchedulingUnitBlueprintTree(this.state.scheduleunit.id) ScheduleService.createSchedulingUnitBlueprintTree(this.state.scheduleunit.id)
.then(blueprint => { .then(blueprint => {
this.growl.show({severity: 'success', summary: 'Success', detail: 'Blueprint created successfully!'});
this.setState({showSpinner: false, redirect: `/schedulingunit/view/blueprint/${blueprint.id}`, isLoading: true}); this.setState({showSpinner: false, redirect: `/schedulingunit/view/blueprint/${blueprint.id}`, isLoading: true});
}); });
} }
/**
* Callback function to close the dialog prompted.
*/
closeDialog() { closeDialog() {
this.setState({dialogVisible: false}); this.setState({dialogVisible: false});
} }
...@@ -205,22 +217,7 @@ class ViewSchedulingUnit extends Component{ ...@@ -205,22 +217,7 @@ class ViewSchedulingUnit extends Component{
} }
return( return(
<> <>
{/*} <div className="p-grid"> <Growl ref={(el) => this.growl = el} />
<div className="p-col-10">
<h2>Scheduling Unit - Details </h2>
</div>
<div className="p-col-2">
<Link to={{ pathname: '/schedulingunit'}} title="Close"
style={{float:'right'}}>
<i className="fa fa-times" style={{marginTop: "10px", marginLeft: '5px'}}></i>
</Link>
<Link to={{ pathname: '/schedulingunit/edit', state: {id: this.state.scheduleunit?this.state.scheduleunit.id:''}}} title="Edit"
style={{float:'right'}}>
<i className="fa fa-edit" style={{marginTop: "10px"}}></i>
</Link>
</div>
</div> */
/*TMSS-363 Blueprint icon changes */}
<PageHeader location={this.props.location} title={'Scheduling Unit - Details'} <PageHeader location={this.props.location} title={'Scheduling Unit - Details'}
actions={this.actions}/> actions={this.actions}/>
{ this.state.isLoading ? <AppLoader/> :this.state.scheduleunit && { this.state.isLoading ? <AppLoader/> :this.state.scheduleunit &&
...@@ -309,7 +306,7 @@ class ViewSchedulingUnit extends Component{ ...@@ -309,7 +306,7 @@ class ViewSchedulingUnit extends Component{
} }
{/* Dialog component to show messages and get confirmation */} {/* Dialog component to show messages and get confirmation */}
<CustomDialog type="confirmation" visible={this.state.dialogVisible} <CustomDialog type="confirmation" visible={this.state.dialogVisible}
header={this.state.dialog.header} message={this.state.dialog.detail} header={this.state.dialog.header} message={this.state.dialog.detail} actions={this.state.dialog.actions}
onClose={this.closeDialog} onCancel={this.closeDialog} onSubmit={this.createBlueprintTree}></CustomDialog> onClose={this.closeDialog} onCancel={this.closeDialog} onSubmit={this.createBlueprintTree}></CustomDialog>
{/* Show spinner during backend API call */} {/* Show spinner during backend API call */}
<CustomPageSpinner visible={this.state.showSpinner} /> <CustomPageSpinner visible={this.state.showSpinner} />
......
import React, {Component} from 'react'; import React, {Component} from 'react';
import _ from 'lodash';
import SchedulingUnitList from './SchedulingUnitList'; import SchedulingUnitList from './SchedulingUnitList';
import PageHeader from '../../layout/components/PageHeader'; import PageHeader from '../../layout/components/PageHeader';
import { TieredMenu } from 'primereact/tieredmenu'; import { TieredMenu } from 'primereact/tieredmenu';
import { CustomDialog } from '../../layout/components/CustomDialog';
import { CustomPageSpinner } from '../../components/CustomPageSpinner';
import ScheduleService from '../../services/schedule.service';
import { Growl } from 'primereact/components/growl/Growl';
export class Scheduling extends Component { export class Scheduling extends Component {
constructor(props){ constructor(props){
...@@ -10,7 +16,8 @@ export class Scheduling extends Component { ...@@ -10,7 +16,8 @@ export class Scheduling extends Component {
scheduleunit: [], scheduleunit: [],
schedule_unit_task: [] , schedule_unit_task: [] ,
isLoading:false, isLoading:false,
redirect: '' redirect: '',
dialog: {header: 'Confirm', detail: 'Do you want to create blueprints for the selected drafts?'},
}; };
this.optionsMenu = React.createRef(); this.optionsMenu = React.createRef();
...@@ -18,6 +25,11 @@ export class Scheduling extends Component { ...@@ -18,6 +25,11 @@ export class Scheduling extends Component {
this.showOptionMenu = this.showOptionMenu.bind(this); this.showOptionMenu = this.showOptionMenu.bind(this);
this.selectOptionMenu = this.selectOptionMenu.bind(this); this.selectOptionMenu = this.selectOptionMenu.bind(this);
this.checkAndCreateBlueprint = this.checkAndCreateBlueprint.bind(this);
this.createBlueprintTree = this.createBlueprintTree.bind(this);
this.createBlueprintTreeNewOnly = this.createBlueprintTreeNewOnly.bind(this);
this.warningContent = this.warningContent.bind(this);
this.closeDialog = this.closeDialog.bind(this);
} }
showOptionMenu(event) { showOptionMenu(event) {
...@@ -36,20 +48,133 @@ export class Scheduling extends Component { ...@@ -36,20 +48,133 @@ export class Scheduling extends Component {
} }
} }
/**
* Subcomponet to display in the confirmation dialog.
*/
warningContent() {
const suListWithBlueprint = this.state.schedulingUnitsWithBlueprint;
const suListWithoutBlueprint = _.difference(this.suList.selectedRows, suListWithBlueprint);
return (
<>
{suListWithBlueprint && suListWithBlueprint.length>0 &&
<div>
<hr></hr>
<span>Blueprint(s) already exist for the following Scheduling Units. If you want to create a blueprint for all of them click yes. If you want to create a blue print for a subset click no to change your selection.</span>
<div className="p-grid" key={`dlg-msg-head`} style={{marginTop: '10px'}}>
<label className="col-lg-3">ID</label>
<label className="col-lg-9">Name</label>
</div>
{suListWithBlueprint.map((schedulingUnit, index) => (
<div className="p-grid" key={`dlg-msg-${index}`} style={{marginBottom: "5px"}}>
<span className="col-lg-3">{schedulingUnit.id}</span>
<span className="col-lg-9">{schedulingUnit.name}</span>
</div>
))}
</div>
}
{suListWithoutBlueprint && suListWithoutBlueprint.length>0 &&
<div>
<hr></hr>
<span>Selected Scheduling Unit drafts without blueprint are listed below.</span>
<div className="p-grid" key={`dlg-msg-head`} style={{marginTop: '10px'}}>
<label className="col-lg-3">ID</label>
<label className="col-lg-9">Name</label>
</div>
{suListWithoutBlueprint.map((schedulingUnit, index) => (
<div className="p-grid" key={`dlg-msg-${index}`} style={{marginBottom: "5px"}}>
<span className="col-lg-3">{schedulingUnit.id}</span>
<span className="col-lg-9">{schedulingUnit.name}</span>
</div>
))}
{suListWithBlueprint && suListWithBlueprint.length>0 &&
<span>If you want to create blueprints for only drafts without blueprints, click 'Create Only New'</span>
}
</div>
}
</>
);
}
/**
* Function to check if blueprint already exist for the selected Scheduling Units and propmt contfirmation dialog.
* When confirmed will create new blueprints for the selected Scheduling Units.
*/
checkAndCreateBlueprint() {
if (this.suList.selectedRows && this.suList.selectedRows.length>0) {
let dialog = this.state.dialog;
dialog.content = this.warningContent;
const schedulingUnitsWithBlueprint = _.filter(this.suList.selectedRows, schedulingUnit=> { return schedulingUnit.scheduling_unit_blueprints.length>0});
dialog.actions = [ {id:"yes", title: 'Yes', callback: this.createBlueprintTree},
{id:"no", title: 'No', callback: this.closeDialog} ]
/* Add this action only when both new and old drafts are selected */
if (schedulingUnitsWithBlueprint.length > 0 && this.suList.selectedRows.length>schedulingUnitsWithBlueprint.length) {
dialog.actions.unshift({id:"newOnly", title: 'Create Only New', callback: this.createBlueprintTreeNewOnly});
}
this.setState({dialogVisible: true, dialog: dialog, schedulingUnitsWithBlueprint: _.sortBy(schedulingUnitsWithBlueprint,['id'])});
} else {
this.growl.show({severity: 'info', summary: 'Select Row', detail: 'Please select one or more Scheduling Unit Draft(s)'});
}
}
/**
* Callback function from dialog to create blueprints for only new drafts without blueprints.
* @param {Event} event
*/
createBlueprintTreeNewOnly(event){
this.createBlueprintTree(event, true);
}
/**
* Function to create actual blueprints for the selected drafts
* @param {Event} event
* @param {Boolean} excludeOld
*/
async createBlueprintTree(event, excludeOld) {
this.setState({dialogVisible: false, showSpinner: true});
let selectedRows = this.suList.selectedRows;
// Remove old drafts from selected rows
if (excludeOld) {
selectedRows = _.difference(selectedRows, this.state.schedulingUnitsWithBlueprint);
}
for (const schedulingUnit of selectedRows) {
await ScheduleService.createSchedulingUnitBlueprintTree(schedulingUnit.id);
}
this.setState({showSpinner: false, schedulingUnitsWithBlueprint:null});
this.growl.show({severity: 'success', summary: 'Success', detail: 'Blueprint(s) created successfully!'});
this.suList.reloadData();
}
/**
* Callback function to close the dialog.
*/
closeDialog() {
this.setState({dialogVisible: false});
}
render() { render() {
return ( return (
<> <>
<Growl ref={(el) => this.growl = el} style={{paddingTop:"50px"}} />
<TieredMenu className="app-header-menu" model={this.menuOptions} popup ref={el => this.optionsMenu = el} /> <TieredMenu className="app-header-menu" model={this.menuOptions} popup ref={el => this.optionsMenu = el} />
<PageHeader location={this.props.location} title={'Scheduling Unit - List'} <PageHeader location={this.props.location} title={'Scheduling Unit - List'}
actions={[ actions={[
{icon:'fa-stamp', title: 'Create Blueprint', type:'button',
actOn:'click', props : { callback: this.checkAndCreateBlueprint}},
{icon: 'fa fa-plus-square', title: 'Add New Scheduling Unit', {icon: 'fa fa-plus-square', title: 'Add New Scheduling Unit',
props: {pathname: '/schedulingunit/create'}}, props: {pathname: '/schedulingunit/create'}},
{icon: 'fa fa-table', title: 'Add Scheduling Set', {icon: 'fa fa-table', title: 'Add Scheduling Set',
props: {pathname: '/schedulingset/schedulingunit/create'}}]} /> props: {pathname: '/schedulingset/schedulingunit/create'}}]} />
{this.state.scheduleunit && {this.state.scheduleunit &&
<SchedulingUnitList /> } <SchedulingUnitList allowRowSelection={true} ref={suList => {this.suList = suList}} /> }
{/* Dialog component to show messages and get confirmation */}
<CustomDialog type="confirmation" visible={this.state.dialogVisible} width="40vw"
header={this.state.dialog.header} message={this.state.dialog.detail} content={this.state.dialog.content}
onClose={this.closeDialog} onCancel={this.closeDialog} onSubmit={this.createBlueprintTree}
actions={this.state.dialog.actions}></CustomDialog>
{/* Show spinner during backend API call */}
<CustomPageSpinner visible={this.state.showSpinner} />
</> </>
); );
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment