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

Merge branch 'TMSS-213' into TMSS-630

parents b95a6c53 a0cd1758
No related branches found
No related tags found
1 merge request!397Resolve TMSS-630
...@@ -34,7 +34,8 @@ class App extends Component { ...@@ -34,7 +34,8 @@ class App extends Component {
overlayMenuActive: localStorage.getItem('overlayMenuActive') === 'true' ? true : false, overlayMenuActive: localStorage.getItem('overlayMenuActive') === 'true' ? true : false,
mobileMenuActive: localStorage.getItem('mobileMenuActive') === 'true' ? true : false, mobileMenuActive: localStorage.getItem('mobileMenuActive') === 'true' ? true : false,
authenticated: Auth.isAuthenticated(), authenticated: Auth.isAuthenticated(),
redirect: (Auth.isAuthenticated() && window.location.pathname === "/login")?"/":window.location.pathname redirect: (Auth.isAuthenticated() && window.location.pathname === "/login")?"/":window.location.pathname,
findObjectPlaceholder: 'Sub Task',
}; };
this.onWrapperClick = this.onWrapperClick.bind(this); this.onWrapperClick = this.onWrapperClick.bind(this);
this.onToggleMenu = this.onToggleMenu.bind(this); this.onToggleMenu = this.onToggleMenu.bind(this);
...@@ -43,6 +44,7 @@ class App extends Component { ...@@ -43,6 +44,7 @@ class App extends Component {
this.setPageTitle = this.setPageTitle.bind(this); this.setPageTitle = this.setPageTitle.bind(this);
this.loggedIn = this.loggedIn.bind(this); this.loggedIn = this.loggedIn.bind(this);
this.logout = this.logout.bind(this); this.logout = this.logout.bind(this);
this.setSearchField = this.setSearchField.bind(this);
this.menu = [ {label: 'Dashboard', icon: 'pi pi-fw pi-home', to:'/dashboard',section: 'dashboard'}, this.menu = [ {label: 'Dashboard', icon: 'pi pi-fw pi-home', to:'/dashboard',section: 'dashboard'},
{label: 'Cycle', icon:'pi pi-fw pi-spinner', to:'/cycle',section: 'cycle'}, {label: 'Cycle', icon:'pi pi-fw pi-spinner', to:'/cycle',section: 'cycle'},
...@@ -131,6 +133,19 @@ class App extends Component { ...@@ -131,6 +133,19 @@ class App extends Component {
this.setState({authenticated: false, redirect:"/"}); this.setState({authenticated: false, redirect:"/"});
} }
/**
* Set search param
* @param {*} key
* @param {*} value
*/
setSearchField(key, value) {
this.setState({
objectType: key,
findObjectId: value,
redirect:"/find/object/"+key+"/"+value
});
}
render() { render() {
const wrapperClass = classNames('layout-wrapper', { const wrapperClass = classNames('layout-wrapper', {
'layout-overlay': this.state.layoutMode === 'overlay', 'layout-overlay': this.state.layoutMode === 'overlay',
...@@ -151,12 +166,17 @@ class App extends Component { ...@@ -151,12 +166,17 @@ class App extends Component {
{/* Load main routes and application only if the application is authenticated */} {/* Load main routes and application only if the application is authenticated */}
{this.state.authenticated && {this.state.authenticated &&
<> <>
<AppTopbar onToggleMenu={this.onToggleMenu} isLoggedIn={this.state.authenticated} onLogout={this.logout}></AppTopbar> <AppTopbar
onToggleMenu={this.onToggleMenu}
isLoggedIn={this.state.authenticated}
onLogout={this.logout}
setSearchField={this.setSearchField}
/>
<Router basename={ this.state.currentPath }> <Router basename={ this.state.currentPath }>
<AppMenu model={this.menu} onMenuItemClick={this.onMenuItemClick} layoutMode={this.state.la} active={this.state.menuActive}/> <AppMenu model={this.menu} onMenuItemClick={this.onMenuItemClick} layoutMode={this.state.la} active={this.state.menuActive}/>
<div className="layout-main"> <div className="layout-main">
{this.state.redirect && {this.state.redirect &&
<Redirect to={{pathname: this.state.redirect}} />} <Redirect to={{pathname: this.state.redirect }}/> }
<AppBreadCrumbWithRouter setPageTitle={this.setPageTitle} /> <AppBreadCrumbWithRouter setPageTitle={this.setPageTitle} />
<RoutedContent /> <RoutedContent />
</div> </div>
......
...@@ -5,19 +5,17 @@ import 'primereact/resources/themes/nova-light/theme.css'; ...@@ -5,19 +5,17 @@ import 'primereact/resources/themes/nova-light/theme.css';
import 'primereact/resources/primereact.css'; import 'primereact/resources/primereact.css';
import 'primeflex/primeflex.css'; import 'primeflex/primeflex.css';
import { PropTypes } from 'prop-types'; import { PropTypes } from 'prop-types';
import Auth from '../../authenticate/auth'; import Auth from '../../authenticate/auth';
import { FindObject } from './FindObject';
export class AppTopbar extends Component { export class AppTopbar extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
username: Auth.getUser().name username: Auth.getUser().name,
}; };
} }
static defaultProps = { static defaultProps = {
onToggleMenu: null onToggleMenu: null
} }
...@@ -31,9 +29,11 @@ export class AppTopbar extends Component { ...@@ -31,9 +29,11 @@ export class AppTopbar extends Component {
<React.Fragment> <React.Fragment>
<div className="layout-wrapper layout-static layout-static-sidebar-inactive"> <div className="layout-wrapper layout-static layout-static-sidebar-inactive">
<div className="layout-topbar clearfix"> <div className="layout-topbar clearfix">
<button className="p-link layout-menu-button" onClick={this.props.onToggleMenu}> <button className="p-link layout-menu-button" onClick={this.props.onToggleMenu}>
<i className="pi pi-bars"></i></button> <i className="pi pi-bars"></i></button>
<span className="header-title">TMSS</span> <span className="header-title">TMSS</span>
{this.props.isLoggedIn && {this.props.isLoggedIn &&
<div className="top-right-bar"> <div className="top-right-bar">
<span><i className="fa fa-user"></i>{this.state.username}</span> <span><i className="fa fa-user"></i>{this.state.username}</span>
...@@ -41,6 +41,7 @@ export class AppTopbar extends Component { ...@@ -41,6 +41,7 @@ export class AppTopbar extends Component {
<i className="pi pi-power-off"></i></button> <i className="pi pi-power-off"></i></button>
</div> </div>
} }
<FindObject setSearchField={this.props.setSearchField} />
</div> </div>
</div> </div>
......
import React, {Component} from 'react';
import { Dropdown } from 'primereact/dropdown';
import _ from 'lodash';
import { appGrowl , setAppGrowl } from './AppGrowl';
import { Growl } from 'primereact/components/growl/Growl';
import { InputText } from 'primereact/inputtext';
export class FindObject extends Component {
constructor(props) {
super(props);
this.state = {
// Find Object - dropdown list value
objectTypes: [
{name: 'Scheduling Unit', code: 'sublueprint'},
{name: 'Task', code: 'taskblueprint'},
{name: 'Subtask', code: 'subtask'},
// {name: 'Task Draft', code: 'taskdraft'},
//{name: 'SU Draft', code: 'sudraft'},
// {name: 'Project', code: 'project'},
],
objectId: '',
objectType: {name: 'Scheduling Unit', code: 'sublueprint'}
};
this.findObject = this.findObject.bind(this);
this.setObjectType = this.setObjectType.bind(this);
this.setFindObjectId = this.setFindObjectId.bind(this);
this.handleEvent = this.handleEvent.bind(this);
}
/**
*
* @param {Key Event} e - Key code
*/
handleEvent(e) {
var key = e.which || e.keyCode;
if(key === 13 || key === 'Enter') {
this.findObject();
}
}
/**
* Set Object Type
* @param {String} value - Object type value
*/
setObjectType(value) {
if (value.name && value.name === 'Project') {
this.setState({objectType: value});
} else if(isNaN(this.state.objectId)){
this.setState({objectType: value, objectId: ''});
} else {
this.setState({objectType: value});
}
}
/**
* Set Object id value
* @param {String/Number} value - Object id, accepts alphanumeric if object type is 'Project'
*/
setFindObjectId(value) {
if (this.state.objectType.name === 'Project' || !isNaN(value)) {
this.setState({objectId: value});
} else{
appGrowl.show({severity: 'info', summary: 'Information', detail: 'Enter valid object Id'});
}
}
/**
* Callback function to find Object
*/
findObject() {
if (this.state.objectId && this.state.objectId.length > 0) {
this.props.setSearchField(this.state.objectType.code, this.state.objectId);
} else {
appGrowl.show({severity: 'info', summary: 'Information', detail: 'Enter Object Id'});
}
}
render() {
return (
<React.Fragment>
<Growl ref={(el) => setAppGrowl(el)} />
<div className="top-right-bar find-object-search" style={{marginRight: '1em'}}>
<Dropdown
className="p-link layout-menu-button find-object-type"
value={this.state.objectType}
options={this.state.objectTypes}
optionLabel="name"
onChange={(e) => {this.setObjectType(e.value)}}
/>
<InputText
value={this.state.objectId}
onChange={(e) => {this.setFindObjectId(e.target.value)}}
title='Enter Object Id to search Object'
className="find-object-search-input"
placeholder="Search by ID"
onKeyDown={this.handleEvent}
/>
<button className="p-link layout-menu-button" style={{float: 'right'}} onClick={this.findObject} >
<i className="pi pi-search find-object-search-btn" />
</button>
</div>
</React.Fragment>
);
}
}
...@@ -3,4 +3,9 @@ ...@@ -3,4 +3,9 @@
padding: 60px 16px 16px 25px; padding: 60px 16px 16px 25px;
min-height: 95vh; min-height: 95vh;
background-color: white; background-color: white;
}
.find-obj-tree-view {
margin-left: 1em;
margin-right: 1em;
} }
\ No newline at end of file
...@@ -118,9 +118,10 @@ ...@@ -118,9 +118,10 @@
color: $topbarItemColor; color: $topbarItemColor;
@include transition(color $transitionDuration); @include transition(color $transitionDuration);
span { // Search type dropdown arrow looks bigger in topbar,
/* span {
font-size: 2em; font-size: 2em;
} }*/
&:hover { &:hover {
color: $topbarItemHoverColor; color: $topbarItemHoverColor;
...@@ -143,4 +144,30 @@ ...@@ -143,4 +144,30 @@
.top-right-bar button { .top-right-bar button {
padding-left: 5px; padding-left: 5px;
} }
\ No newline at end of file
.find-object-search {
padding-top: 0px;
}
.find-object-search-input {
border-inline-start-width: 0px;
border-inline-end-width: 2em !important;
width: 11em;
}
.find-object-search-btn {
display: inline-block;
right: 27px;
position: relative;
top: 6px;
color: darkblue;
}
.find-object-type {
width: 12em;
right:1em;
}
\ No newline at end of file
import React, {Component} from 'react';
import PageHeader from '../../layout/components/PageHeader';
import AppLoader from '../../layout/components/AppLoader';
import { Tree } from 'primereact/tree';
import TaskService from './../../services/task.service';
import ScheduleService from './../../services/schedule.service';
import ProjectService from './../../services/project.service';
export class FindObjectResult extends Component{
constructor(props){
super(props);
this.state = {
objNodes: [],
expandedKeys: {},
isLoading: true
};
this.schedulingSetList= {};
this.projectsList= {};
this.data= {};
this.expandAll = this.expandAll.bind(this);
this.expandNode = this.expandNode.bind(this);
}
componentDidUpdate(prevProps, prevState) {
const objectType = this.props.match.params.type;
const objectId = this.props.match.params.id;
const prevObjectType = prevProps.match.params.type;
const prevObjectId = prevProps.match.params.id;
if(objectType !== prevObjectType || objectId !== prevObjectId){
this.findObject();
}
}
componentDidMount(){
this.findObject();
}
/**
* Find Object based in search id
*/
async findObject(){
let objNodes = [];
this.setState({objNodes: objNodes, isLoading: true});
const objectType = this.props.match.params.type;//(this.props.location.state && this.props.location.state.objectType)?this.props.location.state.objectType:'';
const objectid = this.props.match.params.id;
if (objectType === 'subtask') {
objNodes = await this.findSubTask(objectid);
}
else if (objectType === 'taskdraft') {
objNodes = await this.findTask('draft', objectid);
}
else if (objectType === 'taskblueprint') {
objNodes = await this.findTask('blueprint', objectid);
}
else if (objectType === 'sublueprint') {
objNodes = await this.findSchedulingUnit('blueprint', objectid);
}
else if (objectType === 'sudraft') {
objNodes = await this.findSchedulingUnit('draft', objectid);
}
else if (objectType === 'project') {
objNodes = await this.findProject(objectid);
}
this.setState({objNodes: objNodes, isLoading: false});
this.expandAll();
}
/**
* Find SubTask for given id
* @param {*} id
* @returns
*/
async findSubTask(id){
const subtaskDetails = await TaskService.getSubtaskDetails(id);
if (subtaskDetails) {
let subtask = {};
subtask['key'] = 'subtask'+subtaskDetails.id;
subtask['label'] = <> SubTask ({subtaskDetails.id})
{/* -- View page not available yet --
<span className="find-obj-tree-view"><a href="" target='_blank'>View</a></span> */}
<span className="find-obj-tree-view"> <a href={subtaskDetails.url} target='_blank'
title=" View SubTask API"><i className="fa fa-link" /></a></span></>;
subtask['icon'] = 'fas fa-tasks';
subtask['children'] = await this.findTask('blueprint', subtaskDetails.task_blueprint_id);
return [subtask];
}
return '';
}
/**
* Find Task details for given id
* @param {*} taskType
* @param {*} id
* @returns
*/
async findTask(taskType, id){
const taskDetails = await TaskService.getTask(taskType, id);
if (taskDetails) {
let task = {};
task['key'] = 'task'+taskDetails.id;
task['label'] = <> Task ({taskDetails.id})
<span className="find-obj-tree-view">
<a href={`/task/view/${taskType}/${taskDetails.id}`} target='_blank' title=" View Task Details">
<i className="fa fa-eye" />
</a>
</span>
<span> <a href={taskDetails.url} target='_blank' title=" View Task API"><i className="fa fa-link" /></a></span></>;
task['icon'] = 'fa fa-tasks';
if (taskType === 'blueprint') {
task['children'] = await this.findSchedulingUnit('blueprint', taskDetails.scheduling_unit_blueprint_id);
} else {
task['children'] = await this.findSchedulingUnit('draft', taskDetails.scheduling_unit_draft_id);
}
return [task];
}
return '';
}
/**
* Find Scheduling Unit for given id
* @param {*} suType
* @param {*} id
* @returns
*/
async findSchedulingUnit(suType, id){
let suDetails = null;
if (suType === 'blueprint') {
suDetails = await ScheduleService.getSchedulingUnitBlueprintById (id);
} else {
suDetails = await ScheduleService.getSchedulingUnitDraftById(id);
}
if (suDetails) {
let schedulingUnit = {};
schedulingUnit['key'] = 'su'+suDetails.id;
schedulingUnit['label'] = <> Scheduling Unit ({suDetails.id})
<span className="find-obj-tree-view"><a href={`/schedulingunit/view/${suType}/${suDetails.id}`}
target='_blank' title=" View Scheduling Unit Details"><i className="fa fa-eye" /></a> </span>
<span><a href={suDetails.url} target='_blank' title=" View Scheduling Unit API" >
<i className="fa fa-link" /></a></span></>;
schedulingUnit['icon'] = 'pi pi-fw pi-calendar';
schedulingUnit['children'] = await this.findSchedulingSetBySUId(suDetails);
return [schedulingUnit];
}
return '';
}
/**
* Find project for given SU id
* @param {*} suId
*/
async findSchedulingSetBySUId(suDetails) {
const suSetDetails = suDetails.scheduling_set_object;
if (suSetDetails) {
let suSet = {};
suSet['key'] = 'suset'+suSetDetails.id;
suSet['label'] = <> Scheduling Set ({suSetDetails.id})
{/* -- View page not available yet --
<span className="find-obj-tree-view"><a href=""
target='_blank' title='View Project details'><i className="fa fa-eye" /></a></span> */}
<span className="find-obj-tree-view">
<a href={suSetDetails.url} target='_blank' title='View Scheduling Set API'><i className="fa fa-link" /></a></span></>;
suSet['icon'] = 'fa fa-table';
suSet['children'] = await this.findProject(suSetDetails.project_id);
return [suSet];
}
return '';
}
/**
* Find project details for given id
* @param {*} id
* @returns
*/
async findProject(id){
const projectDetails = await ProjectService.getProjectDetails(id);
if (projectDetails) {
let project = {};
project['key'] = projectDetails.name;
project['label'] = <> Project ({projectDetails.name})
<span className="find-obj-tree-view"><a href={`/project/view/${projectDetails.name}`}
target='_blank' title='View Project details'><i className="fa fa-eye" /></a></span>
<span><a href={projectDetails.url} target='_blank' title='View Project API'><i className="fa fa-link" /></a></span></>;
project['icon'] = 'fab fa-fw fa-wpexplorer';
return [project];
}
return '';
}
expandNode(node, expandedKeys) {
if (node.children && node.children.length) {
expandedKeys[node.key] = true;
for (let child of node.children) {
this.expandNode(child, expandedKeys);
}
}
}
expandAll() {
let expandedKeys = {};
for (let node of this.state.objNodes) {
this.expandNode(node, expandedKeys);
}
this.setState({expandedKeys: expandedKeys });
}
render(){
return(
<>
<PageHeader location={this.props.location} title={'Search Result'}
actions={[]}
/>
{ this.state.isLoading ? <AppLoader /> :
<>
{this.state.objNodes.length > 0 &&
<>
<Tree value={this.state.objNodes} selectionMode="multiple" expandedKeys={this.state.expandedKeys}
style={{width: 'auto'}} onToggle={e => this.setState({expandedKeys: e.value})} />
</>
}
{this.state.objNodes.length === 0 &&
<> No Object found ! </>
}
</>
}
</>
)
}
}
import {FindObjectResult} from './find.object.result';
export {FindObjectResult} ;
...@@ -15,6 +15,7 @@ import SchedulingUnitCreate from './Scheduling/create'; ...@@ -15,6 +15,7 @@ import SchedulingUnitCreate from './Scheduling/create';
import EditSchedulingUnit from './Scheduling/edit'; import EditSchedulingUnit from './Scheduling/edit';
import { CycleList, CycleCreate, CycleView, CycleEdit } from './Cycle'; import { CycleList, CycleCreate, CycleView, CycleEdit } from './Cycle';
import { TimelineView, WeekTimelineView, ReservationCreate, ReservationList } from './Timeline'; import { TimelineView, WeekTimelineView, ReservationCreate, ReservationList } from './Timeline';
import { FindObjectResult } from './Search/'
import SchedulingSetCreate from './Scheduling/excelview.schedulingset'; import SchedulingSetCreate from './Scheduling/excelview.schedulingset';
import Workflow from './Workflow'; import Workflow from './Workflow';
import { Growl } from 'primereact/components/growl/Growl'; import { Growl } from 'primereact/components/growl/Growl';
...@@ -165,6 +166,12 @@ export const routes = [ ...@@ -165,6 +166,12 @@ export const routes = [
component: ReservationCreate, component: ReservationCreate,
name: 'Reservation Add', name: 'Reservation Add',
title: 'Reservation - Add' title: 'Reservation - Add'
},
{
path: "/find/object/:type/:id",
component: FindObjectResult,
name: 'Find Object',
title: 'Find Object'
} }
]; ];
......
...@@ -2,31 +2,39 @@ const axios = require('axios'); ...@@ -2,31 +2,39 @@ const axios = require('axios');
const TaskService = { const TaskService = {
getTaskDetails: async function (taskType, taskId) { getTaskDetails: async function (taskType, taskId) {
try { try {
const url = taskType === 'blueprint'? '/api/task_blueprint/': '/api/task_draft/'; const responseData = await this.getTask(taskType, taskId);
const response = await axios.get(url + taskId); responseData.predecessors = [];
response.data.predecessors = []; responseData.successors = [];
response.data.successors = []; if (taskType === 'blueprint') {
if (taskType === 'blueprint') { responseData.blueprints = [];
response.data.blueprints = []; } else {
} else { responseData.draftName = null;
response.data.draftName = null;
}
return this.getTaskRelationsByTask(taskType, response.data)
.then(relations => {
response.data.predecessors = relations.predecessors;
response.data.successors = relations.successors;
if (taskType === 'draft') {
response.data.blueprints = relations.blueprints;
} else {
response.data.draftObject = relations.draft;
}
return response.data;
});
} catch (error) {
console.error(error);
} }
return this.getTaskRelationsByTask(taskType, responseData)
.then(relations => {
responseData.predecessors = relations.predecessors;
responseData.successors = relations.successors;
if (taskType === 'draft') {
responseData.blueprints = relations.blueprints;
} else {
responseData.draftObject = relations.draft;
}
return responseData;
});
} catch (error) {
console.error(error);
}
},
getTask : async function (taskType, taskId) {
try {
const url = taskType === 'blueprint'? '/api/task_blueprint/': '/api/task_draft/';
const response = await axios.get(url + taskId);
return response.data;
} catch (error) {
console.error(error);
}
}, },
getTaskTemplate: async function(templateId) { getTaskTemplate: async function(templateId) {
try { try {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment