summary tab

VRTKSSUP-229
Осьмаков Денис 5 years ago
commit 5a65bde216
  1. 25
      .editorconfig
  2. 32
      .gitignore
  3. 5
      .vscode/extensions.json
  4. 43
      .vscode/launch.json
  5. 13
      .vscode/settings.json
  6. 11
      .yo-rc.json
  7. 26
      README.md
  8. 18
      config/config.json
  9. 4
      config/copy-assets.json
  10. 7
      config/deploy-azure-storage.json
  11. 13
      config/package-solution.json
  12. 10
      config/serve.json
  13. 4
      config/write-manifests.json
  14. 7
      gulpfile.js
  15. 17136
      package-lock.json
  16. 41
      package.json
  17. 1
      src/index.ts
  18. 27
      src/webparts/summaryWebPart/SummaryWebPartWebPart.manifest.json
  19. 65
      src/webparts/summaryWebPart/SummaryWebPartWebPart.ts
  20. 5
      src/webparts/summaryWebPart/components/ISummaryWebPartProps.ts
  21. 70
      src/webparts/summaryWebPart/components/Structure/Structure.tsx
  22. 119
      src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.tsx
  23. 18
      src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.module.scss
  24. 32
      src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.tsx
  25. 74
      src/webparts/summaryWebPart/components/SummaryWebPart.module.scss
  26. 35
      src/webparts/summaryWebPart/components/SummaryWebPart.tsx
  27. 75
      src/webparts/summaryWebPart/components/TaskStatusesChart/TaskStatusesChart.tsx
  28. 114
      src/webparts/summaryWebPart/components/TrafficLight/TrafficLight.tsx
  29. 4
      src/webparts/summaryWebPart/interfaces/IMainExecItem.ts
  30. 9
      src/webparts/summaryWebPart/interfaces/IPageData.ts
  31. 15
      src/webparts/summaryWebPart/interfaces/ISummaryProjectData.ts
  32. 7
      src/webparts/summaryWebPart/loc/en-us.js
  33. 10
      src/webparts/summaryWebPart/loc/mystrings.d.ts
  34. 26
      tsconfig.json
  35. 30
      tslint.json

@ -0,0 +1,25 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 2
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

32
.gitignore vendored

@ -0,0 +1,32 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
solution
temp
*.sppkg
# Coverage directory used by tools like istanbul
coverage
# OSX
.DS_Store
# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj
# Resx Generated Code
*.resx.ts
# Styles Generated Code
*.scss.ts

@ -0,0 +1,5 @@
{
"recommendations": [
"msjsdiag.debugger-for-chrome"
]
}

@ -0,0 +1,43 @@
{
/**
* Install Chrome Debugger Extension for Visual Studio Code to debug your components with the
* Chrome browser: https://aka.ms/spfx-debugger-extensions
*/
"version": "0.2.0",
"configurations": [{
"name": "Local workbench",
"type": "chrome",
"request": "launch",
"url": "https://localhost:4321/temp/workbench.html",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///.././src/*": "${webRoot}/src/*",
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222"
]
},
{
"name": "Hosted workbench",
"type": "chrome",
"request": "launch",
"url": "https://enter-your-SharePoint-site/_layouts/workbench.aspx",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///.././src/*": "${webRoot}/src/*",
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222",
"-incognito"
]
}
]
}

@ -0,0 +1,13 @@
// Place your settings in this file to overwrite default and user settings.
{
// Configure glob patterns for excluding files and folders in the file explorer.
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/bower_components": true,
"**/coverage": true,
"**/lib-amd": true,
"src/**/*.scss.ts": true
},
"typescript.tsdk": ".\\node_modules\\typescript\\lib"
}

@ -0,0 +1,11 @@
{
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "onprem19",
"version": "1.9.1",
"libraryName": "summary-web-part",
"libraryId": "08d4adf3-23e8-426b-b19c-afe95c0a61a4",
"packageManager": "npm",
"componentType": "webpart"
}
}

