diff --git a/SAS/TMSS/frontend/tmss_webapp/package.json b/SAS/TMSS/frontend/tmss_webapp/package.json index e312fe079c25e286cd21ff13946e04a86223ba4e..763056235c0ea383c9f43f8edc13af4fb919e224 100644 --- a/SAS/TMSS/frontend/tmss_webapp/package.json +++ b/SAS/TMSS/frontend/tmss_webapp/package.json @@ -5,6 +5,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.13.1", "@json-editor/json-editor": "^2.3.0", + "@tds/core-breadcrumbs": "^2.2.4", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", @@ -26,9 +27,12 @@ "react-app-polyfill": "^1.0.6", "react-bootstrap": "^1.0.1", "react-bootstrap-datetimepicker": "0.0.22", + "react-breadcrumbs": "^2.1.7", "react-dom": "^16.13.1", "react-frame-component": "^4.1.2", + "react-helmet": "^6.1.0", "react-json-view": "^1.19.1", + "react-loader-spinner": "^3.1.14", "react-router-dom": "^5.2.0", "react-scripts": "3.4.1", "react-table": "^7.2.1", @@ -44,7 +48,7 @@ "test": "react-scripts test", "eject": "react-scripts eject" }, - "proxy": "http://192.168.99.100:8008", + "proxy": "http://127.0.0.1:8008/", "eslintConfig": { "extends": "react-app" }, diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.js b/SAS/TMSS/frontend/tmss_webapp/src/App.js index 2d66c5389e376708c57ce8c7aac34e43e16d1398..3dfcf0e9d9bbdfb57ab35d90da3c93671d8e87ce 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/App.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/App.js @@ -7,15 +7,23 @@ import {AppMenu} from './layout/components/AppMenu'; import { AppFooter } from './layout/components/AppFooter'; import {RoutedContent} from './routes'; -// import {Dashboard} from './routes/dashboard/dashboard'; + +import { AppBreadcrumb } from "./layout/components/AppBreadcrumb"; +import { withRouter } from 'react-router'; + + //import {Dashboard} from './routes/dashboard/dashboard'; import 'primeicons/primeicons.css'; import 'primereact/resources/themes/nova-light/theme.css'; import 'primereact/resources/primereact.css'; import './layout/layout.scss'; +import 'primereact/resources/primereact.min.css'; +import 'primeflex/primeflex.css'; import './App.scss'; import './App.css'; + + class App extends Component { constructor() { @@ -28,6 +36,8 @@ class App extends Component { overlayMenuActive: false, mobileMenuActive: false, }; + + this.onWrapperClick = this.onWrapperClick.bind(this); this.onToggleMenu = this.onToggleMenu.bind(this); this.onSidebarClick = this.onSidebarClick.bind(this); @@ -38,10 +48,12 @@ class App extends Component { {label: 'Scheduling Units', icon: 'pi pi-fw pi-calendar', to:'/scheduling'}, {label: 'Tasks', icon: 'pi pi-fw pi-check-square', to:'/task'} ]; - + // this.menuComponent = {'Dashboard': Dashboard} } + + onWrapperClick(event) { if (!this.menuClick) { this.setState({ @@ -82,7 +94,11 @@ class App extends Component { this.menuClick = true; } onMenuItemClick(event) { - this.setState({currentMenu:event.item.label, currentPath: event.item.path}); + // console.log(event.item.label,event.item.to); + //this.setState({currentMenu:[{ label: event.item.label,url:event.item.to }],currentPath: event.item.path}); + + this.setState({currentMenu:event.item.label, currentPath: event.item.path}); + // this.setState({bmenu:{label:event.item.label, path: event.item.path}}); } isDesktop() { @@ -90,30 +106,50 @@ class App extends Component { } render() { - const wrapperClass = classNames('layout-wrapper', { 'layout-overlay': this.state.layoutMode === 'overlay', 'layout-static': this.state.layoutMode === 'static', 'layout-static-sidebar-inactive': this.state.staticMenuInactive && this.state.layoutMode === 'static', 'layout-overlay-sidebar-active': this.state.overlayMenuActive && this.state.layoutMode === 'overlay', - 'layout-mobile-sidebar-active': this.state.mobileMenuActive + 'layout-mobile-sidebar-active': this.state.mobileMenuActive + + }); + + const AppBreadCrumbWithRouter = withRouter(AppBreadcrumb); + // const items = [ + + + // { label: 'dashboard',url:'http://localhost:3001/Dashboard' }, + // { label: 'scheduling unit' ,url:'/scheduling' }, + // { label: 'cycle', url: 'http://localhost:3001/cycle' } + // ]; + + + // const home = { icon: 'pi pi-home', url: 'http://localhost:3001/Dashboard' } + + + return ( <React.Fragment> - <div className="App"> + <div className="App"> {/* <div className={wrapperClass} onClick={this.onWrapperClick}> */} <div className={wrapperClass}> - <AppTopbar onToggleMenu={this.onToggleMenu}></AppTopbar> - <Router basename={ this.state.currentPath }> - <AppMenu model={this.menu} onMenuItemClick={this.onMenuItemClick} /> - <div className="layout-main"> - <RoutedContent /> - </div> - </Router> - <AppFooter></AppFooter> - </div> - </div> - </React.Fragment> + <AppTopbar onToggleMenu={this.onToggleMenu}></AppTopbar> + <Router basename={ this.state.currentPath }> + <AppMenu model={this.menu} onMenuItemClick={this.onMenuItemClick} /> + <div className="layout-main"> + + <AppBreadCrumbWithRouter/> + + <RoutedContent /> + </div> + + </Router> + <AppFooter></AppFooter> + </div> + </div> + </React.Fragment> ); } } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppBreadcrumb.js b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppBreadcrumb.js new file mode 100644 index 0000000000000000000000000000000000000000..a53da637a7d131a92b573617ba5d6cedded7ab34 --- /dev/null +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppBreadcrumb.js @@ -0,0 +1,32 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import {Link} from 'react-router-dom'; + +export class AppBreadcrumb extends Component { + + static propTypes = { + match: PropTypes.object, + } + + renderSeparator() { + return ( + <li className="pi pi-chevron-right b-separator"></li> + ); + } + + render() { + const { location } = this.props; + const path = location.pathname === '/' ? [] : location.pathname.split('/').slice(1); + return ( + <div className="p-breadcrumb"> + <li className="pi b-home"><Link className="b-link pi pi-home" to="/"/></li> + {path.map((name, index) => ( + <li className="pi"> + {this.renderSeparator()} + {index != path.length - 1 ? <span className="b-link" onClick={this.props.history.goBack}>{name}</span> : name} + </li> + ))} + </div> + ); + } +} \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js index 51e3e785c404eb0517378faafebd259825e057df..c46698462cfea5aff95a48cbf167c56a0dfd736e 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; + import React, { Component } from 'react'; import {NavLink} from 'react-router-dom' import PropTypes from 'prop-types'; import classNames from 'classnames'; @@ -52,6 +52,7 @@ class AppSubmenu extends Component { } } + renderLinkContent(item) { let submenuIcon = item.items && <i className="pi pi-fw pi-angle-down menuitem-toggle-icon"></i>; let badge = item.badge && <span className="menuitem-badge">{item.badge}</span>; diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_breadcrumb.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_breadcrumb.scss new file mode 100644 index 0000000000000000000000000000000000000000..3c5e14dc9387d315c1d36bd4de4e12396ebaeaa7 --- /dev/null +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_breadcrumb.scss @@ -0,0 +1,85 @@ +.layout-wrapper .layout-main .layout-breadcrumb { + + background-color: #ffffff; + -webkit-box-shadow: inset 0 -2px 4px 0 rgba(0, 0, 0, 0.14); + -moz-box-shadow: inset 0 -2px 4px 0 rgba(0, 0, 0, 0.14); + box-shadow: inset 0 -2px 4px 0 rgba(0, 0, 0, 0.14); + min-height: 42px; + padding-top: 64px; +} +.layout-wrapper .layout-main .layout-breadcrumb:before, .layout-wrapper .layout-main .layout-breadcrumb:after { + content: ""; + display: table; +} +.layout-wrapper .layout-main .layout-breadcrumb:after { + clear: both; +} +.layout-wrapper .layout-main .layout-breadcrumb ul { + margin: 8px 0 0 0; + padding: 0 0 0 20px; + list-style: none; + color: #757575; + display: inline-block; +} +.layout-wrapper .layout-main .layout-breadcrumb ul li { + display: inline-block; + vertical-align: middle; + color: #757575; + text-transform: capitalize; +} +.layout-wrapper .layout-main .layout-breadcrumb ul li:first-child { + margin-right: 4px; +} +.layout-wrapper .layout-main .layout-breadcrumb ul li:first-child button { + margin-top: 2px; + font-size: 1em; +} +.layout-wrapper .layout-main .layout-breadcrumb ul li button { + display: inline-block; + color: #757575; +} +.layout-wrapper .layout-main .layout-breadcrumb .layout-breadcrumb-options { + float: right; + padding: 0px 20px 0 0; + height: 100%; +} +.layout-wrapper .layout-main .layout-breadcrumb .layout-breadcrumb-options button { + color: #757575; + display: inline-block; + width: 42px; + height: 42px; + line-height: 42px; + text-align: center; + cursor: pointer; + font-size: 1em; + -moz-transition: background-color 0.3s; + -o-transition: background-color 0.3s; + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; +} +.layout-wrapper .layout-main .layout-breadcrumb .layout-breadcrumb-options button:hover { + background-color: #e8e8e8; +} +.layout-wrapper .layout-main .layout-breadcrumb .layout-breadcrumb-options button i { + line-height: inherit; +} +.pi{ +text-transform: uppercase; +} +.b-link { + + font-size: 1.25rem; + color: #000; + cursor: pointer; + &:hover { + text-decoration: underline; + } +} +.b-separator { + font-size: 1rem !important; + margin: 0 5px; +} +.b-home { + position: relative; + top: 2px; +} diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_layout.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_layout.scss index b5182b1c58420ad500fc0cb48e1b85d4ef2ae393..76a1f2a1bfbe73bc562b84f0281cee3feab84369 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_layout.scss +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_layout.scss @@ -9,4 +9,5 @@ @import "./_footer"; @import "./_responsive"; @import "./_utils"; -@import "./_dashboard"; \ No newline at end of file +@import "./_dashboard"; +@import "./_breadcrumb"; \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_sidebar.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_sidebar.scss index cca2a830c7f57a18ff9687d8d98de016709c7aa5..dbbe701983ef0d4ff2243f82a7d2c30937180545 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_sidebar.scss +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_sidebar.scss @@ -28,4 +28,7 @@ background-color: $menuitemBadgeBgColor; @include border-radius(50%); } + .layout-breadcrumb { + padding-top: 108px; + } } \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Dashboard/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Dashboard/index.js index 174a7a7af740a2d36a804c4a2dc6759d9a106fea..a0a798161d65edf83901902a88e3957569741bd8 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Dashboard/index.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Dashboard/index.js @@ -1,5 +1,6 @@ import React, {Component} from 'react'; + export class Dashboard extends Component { constructor(props){ diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js index d7b118a645897188244666a1ac12206c5bf64ba9..f2dd1a9f9816abcbea863b9ad11e346c14df7cb7 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js @@ -1,7 +1,8 @@ import React, { Component } from 'react' import 'primeflex/primeflex.css'; import ViewTable from './../../components/ViewTable'; -import {getScheduling_Unit_Draft} from '../../services/ScheduleService' +import {getScheduling_Unit_Draft} from '../../services/ScheduleService'; +import Loader from 'react-loader-spinner'; class SchedulingUnitList extends Component{ @@ -10,20 +11,36 @@ class SchedulingUnitList extends Component{ this.state = { scheduleunit: [], paths: [{ - "View": "/schedulingunit/view", - }] + "View": "/scheduling/view", + }], + isLoading: false, } } componentDidMount(){ + this.setState({ isLoading: true }); getScheduling_Unit_Draft().then(scheduleunit =>{ this.setState({ - scheduleunit : scheduleunit.data + scheduleunit : scheduleunit.data ,isLoading: false }); }) } render(){ + const {isLoading } = this.state; + if (isLoading) { + return <div + style={{ + width: "100%", + height: "100", + display: "flex", + justifyContent: "center", + alignItems: "center" + }} + > + <Loader type="ThreeDots" color="#004B93" height={80} width={80} /> + </div> + } if(this.state.scheduleunit.results){ this.state.scheduleunit.results.forEach(item =>{ @@ -35,7 +52,10 @@ class SchedulingUnitList extends Component{ let defaultcolumns = [ {"name":"Name","description":"Description","created_at":"Created Date","updated_at":"Updated Date","requirements_template_id": "Template"}] return( <> - {/* + + { + + /* * Call View table to show table data, the parameters are, data - Pass API data defaultcolumns - This colum will be populate by default in table with header mentioned diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js index b890b01651899dc41059e2b3b7d593f433788b53..d739b1ccba384e5082ed28d655cc4ffe7552330d 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js @@ -1,9 +1,11 @@ + import React, { Component } from 'react' import {Link} from 'react-router-dom' import 'primeflex/primeflex.css'; import { Chips } from 'primereact/chips'; import ViewTable from './../../components/ViewTable'; -import {getScheduling_Unit_Draft_By_Id, getTasks_Draft_By_scheduling_Unit_Id} from '../../services/ScheduleService' +import {getScheduling_Unit_Draft_By_Id, getTasks_Draft_By_scheduling_Unit_Id} from '../../services/ScheduleService'; +import Loader from 'react-loader-spinner'; class ViewSchedulingUnit extends Component{ @@ -11,54 +13,100 @@ class ViewSchedulingUnit extends Component{ super(props) this.state = { scheduleunit: null, - schedule_unit_task: [], + schedule_unit_task: [], paths: [{ "View": "/task", - }] + }], + } } - componentDidMount(){ - let schedule_id = this.props.location.state.id - if (schedule_id) { - getScheduling_Unit_Draft_By_Id(schedule_id).then(scheduleunit =>{ - getTasks_Draft_By_scheduling_Unit_Id(scheduleunit.data.id).then(tasks =>{ - this.setState({ - scheduleunit : scheduleunit.data,schedule_unit_task : tasks.data.results - }); - }) - }) + componentDidMount(){ + + this.setState({ isLoading: true }); + let schedule_id = this.props.location.state.id; + + if (schedule_id) { + + getScheduling_Unit_Draft_By_Id(schedule_id).then(scheduleunit =>{ + getTasks_Draft_By_scheduling_Unit_Id(scheduleunit.data.id).then(tasks =>{ + this.setState({ + + scheduleunit : scheduleunit.data, + schedule_unit_task : tasks.data.results, + isLoading:false + + + + }); + + }); + + + }) + } } + render(){ + const {isLoading } = this.state; + + + if (this.state.schedule_unit_task.length>0) { + this.state.schedule_unit_task.forEach(item =>{ - delete item['specifications_doc'] + delete item['specifications_doc'] }); } + // Default column for Schedule Unit-Task Details // let defaultcolumns = [ {"id":"Task Identifier","name":"Task Name","description":"Task Description","created_at":"Created Date","updated_at":"Updated Date","requirements_template_id": "Requirement Temp"}] let defaultcolumns = [ {"id":"Task Identifier","name":"Task Name","description":"Task Description","created_at":"Created Date","updated_at":"Updated Date"}] + + + return( + <> + <div className="p-grid"> <div className="p-col-5"> <h2>Scheduling Unit - Details </h2> + </div> + <div className="p-col-1"> - <Link to={{ pathname: '/sheduling/edit', state: {id: this.state.scheduleunit?this.state.scheduleunit.id:''}}} tooltip="Edit" > + + <Link to={{ pathname: '/scheduling/edit', state: {id: this.state.scheduleunit?this.state.scheduleunit.id:''}}} tooltip="Edit" > <i className="fa fa-edit" style={{marginTop: "10px"}}></i> </Link> </div> </div> - - {this.state.scheduleunit && - <> - <div className="p-grid"> + + + { isLoading ? <div + style={{ + width: "100%", + height: "100", + display: "flex", + justifyContent: "center", + alignItems: "center" + }} + > + <Loader type="ThreeDots" color="#004B93" height={80} width={80} /> + </div>:this.state.scheduleunit + + + + && + <Loader type="ThreeDots" color="#004B93" height={80} width={80} /> && + <> + <div className="p-grid"> <label className="p-col-2">Name</label> <span className="p-col-4">{this.state.scheduleunit.name}</span> <label className="p-col-2">Description</label> @@ -76,7 +124,9 @@ class ViewSchedulingUnit extends Component{ <span className="p-col-4">{this.state.scheduleunit.tags}</span> </div> </> + } + <div style={{marginTop: '20px'}}> <h3>Tasks Details</h3> </div> @@ -87,12 +137,30 @@ class ViewSchedulingUnit extends Component{ showaction - {true/false} -> to show the action column paths - specify the path for navigation - Table will set "id" value for each row in action button */} - {this.state.schedule_unit_task.length>0 && - <ViewTable - data={this.state.schedule_unit_task} + + + + + {isLoading ? <div + style={{ + width: "100%", + height: "100", + display: "flex", + justifyContent: "center", + alignItems: "center" + }} + > + <Loader type="ThreeDots" color="#004B93" height={80} width={80} /> + </div>:this.state.schedule_unit_task.length>0 + + && + <ViewTable + + data ={this.state.schedule_unit_task} defaultcolumns={defaultcolumns} showaction="true" paths={this.state.paths} + /> } </> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js index 886fd7a544c90aafa55362200812dca83129a145..64cfd584bafc3f77dea7906ed3bb1e68d7f1009b 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js @@ -1,23 +1,28 @@ import React, {Component} from 'react'; -import SchedulingUnitList from './SchedulingUnitList' +import SchedulingUnitList from './SchedulingUnitList'; + + + export class Scheduling extends Component { constructor(props){ super(props) this.state = { scheduleunit: [], - schedule_unit_task: [] + schedule_unit_task: [] , + isLoading:false } } render() { + return ( <> <h2>Scheduling Unit - List</h2> - {this.state.scheduleunit && - <SchedulingUnitList /> - } - </> + + {this.state.scheduleunit && + <SchedulingUnitList /> } + </> ); } } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js index 52c91365f5b166f13fd6d759eb445adc0aa3270d..9e923b6e55883d17f8d9544f74d48002d795c23b 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js @@ -11,6 +11,7 @@ import { Button } from 'primereact/button'; import Jeditor from '../../components/JSONEditor/JEditor'; import TaskService from '../../services/task.services'; +import Loader from 'react-loader-spinner'; export class TaskEdit extends Component { templateOutput = {}; // id: selectedTemplateId, output: values enetered in the editor form @@ -29,7 +30,8 @@ export class TaskEdit extends Component { taskTemplates:[], validEditor: false, validForm: false, - errors: {} + errors: {}, + isLoading: false }; this.formRules = { name: {required: true, message: "Name can not be empty"}, @@ -83,12 +85,15 @@ export class TaskEdit extends Component { * @param {Number} templateId */ changeTaskTemplate(templateId) { + const template = _.find(this.state.taskTemplates, {'id': templateId}); let task = this.state.task; task.specifications_template_id = templateId; + task.specifications_template = template.url; this.setState({taskSchema: null}); this.setState({task: task, taskSchema: template.schema}); + this.state.editorFunction(); } @@ -123,47 +128,53 @@ export class TaskEdit extends Component { TaskService.updateTask("draft", task) .then( (taskDraft) => { if (taskDraft) { - this.setState({redirect: '/task/view'}); + this.setState({redirect: '/Task/View'}); } }); } cancelEdit() { - this.setState({redirect: '/task/view'}); + this.setState({redirect: '/Task/View'}); } componentDidMount() { + this.setState({ isLoading: true }); TaskService.getTaskTemplates() .then((templates) => { - this.setState({taskTemplates: templates}); + this.setState({taskTemplates: templates,isLoading: false}); }); TaskService.getTaskDetails("draft", this.props.taskId?this.props.taskId:this.props.location.state.taskId) .then((task) => { if (task) { TaskService.getSchedulingUnit("draft", task.scheduling_unit_draft_id) .then((schedulingUnit) => { - this.setState({schedulingUnit: schedulingUnit}); + this.setState({schedulingUnit: schedulingUnit,isLoading: false}); }); this.templateOutput[task.specifications_template_id] = task.specifications_doc; TaskService.getTaskTemplate(task.specifications_template_id) .then((taskTemplate) => { - this.setState({task: task, taskSchema: taskTemplate.schema}); + this.setState({task: task, taskSchema: taskTemplate.schema,isLoading: false}); }); } else { - this.setState({redirect: "/not-found"}); + this.setState({redirect: "/Not-found"}); } }); } render() { + if (this.state.redirect) { return <Redirect to={ {pathname: this.state.redirect, state: {id: this.state.task.id}} }></Redirect> } + const { isLoading } = this.state; + const taskSchema = this.state.taskSchema; + let jeditor = null; if (this.state.taskSchema) { + jeditor = React.createElement(Jeditor, {title: "Specification", schema: taskSchema, //initValue: this.state.templateOutput[this.state.task.specifications_template_id], @@ -185,7 +196,20 @@ export class TaskEdit extends Component { </Link> </div> </div> + + {isLoading ? <div + style={{ + width: "100%", + height: "100", + display: "flex", + justifyContent: "center", + alignItems: "center" + }} + > + <Loader type="ThreeDots" color="#004B93" height={80} width={80} /> + </div>: <div> + <div className="p-fluid"> <div className="p-field p-grid"> <label htmlFor="taskName" className="col-lg-2 col-md-2 col-sm-12">Name <span style={{color:'red'}}>*</span></label> @@ -242,12 +266,17 @@ export class TaskEdit extends Component { </div> </div> + </div> + } + + <div className="p-fluid"> <div className="p-grid"><div className="p-col-12"> {this.state.taskSchema?jeditor:""} </div></div> </div> + <div className="p-grid p-justify-start"> <div className="p-col-1"> <Button label="Save" className="p-button-primary" icon="pi pi-check" onClick={this.saveTask} disabled={!this.state.validEditor || !this.state.validForm} /> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js index d7e2c03a6532dbb07064d9ca603f5796bbedd986..5b28c75cd2a846353bd878a4f7debf406680c053 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js @@ -1,4 +1,4 @@ -import {TaskEdit} from './edit'; -import {TaskView} from './view'; +import {TaskEdit} from './Edit'; +import {TaskView} from './View'; export {TaskEdit, TaskView} ; diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js index e33bcdb5c5945961622585eb8ebfaffc75f43cd3..dc193c196b028f03b1cb892d772b326b8c686f28 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js @@ -3,6 +3,8 @@ import {Link, Redirect} from 'react-router-dom' import moment from 'moment'; import Jeditor from '../../components/JSONEditor/JEditor'; +import Loader from 'react-loader-spinner'; + import TaskService from '../../services/task.services'; import { Chips } from 'primereact/chips'; @@ -12,6 +14,7 @@ export class TaskView extends Component { constructor(props) { super(props); this.state = { + isLoading: false }; this.setEditorFunction = this.setEditorFunction.bind(this); if (this.props.match.params.id) { @@ -23,6 +26,7 @@ export class TaskView extends Component { } static getDerivedStateFromProps(nextProps, prevstate){ + if (prevstate.task && nextProps.location.state && (nextProps.location.state.taskId === prevstate.task.id || nextProps.location.state.taskType === prevstate.taskType)) { @@ -32,20 +36,26 @@ export class TaskView extends Component { } componentDidUpdate(prevProps, prevState) { + if (this.state.task && this.props.location.state && (this.state.task.id !== this.props.location.state.taskId || this.state.taskType !== this.props.location.state.taskType)) { + this.getTaskDetails(this.props.location.state.taskId, this.props.location.state.taskType); + } } componentDidMount() { + const taskId = this.props.location.state?this.props.location.state.id:this.state.taskId; let taskType = this.props.location.state?this.props.location.state.type:this.state.taskType; taskType = taskType?taskType:'draft'; if (taskId && taskType) { + this.setState({ isLoading: true }); this.getTaskDetails(taskId, taskType); } else { + this.setState({redirect: "/not-found"}); } } @@ -55,6 +65,7 @@ export class TaskView extends Component { * @param {Function} editorFunction */ setEditorFunction(editorFunction) { + this.setState({editorFunction: editorFunction}); } @@ -63,21 +74,29 @@ export class TaskView extends Component { * @param {number} taskId */ getTaskDetails(taskId, taskType) { + if (taskId) { + taskType = taskType?taskType:'draft'; + TaskService.getTaskDetails(taskType, taskId) + .then((task) => { + if (task) { + TaskService.getSchedulingUnit(taskType, (taskType==='draft'?task.scheduling_unit_draft_id:task.scheduling_unit_blueprint_id)) .then((schedulingUnit) => { - this.setState({schedulingUnit: schedulingUnit}); + this.setState({schedulingUnit: schedulingUnit,isLoading:false}); }); TaskService.getTaskTemplate(task.specifications_template_id) .then((taskTemplate) => { + if (this.state.editorFunction) { + this.state.editorFunction(); } - this.setState({task: task, taskTemplate: taskTemplate, taskType: taskType}); + this.setState({task: task, taskTemplate: taskTemplate, taskType: taskType,isLoading:false}); }); } else { @@ -88,22 +107,33 @@ export class TaskView extends Component { } render() { + const { isLoading } = this.state; + if (this.state.redirect) { return <Redirect to={ {pathname: this.state.redirect} }></Redirect> } + let jeditor = null + + if (this.state.taskTemplate) { - jeditor = React.createElement(Jeditor, {title: "Specification", - schema: this.state.taskTemplate.schema, + + + jeditor = React.createElement(Jeditor, {title: "Specification", + schema: this.state.taskTemplate.schema, initValue: this.state.task.specifications_doc, disabled: true, + // callback: this.setEditorOutput, - parentFunction: this.setEditorFunction + parentFunction: this.setEditorFunction, + }); } + // Child component to render predecessors and successors list const TaskRelationList = ({ list }) => ( + <ul className="task-list"> {list && list.map(item => ( <li key={item.id}> @@ -112,8 +142,8 @@ export class TaskView extends Component { ))} </ul> ); - return ( - <React.Fragment> + return ( + <React.Fragment> <div className="p-grid"> <div className="p-col-10 p-lg-3 p-md-4"> <h2>Task - Details </h2> @@ -129,7 +159,17 @@ export class TaskView extends Component { } </div> </div> - { this.state.task && + { isLoading ? <div + style={{ + width: "100%", + height: "100", + display: "flex", + justifyContent: "center", + alignItems: "center" + }} + > + <Loader type="ThreeDots" color="#004B93" height={80} width={80} /> + </div>:this.state.task && <React.Fragment> <div className="main-content"> <div className="p-grid"> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js index c2ed5db0bf2a288c04804a01af9be64bac421517..12ee27690208122a40b4863c8d64f62295be2b76 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js @@ -2,7 +2,8 @@ import React from 'react'; import { Route, Switch, - Redirect + Redirect, + } from 'react-router-dom'; import {NotFound} from '../layout/components/NotFound'; @@ -13,16 +14,17 @@ import ViewSchedulingUnit from './Scheduling/ViewSchedulingUnit' export const RoutedContent = () => { return ( + <Switch> <Redirect from="/" to="/" exact /> - <Route path="/not-found" exact component= {NotFound} /> + <Route path="/not-found" exact component= {NotFound} /> <Route path="/dashboard" exact component={Dashboard} /> <Route path="/scheduling" exact component={Scheduling} /> <Route path="/task" exact component={TaskView} /> <Route path="/task/view" exact component={TaskView} /> <Route path="/task/view/:type/:id" exact component={TaskView} /> <Route path="/task/edit" exact component={TaskEdit} /> - <Route path="/schedulingunit/view" exact component={ViewSchedulingUnit} /> + <Route path="/scheduling/view" exact component={ViewSchedulingUnit} /> </Switch> ); } \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/ScheduleService.js b/SAS/TMSS/frontend/tmss_webapp/src/services/ScheduleService.js index 4d06342047389af3579698288dfba8ce0e307342..d2d5285744fd955b4ea115424a322b3be51976cf 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/ScheduleService.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/ScheduleService.js @@ -10,6 +10,7 @@ export async function getScheduling_Unit_Draft(){ } ).then(function(response) { res= response; + }).catch(function(error) { console.log('Error on Authentication',error); });