From 1d7ea3c1566003931d34c680dec933cd843d514e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D1=81=D1=8C=D0=BC=D0=B0=D0=BA=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=81?= Date: Fri, 21 Feb 2020 15:44:51 +0300 Subject: [PATCH] styles --- .../RejectTasks/RejectTasks.module.scss | 123 +++++++++++ .../components/RejectTasks/RejectTasks.tsx | 203 ++++++++++++++++++ .../Structure/Structure.module.scss | 1 + .../components/Structure/Structure.tsx | 63 +++++- .../SummaryContainer/SummaryContainer.tsx | 57 ++++- .../SummaryGlobalComponent.module.scss | 37 +++- .../SummaryGlobalComponent.tsx | 25 ++- .../components/SummaryWebPart.module.scss | 76 +------ .../components/SummaryWebPart.tsx | 25 ++- .../TaskStatusesChart/TaskStatusesChart.tsx | 66 +++++- .../components/TrafficLight/TrafficLight.tsx | 56 +++-- .../interfaces/IDeviationTasks.ts | 4 + .../summaryWebPart/interfaces/IPageData.ts | 1 + 13 files changed, 613 insertions(+), 124 deletions(-) create mode 100644 src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.module.scss create mode 100644 src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.tsx create mode 100644 src/webparts/summaryWebPart/components/Structure/Structure.module.scss create mode 100644 src/webparts/summaryWebPart/interfaces/IDeviationTasks.ts diff --git a/src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.module.scss b/src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.module.scss new file mode 100644 index 0000000..3216882 --- /dev/null +++ b/src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.module.scss @@ -0,0 +1,123 @@ + +.commonTable { + /* min-width: 361px; + max-width: 361px; + width: 361px; */ + width: 100%; + border-bottom: 1px solid #c8c8c8; + .thead { + display: flex; + .th { + padding: 6px; + border-top: 1px solid #c8c8c8; + border-left: 1px solid #c8c8c8; + font-family: "Segoe UI Web (West European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif; + width: 100%; + color: #767676; + font-size: 13px; + font-weight: bold; + transition: 0.5s; + + cursor: pointer; + + &:hover { + background: #f4f4f4; + color: #666666; + transition: 0.5s; + } + } + .Departments { + min-width: 123px !important; + } + .Managers { + min-width: 116px !important; + } + .Members { + min-width: 116px !important; + } + .count { + min-width: 46px !important; + max-width: 46px !important; + border-right: 1px solid #c8c8c8; + } + } + .tbody { + display: flex; + + .td { + border-top: 1px solid #c8c8c8; + border-left: 1px solid #c8c8c8; + color: #767676; + background: #ffffff; + font-size: 13px; + width: 100%; + + font-family: "Segoe UI Web (West European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif; + transition: 0.5s; + cursor: pointer; + + + .cell { + padding: 3px 5px; + color: #767676; + border-bottom: 1px solid #c8c8c8; + display: flex; + align-items: center; + justify-content: center; + + /* max-width: 100px; */ + &:hover { + background: #f4f4f4; + color: #666666; + transition: 0.5s; + } + span { + /* white-space: nowrap; */ + overflow: hidden; + text-overflow: ellipsis; + display: block; + } + } + .Departments { + width: 124px !important; + margin-left: 1px; + } + .Managers { + min-width: 106px !important; + } + .Members { + min-width: 106px !important; + } + .isCrit { + background: #ff000042; + &:hover { + background: #ff0000ab; + color: #4b4b4b; + transition: 0.5s; + } + } + .count { + min-width: 47px !important; + } + .cell:last-child { + border-bottom: none; + } + div { + text-align: center; + vertical-align: center; + } + .dividingLine{ + border-bottom: 1px solid #c8c8c8; + } + } + .MembersTaskCount { + width: 58px; + max-width: 58px !important; + min-width: 58px !important; + border-right: 1px solid #c8c8c8; + } + } +} +.dividingLine{ + border-bottom: 1px solid #c8c8c8; +} \ No newline at end of file diff --git a/src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.tsx b/src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.tsx new file mode 100644 index 0000000..6b2d3c1 --- /dev/null +++ b/src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.tsx @@ -0,0 +1,203 @@ +import * as React from 'react'; +/* import styles from '../SummaryGlobalComponent/SummaryGlobalComponent.module.scss' */ +import { DetailsList, SelectionMode, DetailsListLayoutMode } from 'office-ui-fabric-react/lib/DetailsList'; +import { DeviationTasks } from '../../interfaces/IDeviationTasks'; +import styles from '../RejectTasks/RejectTasks.module.scss' + + +export interface IComponentProps { + structureData: DeviationTasks[] +} + + +export interface IComponentState { + +} +export default class TrafficLight extends React.Component { + + private _renderHeaderCell(): JSX.Element { + + return ( +
+
+ Подразделение +
+
+ Руководитель +
+
+ Участник +
+
+ Кол-во задач +
+
+ ) + } + + private _cell(value:string,length:any,className:string,crit?:boolean,): JSX.Element { + // 7 px это 1px border и padding 3px + + var height = 'calc('+ 100/length + '% - 7px)' + var critClassName = '' + if(crit) { + critClassName = 'isCrit' + } + + return ( +
{value}
+ ) + + + } + + + private _renderCell(structureData:any,i:number): JSX.Element { + + var Departments = [] //Подразделения + var Managers = [] //Руководители + var Members = [] //Участники + var MembersTaskCount = [] //Кол-во задач + + if(structureData){ + if(structureData.Departments.length){ + + // пушу в массив Departments ячейки + Departments.push(this._cell(structureData.Departments[i].Name,1 , 'Departments')) + if(structureData.Departments[i].Managers){ + for (let index = 0; index < structureData.Departments[i].Managers.length; index++) { + let menagers = structureData.Departments[i].Managers[index].Name + if(menagers){ + //Сокращаю Имена и Отчества Пример Масловский Артем Андреевич Масловский А.А. + let ManagersName = structureData.Departments[i].Managers[index].Name.split(' ') + let name = ManagersName[1].split('')[0] + '.' + let surname = ManagersName[0] + + if(ManagersName[2]){ + + let patronymic = ManagersName[1].split('')[0] + '.' + + ManagersName = surname + ' ' + name + ' ' + patronymic + } else { + ManagersName = surname + ' ' + name + } + + let maxLength = 0 + + structureData.Departments[i].Managers.forEach(function(e) { + maxLength = maxLength + e.Members.length + }) + + + //Переменная для расчета высоты ячейки менеджеров. + let length = maxLength/structureData.Departments[i].Managers[index].Members.length + //Пушу ячейки + Managers.push(this._cell( ManagersName ,length,'Managers')) + } else { + Managers.push(this._cell( '' ,structureData.Departments[i].Managers[index].length,'Managers')) + } + if(structureData.Departments[i].Managers[index].Members.length){ + for (let counter = 0; counter < structureData.Departments[i].Managers[index].Members.length; counter++) { + let MembersName = structureData.Departments[i].Managers[index].Members[counter].Name + if(MembersName) { + //Сокращаю Имена и Отчества Пример Масловский Артем Андреевич Масловский А.А. + + MembersName = MembersName.split(' '); + let name = MembersName[1].split('')[0] + '.'; + let surname = MembersName[0]; + if(MembersName[2]){ + MembersName[2].split('')[0]; + + let patronymic = MembersName[2].split('')[0] + '.'; + + MembersName = surname + ' ' + name + ' ' + patronymic; + } else { + MembersName = surname + ' ' + name + } + } + //Пушу ячейки + Members.push( + this._cell( MembersName ,structureData.Departments[i].Managers[index].length,'Members', + structureData.Departments[i].Managers[index].Members[counter].Crit) + ) + //Пушу ячейки + MembersTaskCount.push( + this._cell(structureData.Departments[i].Managers[index].Members[counter].TaskCount ,structureData.Departments[i].Managers[index].length,'count', + structureData.Departments[i].Managers[index].Members[counter].Crit) + ) + } + } + } + } + } + } + + return ( +
+
+ + { + Departments + } + +
+
+ { + Managers + } +
+
+ { + Members + } +
+
+ { + MembersTaskCount + } +
+
+ ) + } + private _renderBodyTable(structureData:any,): JSX.Element { + var body = [] + + for (let i = 0; i < structureData.Departments.length; i++) { + body.push(this._renderCell(structureData, i)) + } + + return ( +
{body}
+ + ) + } + componentDidMount(){ + + } + + public onRenderFooter = () =>{ + + } + + public render(): React.ReactElement { + + return ( +
+
+ +
+
+ {this._renderHeaderCell()} +
+
+ { + this._renderBodyTable(this.props.structureData) + } +
+
+ +
+
+ ); + } +} diff --git a/src/webparts/summaryWebPart/components/Structure/Structure.module.scss b/src/webparts/summaryWebPart/components/Structure/Structure.module.scss new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/webparts/summaryWebPart/components/Structure/Structure.module.scss @@ -0,0 +1 @@ + diff --git a/src/webparts/summaryWebPart/components/Structure/Structure.tsx b/src/webparts/summaryWebPart/components/Structure/Structure.tsx index 2e4e0e7..9def512 100644 --- a/src/webparts/summaryWebPart/components/Structure/Structure.tsx +++ b/src/webparts/summaryWebPart/components/Structure/Structure.tsx @@ -1,7 +1,11 @@ import * as React from 'react'; -import styles from '../SummaryGlobalComponent/SummaryGlobalComponent.module.scss' +/* import styles from '../SummaryGlobalComponent/SummaryGlobalComponent.module.scss' */ import { DetailsList, SelectionMode, DetailsListLayoutMode } from 'office-ui-fabric-react/lib/DetailsList'; -import { IMainExecItem } from '../../interfaces/IMainExecItem' +import { IMainExecItem } from '../../interfaces/IMainExecItem'; +import styles from '../SummaryWebPart.module.scss' +import { FontSizes } from '@uifabric/styling/lib'; +import { DetailsHeader } from 'office-ui-fabric-react/lib/components/DetailsList/DetailsHeader'; + export interface IComponentProps { structureData: IMainExecItem[] @@ -34,27 +38,68 @@ export default class TrafficLight extends React.Component{ + + public renderHeader = (detailsHeaderProps) => { + return ( + + ); + } + + public renderCustomHeaderTooltip = (tooltipHostProps) => { + return ( + + {tooltipHostProps.children} + + ); } public render(): React.ReactElement { - const { items } = this.state; + const { items } = this.state; + if(items){ + items.forEach(function(e) { + var name = '' + var surname = '' + var patronymic = '' + if(e.name) { + name = e.name.split(' ')[1].split('')[0] + '.' + surname = e.name.split(' ')[0] + + if(e.name.split(' ')[2]){ + patronymic = e.name.split(' ')[2].split('')[0] + '.' + e.name = surname + ' ' + name + ' ' + patronymic + } else { + e.name = surname + ' ' + name + } + } + }) + } + + return ( -
+
+

Основные исполнители

+
); } diff --git a/src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.tsx b/src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.tsx index c9334ac..427256b 100644 --- a/src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.tsx +++ b/src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { ISummaryProjectData } from '../../interfaces/ISummaryProjectData'; +import styles from '../SummaryWebPart.module.scss' import { DetailsList, SelectionMode, @@ -9,7 +10,7 @@ import { } from "office-ui-fabric-react/lib/DetailsList"; import { values } from '@uifabric/utilities/lib'; import { sp, Web, Field } from "@pnp/sp"; - +import { SPHttpClient, SPHttpClientResponse, SPHttpClientConfiguration } from '@microsoft/sp-http'; export interface IComponentProps { order: string; context: any; @@ -32,8 +33,8 @@ export default class SummaryContainer extends React.Component{ let selectedFields = res.map(e=>e.fieldName).join(', '); + selectedFields = selectedFields +', MainProjectPlanGuid, Title' let lookupFields = res.filter(e=> e.LookupField !== "").map(e=>e.LookupField).join(', '); - + let toState = []; web.lists .getById("eeba7db6-4c28-41a2-a54e-82a2aaf0ca15") @@ -67,11 +69,13 @@ export default class SummaryContainer extends React.Component { - res.forEach(e=>{ + + res.forEach(e=>{ + let fieldValue = !e.fieldName.match(/\/Title/gi)?currentProject[0][e.fieldName] : currentProject[0][e.fieldName.split('/')[0]]? currentProject[0][e.fieldName.split('/')[0]]['Title'] : ''; if (fieldValue && fieldValue.toString().match(/\;\#/gi)){ - fieldValue = fieldValue.toString().replace(/[\;\#][^\s]/gi, ''); + fieldValue = fieldValue.toString().replace(/[][^\s]/gi, ''); if (fieldValue.toString().match(/undefined/gi)) fieldValue = fieldValue.toString().replace(/undefined/gi, ''); } @@ -83,7 +87,39 @@ export default class SummaryContainer extends React.Component res.json()) + .then((data) => { + let MainProjectPlanGuid = data.value + web.lists + .getById("eeba7db6-4c28-41a2-a54e-82a2aaf0ca15") + .items.filter( + "MainProjectPlanGuid eq '" + MainProjectPlanGuid + "'" + ) + .select(selectedFields) + .expand(lookupFields) + .get().then( + (data) => { + if(data[0]) { + if(data[0]['Title']) { + toState.push({ + key: 100000, + fieldName: 'Наименования родительского проекта', + value: data[0].Title + }) + } + } + + this.setState({ items: toState }); + + } + + ) + }).catch() }); }) } @@ -110,10 +146,17 @@ export default class SummaryContainer extends React.Component { const { items } = this.state; + + items.forEach(function(e) { + if(e.fieldName == 'Внешний исполнитель') { + e.value = e.value.split(';#').join(' ') + } + }) return (