@ -0,0 +1,26 @@
## summary-web-part
This is where you include your WebPart documentation.
### Building the code
```bash
git clone the repo
npm i
npm i -g gulp
gulp
```
This package produces the following:
* lib/* - intermediate-stage commonjs build artifacts
* dist/* - the bundled script, along with other resources
* deploy/* - all resources which should be uploaded to a CDN.
### Build options
gulp clean - TODO
gulp test - TODO
gulp serve - TODO
gulp bundle - TODO
gulp package-solution - TODO

@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"summary-web-part-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/summaryWebPart/SummaryWebPartWebPart.js",
"manifest": "./src/webparts/summaryWebPart/SummaryWebPartWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"SummaryWebPartWebPartStrings": "lib/webparts/summaryWebPart/loc/{locale}.js"
}
}

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "temp/deploy"
}

@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./temp/deploy/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "summary-web-part",
"accessKey": "<!-- ACCESS KEY -->"
}

@ -0,0 +1,13 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "summary-web-part-client-side-solution",
"id": "08d4adf3-23e8-426b-b19c-afe95c0a61a4",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true
},
"paths": {
"zippedPackage": "solution/summary-web-part.sppkg"
}
}

@ -0,0 +1,10 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://localhost:5432/workbench",
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
}

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
"cdnBasePath": "<!-- PATH TO CDN -->"
}

@ -0,0 +1,7 @@
'use strict';
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
build.initialize(gulp);

17136
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,41 @@
{
"name": "summary-web-part",
"version": "0.0.1",
"private": true,
"main": "lib/index.js",
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "~1.4.0",
"@microsoft/sp-lodash-subset": "~1.4.0",
"@microsoft/sp-office-ui-fabric-core": "~1.4.0",
"@microsoft/sp-webpart-base": "~1.4.0",
"@types/es6-promise": "0.0.33",
"@types/react": "15.6.6",
"@types/react-dom": "15.5.6",
"@types/webpack-env": "1.13.1",
"chart.js": "^2.9.2",
"chartjs-plugin-datalabels": "^0.7.0",
"react": "15.6.2",
"react-chartjs-2": "^2.8.0",
"react-dom": "15.6.2"
},
"resolutions": {
"@types/react": "15.6.6"
},
"devDependencies": {
"@microsoft/sp-build-web": "~1.4.1",
"@microsoft/sp-module-interfaces": "~1.4.1",
"@microsoft/sp-webpart-workbench": "~1.4.1",
"gulp": "~3.9.1",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2"
}
}

@ -0,0 +1 @@
// A file is required to be in the root of the /src directory by the TypeScript compiler

@ -0,0 +1,27 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
"id": "083aea7b-028e-4853-884d-0f0cac423575",
"alias": "SummaryWebPartWebPart",
"componentType": "WebPart",
// The "*" signifies that the version should be taken from the package.json
"version": "*",
"manifestVersion": 2,
// If true, the component can only be installed on sites where Custom Script is allowed.
// Components that allow authors to embed arbitrary script code should set this to true.
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
"requiresCustomScript": false,
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
"group": { "default": "Other" },
"title": { "default": "Сводка" },
"description": { "default": "Сводка" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "Сводка",
"requestUrl": "http://logics.portal.vertex.spb.ru/api/Project/GetSummaryProject?projCode="
}
}]
}

@ -0,0 +1,65 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-webpart-base';
import * as strings from 'SummaryWebPartWebPartStrings';
import SummaryWebPart from './components/SummaryWebPart';
import { ISummaryWebPartProps } from './components/ISummaryWebPartProps';
export interface ISummaryWebPartWebPartProps {
description: string;
requestUrl: string;
context: any;
}
export default class SummaryWebPartWebPart extends BaseClientSideWebPart<ISummaryWebPartWebPartProps> {
public render(): void {
const element: React.ReactElement<ISummaryWebPartProps > = React.createElement(
SummaryWebPart,
{
description: this.properties.description,
requestUrl: this.properties.requestUrl ? this.properties.requestUrl : 'http://logics.portal.vertex.spb.ru/api/Project/GetSummaryProject?projCode=',
context: this.context
}
);
ReactDom.render(element, this.domElement);
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: 'Настройка'
},
groups: [
{
groupName: 'Адрес запроса',
groupFields: [
PropertyPaneTextField('requestUrl', {
label: 'URL'
})
]
}
],
}
]
};
}
}

@ -0,0 +1,5 @@
export interface ISummaryWebPartProps {
description: string;
requestUrl: string;
context: any;
}

@ -0,0 +1,70 @@
import * as React from 'react';
import styles from '../SummaryGlobalComponent/SummaryGlobalComponent.module.scss'
import { DetailsList, SelectionMode, DetailsListLayoutMode } from 'office-ui-fabric-react/lib/DetailsList';
import { IMainExecItem } from '../../interfaces/IMainExecItem'
export interface IComponentProps {
structureData: IMainExecItem[]
}
export interface IComponentState {
items: {
key: number;
name: string;
department: number | string;
} [] | null
}
export interface IComponentState {
}
export default class TrafficLight extends React.Component<IComponentProps, IComponentState> {
public state = {
items: null
}
componentDidMount(){
const { structureData } = this.props;
let rows = [];
for (let i = 0; i < structureData.length; i++){
rows.push({
key: i,
name: structureData[i].name,
department: structureData[i].unit
})
}
this.setState({items: rows});
}
public onRenderFooter = () =>{
}
public render(): React.ReactElement<IComponentProps> {
const { items } = this.state;
return (
<div style={{display: 'flex', flexDirection: 'column'}}>
<DetailsList
items={items}
columns={[
{
key: 'column1',
name: 'Название',
fieldName: 'name',
minWidth: 16,
maxWidth: 150
},
{
key: 'column2',
name: 'Статус',
fieldName: 'department',
minWidth: 16,
maxWidth: 80
}
]}
compact={true}
isHeaderVisible={true}
selectionMode={SelectionMode.none}
/>
</div>
);
}
}

@ -0,0 +1,119 @@
import * as React from 'react';
import { ISummaryProjectData } from '../../interfaces/ISummaryProjectData';
import { DetailsList, SelectionMode, DetailsListLayoutMode } from 'office-ui-fabric-react/lib/DetailsList';
export interface IComponentProps{
projectInfo: ISummaryProjectData
}
export interface IComponentState {
items: {
key: number;
fieldName: string;
value: number | string;
}[] | null
}
export default class SummaryContainer extends React.Component<IComponentProps, IComponentState> {
public state = {
items: null
};
componentDidMount(){
const {projectInfo} =this.props;
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,
},
]
this.setState({items: rows})
}
public columns = [
{
key: 'column1',
name: 'Название',
fieldName: 'fieldName',
minWidth: 16,
maxWidth: 150
},
{
key: 'column2',
name: 'Значение',
fieldName: 'value',
minWidth: 16,
maxWidth: 100
},
]
public render(): React.ReactElement<IComponentProps> {
const {items} = this.state;
return (
<div>
<DetailsList
items={items}
columns={this.columns}
compact={true}
isHeaderVisible={false}
selectionMode={SelectionMode.none}
layoutMode={DetailsListLayoutMode.justified}
/>
</div>
);
}
}

@ -0,0 +1,18 @@
.SummaryPageContainer{
display: grid;
grid-template-columns: 34% 34% 30%;
column-gap: 30px;
.SummaryPageRowOne{
display: grid;
grid-template-rows: 1fr 1fr;
column-gap: 30px;
}
.SummaryPageRowTwo{
width: 100%;
}
}
.statusesContainer{
display: flex;
flex-direction: column;
}

@ -0,0 +1,32 @@
import * as React from 'react';
import styles from './SummaryGlobalComponent.module.scss'
import SummaryContainer from '../SummaryContainer/SummaryContainer';
import TrafficLight from '../TrafficLight/TrafficLight';
import TaskStatusesChart from '../TaskStatusesChart/TaskStatusesChart';
import Structure from '../Structure/Structure';
import { IPageData } from '../../interfaces/IPageData';
export interface IComponentProps{
data: IPageData
}
export default class SummaryGlobalComponent extends React.Component<IComponentProps, {}> {
public render(): React.ReactElement<IComponentProps> {
const { data } = this.props;
return (
<div className={styles.SummaryPageContainer}>
<SummaryContainer projectInfo={data.PrjInfo} />
<div className={styles.SummaryPageRowOne}>
<TrafficLight statuses={data.Status} taskStats={data.TaskStats}/>
<TaskStatusesChart taskStats={data.TaskStats}/>
</div>
<Structure structureData={data.MainExec}/>
</div>
);
}
}

@ -0,0 +1,74 @@
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
.summaryWebPart {
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
@include ms-Grid-row;
@include ms-fontColor-white;
background-color: $ms-color-themeDark;
padding: 20px;
}
.column {
@include ms-Grid-col;
@include ms-lg10;
@include ms-xl8;
@include ms-xlPush2;
@include ms-lgPush1;
}
.title {
@include ms-font-xl;
@include ms-fontColor-white;
}
.subTitle {
@include ms-font-l;
@include ms-fontColor-white;
}
.description {
@include ms-font-l;
@include ms-fontColor-white;
}
.button {
// Our button
text-decoration: none;
height: 32px;
// Primary Button
min-width: 80px;
background-color: $ms-color-themePrimary;
border-color: $ms-color-themePrimary;
color: $ms-color-white;
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
-webkit-font-smoothing: antialiased;
font-size: $ms-font-size-m;
font-weight: $ms-font-weight-regular;
border-width: 0;
text-align: center;
cursor: pointer;
display: inline-block;
padding: 0 16px;
.label {
font-weight: $ms-font-weight-semibold;
font-size: $ms-font-size-m;
height: 32px;
line-height: 32px;
margin: 0 4px;
vertical-align: top;
display: inline-block;
}
}
}

@ -0,0 +1,35 @@
import * as React from 'react';
import { ISummaryWebPartProps } from './ISummaryWebPartProps';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import SummaryGlobalComponent from './SummaryGlobalComponent/SummaryGlobalComponent'
import { IPageData } from '../interfaces/IPageData';
export interface IComponentState{
pageData: IPageData | null
isLoaded: boolean;
}
export default class SummaryWebPart extends React.Component<ISummaryWebPartProps, IComponentState > {
public state = {
pageData: null,
isLoaded: false
}
componentDidMount(){
const {requestUrl,context} = this.props;
let relUrl = context.pageContext.web.serverRelativeUrl
let projectCode = relUrl ? relUrl.split('/')[relUrl.split('/').length - 1] : '';
fetch(requestUrl + projectCode)
.then((response)=>{
return response.json()
}).then(result=>{
this.setState({ pageData: result.data, isLoaded: true})
})
}
public render(): React.ReactElement<ISummaryWebPartProps> {
const { pageData, isLoaded } = this.state;
return (isLoaded ? <SummaryGlobalComponent data={pageData} /> : <Spinner label="Подождите, идёт загрузка" ariaLive="assertive" size={SpinnerSize.large} />)
}
}

@ -0,0 +1,75 @@
import * as React from 'react';
import { Bar } from 'react-chartjs-2';
import ChartDataLabels from 'chartjs-plugin-datalabels';
export interface IComponentProps{
taskStats: {[key: string]: number;}
}
export default class TaskStatusesChart extends React.Component<IComponentProps, {}> {
public getChartData = () =>{
const { taskStats } = this.props;
return {
labels: ['Выполняемые', 'Планируемые', 'Завершенные', 'Всего задач'],
datasets: [
{
label: '',
backgroundColor: '#407855',
borderColor: '#407855',
borderWidth: 1,
data: [taskStats.exec, taskStats.plan, taskStats.compl, taskStats.plan + taskStats.compl + taskStats.exec]
}
]
};
}
public render(): React.ReactElement<IComponentProps> {
const { taskStats } = this.props;
return (
<div>
<Bar
data={this.getChartData}
plugins={ [ChartDataLabels]}
options={{
maintainAspectRatio: false,
legend: {
display: false
},
plugins: {
datalabels: {
color: '#000',
font: {
size: '10',
},
anchor: 'end',
align: 'top',
},
},
title: {
display: true,
text: 'Текущие состояние проекта',
fontSize: 16
},
scales: {
yAxes: [{
showGrid: false,
ticks: {
fontSize: 8,
suggestedMax: (taskStats.plan + taskStats.compl + taskStats.exec) + 20,
}
}],
xAxes: [{
maxBarThickness: 30,
ticks: {
fontSize: 8
}
}]
}
}}
/>
</div>
);
}
}

@ -0,0 +1,114 @@
import * as React from 'react';
import styles from '../SummaryGlobalComponent/SummaryGlobalComponent.module.scss'
import { DetailsList, SelectionMode, DetailsListLayoutMode } from 'office-ui-fabric-react/lib/DetailsList';
export interface IComponentProps{
statuses: {[key: string]: string;};
taskStats: {[key: string]: number;};
}
export default class TrafficLight extends React.Component<IComponentProps, {}> {
public renderItemColumn = (item, index: number, column) => {
const fieldContent = item[column.fieldName] as string;
if (column.key === 'column2'){
switch (item.status) {
case 'warning':
return <div style={{background: 'yellow', width: '10px', height: '10px', borderRadius: '50%', border: '1px solid #444', marginTop: '2px'}}></div>
case 'critical':
return <div style={{ background: 'red', width: '10px', height: '10px', borderRadius: '50%', border: '1px solid #444', marginTop: '2px'}}></div>
case 'normal':
return <div style={{ background: 'green', width: '10px', height: '10px', borderRadius: '50%', border: '1px solid #444', marginTop: '2px' }}></div>
}
}else{
return <span>{fieldContent}</span>;
}
}
public render(): React.ReactElement<IComponentProps> {
const { statuses, taskStats} = this.props;
let procent = (taskStats.compl/(taskStats.plan + taskStats.compl + taskStats.exec))* 100;
return (
<div className={styles.statusesContainer}>
<DetailsList
onRenderItemColumn={this.renderItemColumn}
items={
[
{
key: 1,
fieldName: 'Статус по сроку',
status: statuses.term,
},
{
key: 2,
fieldName: 'Статус по бюджету',
status: statuses.budget,
},
{
key: 3,
fieldName: 'Статус по % выполнения',
status: statuses.percCompl,
},
]
}
columns={[
{
key: 'column1',
name: 'Название',
fieldName: 'fieldName',
minWidth: 16,
maxWidth: 150
},
{
key: 'column2',
name: 'Статус',
fieldName: 'status',
minWidth: 16,
maxWidth: 80
}
]}
compact={true}
isHeaderVisible={false}
selectionMode={SelectionMode.none}
/>
<DetailsList
items={
[
{
key: 1,
start: '10.10.10',
end: '10.10.11',
time: '10.10.12'
},
]
}
columns={[
{
key: 'column1',
name: 'Дата начала',
fieldName: 'start',
minWidth: 80,
},
{
key: 'column2',
name: 'Дата окончания',
fieldName: 'end',
minWidth: 80,
},
{
key: 'column3',
name: 'Срок выполнения',
fieldName: 'time',
minWidth: 100,
}
]}
compact={true}
isHeaderVisible={true}
selectionMode={SelectionMode.none}
layoutMode={DetailsListLayoutMode.justified}
/>
<div style={{ marginLeft: '9', fontSize: '13px' }}>{`Актуальный статус выполнения ${procent.toFixed(2)}%`}</div>
</div>
);
}
}

@ -0,0 +1,4 @@
export interface IMainExecItem {
name: string;
unit: string;
}

@ -0,0 +1,9 @@
import {ISummaryProjectData} from './ISummaryProjectData'
import { IMainExecItem } from './IMainExecItem'
export interface IPageData {
PrjInfo: ISummaryProjectData;
Status: {[key: string]: string;};
TaskStats: {[key: string]: number;};
MainExec: IMainExecItem[]
}

@ -0,0 +1,15 @@
export interface ISummaryProjectData{
spID: number
status: string
chief: string
code: string
portfolio: string
programm: string
type: string
target: string
task: string
team: string[]
customer: string
curator: string
coordinator: string
}

@ -0,0 +1,7 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field"
}
});

@ -0,0 +1,10 @@
declare interface ISummaryWebPartWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'SummaryWebPartWebPartStrings' {
const strings: ISummaryWebPartWebPartStrings;
export = strings;
}

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [
"es6-promise",
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection"
]
}
}

@ -0,0 +1,30 @@
{
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"variable-name": false,
"whitespace": false
}
}
Loading…
Cancel
Save