diff --git a/package-lock.json b/package-lock.json index 0c066a7..a6bbf16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -347,6 +347,11 @@ "superagent": "^3.5.2" } }, + "@microsoft/microsoft-graph-types": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.7.0.tgz", + "integrity": "sha512-Mxu5H+69F8T5NzV4+U8FkTvpIYYWHsmRZzfAuOlIO0zJJGlVyRIVqpq4NmOdUXGC00vZ73ONgCuzuaksxqDm/Q==" + }, "@microsoft/node-core-library": { "version": "0.3.16", "resolved": "https://registry.npmjs.org/@microsoft/node-core-library/-/node-core-library-0.3.16.tgz", @@ -1123,6 +1128,88 @@ } } }, + "@pnp/common": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@pnp/common/-/common-1.3.8.tgz", + "integrity": "sha512-VYdShvkeOeOzXB3Lg/BqS+0WaHFSCd4n/8huBt7b63ormLLBrHX9aFRy457GiqHbnfEflHNBsVfwPj11z5wktg==", + "requires": { + "adal-angular": "1.0.17", + "tslib": "1.10.0" + }, + "dependencies": { + "adal-angular": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/adal-angular/-/adal-angular-1.0.17.tgz", + "integrity": "sha1-bpNuDkH5HTsqiOf/ypwvb29WLMQ=" + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/graph": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@pnp/graph/-/graph-1.3.8.tgz", + "integrity": "sha512-uBBDrpWNILGBfTxtHqFrdv3YkJZm+jgXOLBp3KR8ocBrTt+yQmkCEwztawYqUhSys6SoDkcFE/DqLIjhyHiBDA==", + "requires": { + "@microsoft/microsoft-graph-types": "1.7.0", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/logging": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-1.3.8.tgz", + "integrity": "sha512-5uA+03Q9TCigpf3yJqqms0BCDzvm8Ko0bmX1TM4hjNGh2MEqE3OlQ99uPSz4jQGmEQ/93ReGvzD5S+JL9qd8EA==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/odata": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@pnp/odata/-/odata-1.3.8.tgz", + "integrity": "sha512-uGcV+Dx59W/yO6xOlMoObF8IYWZJnUqCsbuH/KI4BQ+izcPXi4N2tnj2i2OOEso0dobduoADR8q8XK7+SpXjOQ==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/sp": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-1.3.8.tgz", + "integrity": "sha512-x85cQL/L5fBYJWqWvDL3e2sHdYZIqUeWifFndsGRk6iLFHTq2DsxNNzTnCpP7JCKUwK6jHpu0JzIuK98E8Hl9w==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, "@types/adal": { "version": "1.0.27", "resolved": "https://registry.npmjs.org/@types/adal/-/adal-1.0.27.tgz", diff --git a/package.json b/package.json index 403c9ee..4322a60 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,11 @@ "@microsoft/sp-lodash-subset": "~1.4.0", "@microsoft/sp-office-ui-fabric-core": "~1.4.0", "@microsoft/sp-webpart-base": "~1.4.0", + "@pnp/common": "^1.3.8", + "@pnp/graph": "^1.3.8", + "@pnp/logging": "^1.3.8", + "@pnp/odata": "^1.3.8", + "@pnp/sp": "^1.3.8", "@types/es6-promise": "0.0.33", "@types/react": "15.6.6", "@types/react-dom": "15.5.6", diff --git a/src/webparts/summaryWebPart/SummaryWebPartWebPart.manifest.json b/src/webparts/summaryWebPart/SummaryWebPartWebPart.manifest.json index 8b61c10..6c82b7b 100644 --- a/src/webparts/summaryWebPart/SummaryWebPartWebPart.manifest.json +++ b/src/webparts/summaryWebPart/SummaryWebPartWebPart.manifest.json @@ -21,7 +21,8 @@ "officeFabricIconFontName": "Page", "properties": { "description": "Сводка", - "requestUrl": "http://logics.portal.vertex.spb.ru/api/Project/GetSummaryProject?projCode=" + "requestUrl": "http://logics.portal.vertex.spb.ru/api/Project/GetSummaryProject?projCode=", + "rowsOrder": "Manager_Project; Status_Project; Code_project; pmis_ProjectPortfolio; Type_Project; Objective_Project; Tasks_Project; Customer_Project; Curator_Project; Coordinator_Project" } }] } diff --git a/src/webparts/summaryWebPart/SummaryWebPartWebPart.ts b/src/webparts/summaryWebPart/SummaryWebPartWebPart.ts index 603b431..74e0248 100644 --- a/src/webparts/summaryWebPart/SummaryWebPartWebPart.ts +++ b/src/webparts/summaryWebPart/SummaryWebPartWebPart.ts @@ -14,6 +14,7 @@ import { ISummaryWebPartProps } from './components/ISummaryWebPartProps'; export interface ISummaryWebPartWebPartProps { description: string; requestUrl: string; + rowsOrder: string; context: any; } @@ -25,7 +26,8 @@ export default class SummaryWebPartWebPart extends BaseClientSideWebPart { - public state = { - items: null - }; +export default class SummaryContainer extends React.Component { + public state = { + items: [] + }; - componentDidMount(){ - const {projectInfo} =this.props; - let missCount = 0; - let rows = [ - { - key: 1, - fieldName: 'Руководитель проекта', - value: projectInfo.chief, - }, - { - key: 2, - fieldName: 'Статус', - value: projectInfo.status, - }, - { - key: 3, - fieldName: 'Код проекта', - value: projectInfo.code, - }, - { - key: 4, - fieldName: 'Портфель проектов', - value: projectInfo.portfolio, - }, - { - key: 5, - fieldName: 'Программа проектов', - value: projectInfo.programm, - }, - { - key: 6, - fieldName: 'Тип проекта', - value: projectInfo.type, - }, - { - key: 7, - fieldName: 'Цель проекта', - value: projectInfo.target, - }, - { - key: 8, - fieldName: 'Задачи проекта', - value: projectInfo.task, - }, - { - key: 9, - fieldName: 'Заказчик проекта', - value: projectInfo.customer, - }, - { - key: 10, - fieldName: 'Куратор проекта', - value: projectInfo.curator, - }, - { - key: 11, - fieldName: 'Координатор проекта', - value: projectInfo.coordinator, - }, - ].filter(e=>{ - return e.value !== "" - }); + componentDidMount() { + const { order, context } = this.props; + let relUrl = context.pageContext.web.serverRelativeUrl; + let prjCode = relUrl ? relUrl.split("/")[relUrl.split("/").length - 1] : ""; - this.setState({items: rows}); - } + let web = new Web("http://portal.vertex.spb.ru/PMIS"); + let webMDM = new Web("http://portal.vertex.spb.ru/sites/mdm"); + let dispItems = webMDM.lists.getById("35b69b82-eb54-46fb-a8b4-2c763b11e10f").items.select("Title, Order0").get(); + let fields = web.lists.getById("eeba7db6-4c28-41a2-a54e-82a2aaf0ca15").fields.get(); + Promise.all([dispItems, fields]).then(result=>{ + let sortedDispItems = result[0].sort((a, b) => a.Order0 - b.Order0); + let allFields = result[1]; + return sortedDispItems.map(dispItem => { + let item = allFields.filter(e => dispItem.Title == e.StaticName); + return { + key: dispItem.Order0, + fieldName: item[0].LookupField + ? `${dispItem.Title}/Title` + : dispItem.Title, + fieldRuTitle: item[0].Title, + LookupField: item[0].LookupField ? dispItem.Title : "" + }; + }); + }).then(res=>{ + let selectedFields = res.map(e=>e.fieldName).join(', '); + let lookupFields = res.filter(e=> e.LookupField !== "").map(e=>e.LookupField).join(', '); - public columns = [ - { - key: 'column1', - name: 'Название', - fieldName: 'fieldName', - minWidth: 16, - maxWidth: 150 - }, - { - key: 'column2', - name: 'Значение', - fieldName: 'value', - minWidth: 16, - maxWidth: 100 - }, - ] + let toState = []; + web.lists + .getById("eeba7db6-4c28-41a2-a54e-82a2aaf0ca15") + .items.filter( + "Code_project eq '" + prjCode + "'" + ) + .select(selectedFields) + .expand(lookupFields) + .get() + .then(currentProject => { + 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){ + toState.push({ + key: e.key, + fieldName: e.fieldRuTitle, + value: fieldValue + }); + } + }); + this.setState({ items: toState }); + }); + }) + } - public render(): React.ReactElement { - const {items} = this.state; - return ( -
- -
- ); + public columns = [ + { + key: "column1", + name: "Название", + fieldName: "fieldName", + minWidth: 16, + maxWidth: 150, + canResizeColumns: true, + isMultiline: true + }, + { + key: "column2", + name: "Значение", + fieldName: "value", + minWidth: 16, + canResizeColumns: true, + isMultiline: true + } + ]; + + public render(): React.ReactElement { + const { items } = this.state; + return ( +
+ +
+ ); + } } -} diff --git a/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.module.scss b/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.module.scss index cc7d9d3..cafdc60 100644 --- a/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.module.scss +++ b/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.module.scss @@ -3,9 +3,11 @@ grid-template-columns: 34% 34% 30%; column-gap: 30px; .SummaryPageRowOne{ - display: grid; - grid-template-rows: 1fr 1fr; - column-gap: 30px; + display: flex; + flex-direction: column; + canvas{ + height: 100% !important; + } } .SummaryPageRowTwo{ width: 100%; diff --git a/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.tsx b/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.tsx index 0767d5d..b348eda 100644 --- a/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.tsx +++ b/src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.tsx @@ -7,26 +7,35 @@ import Structure from '../Structure/Structure'; import { IPageData } from '../../interfaces/IPageData'; -export interface IComponentProps{ - data: IPageData +export interface IComponentProps { + data: IPageData; + rowsOrder: string; + context: any } export default class SummaryGlobalComponent extends React.Component { public render(): React.ReactElement { - const { data } = this.props; + const { data, rowsOrder, context } = this.props; return (
- +
- - + +
- +
); } diff --git a/src/webparts/summaryWebPart/components/SummaryWebPart.tsx b/src/webparts/summaryWebPart/components/SummaryWebPart.tsx index 61d7a0c..7752132 100644 --- a/src/webparts/summaryWebPart/components/SummaryWebPart.tsx +++ b/src/webparts/summaryWebPart/components/SummaryWebPart.tsx @@ -22,8 +22,8 @@ export default class SummaryWebPart extends React.Component{ return response.json() }).then(result=>{ @@ -38,12 +38,28 @@ export default class SummaryWebPart extends React.Component { const { pageData, isLoaded, isBlank } = this.state; - return (isLoaded ? -
-
- + return isLoaded ? ( +
+
+ +
+
- : - isBlank ?
: ) + ) : isBlank ? ( +
+ ) : ( + + ); } } diff --git a/src/webparts/summaryWebPart/components/TrafficLight/TrafficLight.tsx b/src/webparts/summaryWebPart/components/TrafficLight/TrafficLight.tsx index 995f81d..fcd3ee0 100644 --- a/src/webparts/summaryWebPart/components/TrafficLight/TrafficLight.tsx +++ b/src/webparts/summaryWebPart/components/TrafficLight/TrafficLight.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import styles from '../SummaryGlobalComponent/SummaryGlobalComponent.module.scss' -import Moment from "react-moment"; import moment from "moment/min/moment-with-locales"; import { DetailsList, SelectionMode, DetailsListLayoutMode } from 'office-ui-fabric-react/lib/DetailsList'; @@ -30,15 +29,15 @@ export default class TrafficLight extends React.Component { const { statuses, taskStats, dateInfo} = this.props; let procent = (taskStats.compl/(taskStats.plan + taskStats.compl + taskStats.exec))* 100; - let startDate = moment(dateInfo.dateStart).format("DD.MM.YY"); - let finDate = moment(dateInfo.dateFinish).format("DD.MM.YY"); - let totalDays = new moment.duration((new Date(dateInfo.dateFinish) as any) -(new Date(dateInfo.dateStart) as any)).asDays(); + let startDate = moment(dateInfo.dateStart).format("DD.MM.YYYY"); + let finDate = moment(dateInfo.dateFinish).format("DD.MM.YYYY"); + let totalDays = new moment.duration((new Date(dateInfo.dateFinish ? dateInfo.dateFinish.split('T')[0] : dateInfo.dateFinish) as any) - (new Date(dateInfo.dateStart ? dateInfo.dateStart.split('T')[0] : dateInfo.dateStart) as any)).asDays(); return (
{ fieldName: "Статус по % выполнения", status: statuses.percCompl } - ]} + ] : + [ + { + key: 1, + fieldName: "Статус по сроку", + status: statuses.term + }, + { + key: 2, + fieldName: "Статус по % выполнения", + status: statuses.percCompl + } + ] + } columns={[ { key: "column1", @@ -79,9 +91,9 @@ export default class TrafficLight extends React.Component { items={[ { key: 1, - start: startDate, - end: finDate, - time: totalDays, + start: startDate !== 'Invalid date' ? startDate : '', + end: finDate !== 'Invalid date' ? finDate : '', + time: totalDays ? totalDays : '', allTasks: taskStats.plan + taskStats.compl + taskStats.exec } ]} @@ -127,7 +139,7 @@ export default class TrafficLight extends React.Component { marginTop: 15, marginBottom: 15 }} - >{`Актуальный статус выполнения ${procent.toFixed(2)}%`}
+ >{`Актуальный статус выполнения ${!isNaN(+procent.toFixed(2)) ? procent.toFixed(2) + '%' : ' -' }`}
); }