new buttons with perm and disp

VRTKSSUP-229
Осьмаков Денис 5 years ago
parent 1d7ea3c156
commit 40a53f7d99
  1. 145
      src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.module.scss
  2. 265
      src/webparts/summaryWebPart/components/RejectTasks/RejectTasks.tsx
  3. 3
      src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.scss
  4. 11
      src/webparts/summaryWebPart/components/SummaryContainer/SummaryContainer.tsx
  5. 10
      src/webparts/summaryWebPart/components/SummaryGlobalComponent/SummaryGlobalComponent.module.scss
  6. 53
      src/webparts/summaryWebPart/components/SummaryWebPart.tsx
  7. 2
      src/webparts/summaryWebPart/components/TaskStatusesChart/TaskStatusesChart.tsx
  8. 4
      src/webparts/summaryWebPart/interfaces/IDeviationTasks.ts

@ -1,123 +1,64 @@
.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;
min-width: 350px;
border-collapse:collapse;
caption-side:bottom;
table-layout: fixed;
overflow: hidden;
white-space: nowrap;
thead {
tr {
th{
padding: 6px;
border: 1px solid #c8c8c8;
font-family: "Segoe UI Web (West European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif;
color: #767676;
font-size: 13px;
font-weight: bold;
transition: 0.5s;
white-space: normal;
word-break: break-all;
cursor: pointer;
&:hover {
background: #f4f4f4;
color: #666666;
transition: 0.5s;
}
}
}
.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;
.commonTbody {
tr {
td {
padding: 6px;
border: 1px solid #c8c8c8;
font-family: "Segoe UI Web (West European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif;
color: #767676;
border-bottom: 1px solid #c8c8c8;
display: flex;
align-items: center;
justify-content: center;
/* max-width: 100px; */
font-size: 13px;
transition: 0.5s;
cursor: pointer;
&:hover {
background: #f4f4f4;
color: #666666;
transition: 0.5s;
}
span {
/* white-space: nowrap; */
div {
width: 99%;
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;
background: #ff000042;
&:hover {
background: #ff0000ab;
color: #4b4b4b;
transition: .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;
}

@ -1,203 +1,160 @@
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<IComponentProps, IComponentState> {
export default class DeviationTaskTable extends React.Component<IComponentProps, IComponentState> {
private _renderHeaderCell(): JSX.Element {
private _renderHeaderTable(): JSX.Element {
return (
<div className={styles.thead}>
<div className={styles.th + ' ' + styles.Departments}>
Подразделение
</div>
<div className={styles.th + ' ' + styles.Managers}>
Руководитель
</div>
<div className={styles.th + ' ' + styles.Members}>
Участник
</div>
<div className={styles.count + ' ' + styles.th}>
Кол-во задач
</div>
</div>
<thead>
<tr>
<th>
Подразделение
</th>
<th>
Руководитель
</th>
<th>
Участник
</th>
<th style={{width:"50px"}}>
Кол-во задач
</th>
</tr>
</thead>
)
}
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 (
<div className={styles.cell + ' ' + styles[className] + ' ' + styles[critClassName]} style={{height}}><span>{value}</span></div>
)
}
private _renderCell(structureData:any,i:number): JSX.Element {
private _renderBodyTable(structureData:any): JSX.Element {
var Departments = [] //Подразделения
var Managers = [] //Руководители
var Members = [] //Участники
var MembersTaskCount = [] //Кол-во задач
var structureTable = [] //В этом массив пушиться вся структура таблицы (tr td)
// Прохожусь по всему приходящему массиву. Через функции _cell() и _customCell пушу ячеейки в structureTable. Так же в этой фунции определяться rowSpan и сокращаеться value до ФИО
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]
for (let i = 0; i < structureData.Departments.length; i++) {
// Формула rowSpan
let rowSpan = 0;
structureData.Departments[i].Managers.forEach(function(e) {
rowSpan = rowSpan + (e.Members.length+1);
})
// Конец формуле
structureTable.push(this._cell(structureData.Departments[i].Name, rowSpan+1 , 'Departments',true))
if(structureData.Departments[i].Managers){
for (let index = 0; index < structureData.Departments[i].Managers.length; index++) {
if(ManagersName[2]){
let menagers = structureData.Departments[i].Managers[index].Name;
let patronymic = ManagersName[1].split('')[0] + '.'
ManagersName = surname + ' ' + name + ' ' + patronymic
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
ManagersName = surname + ' ' + name;
}
let maxLength = 0
let maxLength = 0;
structureData.Departments[i].Managers.forEach(function(e) {
maxLength = maxLength + e.Members.length
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)
structureTable.push(
this._cell( ManagersName ,structureData.Departments[i].Managers[index].Members.length+1,'Managers')
)
} else {
structureTable.push(
this._cell( ' ' ,structureData.Departments[i].Managers[index].Members.length+1,'Managers')
)
//Пушу ячейки
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)
)
}
}
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
}
}
let isCrit = structureData.Departments[i].Managers[index].Members[counter].Crit
structureTable.push(
this._customCell( MembersName , structureData.Departments[i].Managers[index].Members[counter].TaskCount,isCrit)
)
}
}
}
}
}
}
}
}
return (
<div className={styles.tbody}>
<div className={styles.td}>
{
Departments
}
</div>
<div className={styles.td}>
{
Managers
}
</div>
<div className={styles.td}>
{
Members
}
</div>
<div className={styles.MembersTaskCount + ' ' + styles.td}>
{
MembersTaskCount
}
</div>
</div>
<tbody className={styles.commonTbody} >
{structureTable}
</tbody>
)
}
private _renderBodyTable(structureData:any,): JSX.Element {
var body = []
for (let i = 0; i < structureData.Departments.length; i++) {
body.push(this._renderCell(structureData, i))
}
return (
<div>{body}</div>
private _cell(value:string,length:any,className:string,row?:boolean,): JSX.Element {
)
return (
<tr><td rowSpan={length} ><div><span>{value}</span></div></td></tr>
)
}
componentDidMount(){
private _customCell(membersValue:string,countValue:string,crit?:boolean): JSX.Element {
let critClassName = '';
if(crit) {
critClassName = 'isCrit';
}
return (
<tr style={ {height:"25px"}}>
<td className={styles[critClassName]}><div><span>{membersValue}</span></div></td >
<td className={styles[critClassName]} style={{textAlign:"center"}}><div><span>{countValue}</span></div></td >
</tr>
)
}
public onRenderFooter = () =>{
}
public render(): React.ReactElement<IComponentProps> {
return (
<div style={{display: 'flex', justifyContent: 'center',minWidth:' 360px'}}>
<div>
<div className={styles.commonTable}>
<div>
{this._renderHeaderCell()}
</div>
<div>
{
this._renderBodyTable(this.props.structureData)
}
</div>
</div>
</div>
</div>
<table className={styles.commonTable}>
{this._renderHeaderTable()}
{this._renderBodyTable(this.props.structureData)}
</table>
);
}
}

@ -0,0 +1,3 @@
.ms-DetailsRow-cell {
white-space: pre-line;
}

@ -1,6 +1,7 @@
import * as React from 'react';
import { ISummaryProjectData } from '../../interfaces/ISummaryProjectData';
import styles from '../SummaryWebPart.module.scss'
import styles from '../SummaryWebPart.module.scss';
import '../SummaryContainer/SummaryContainer.scss'
import {
DetailsList,
SelectionMode,
@ -149,7 +150,13 @@ export default class SummaryContainer extends React.Component<IComponentProps,IC
items.forEach(function(e) {
if(e.fieldName == 'Внешний исполнитель') {
e.value = e.value.split(';#').join(' ')
let value = []
e.value.split(';#').forEach(function(item) {
if(item) {
value.push(item)
}
})
e.value = value.join('\n')
}
})
return (

@ -1,7 +1,7 @@
.SummaryPageContainer{
display: flex;
justify-content: space-between;
min-width: 1159px;
min-width: 1060px;
div{
.Title {
text-align: center;
@ -11,14 +11,14 @@
}
.SummaryPageColumnOne{
width: 100%;
width: calc(33% - 15px);
}
.SummaryPageColumnTwo{
width: 100%;
margin: 0 25px;
width: calc(33% - 10px);
margin: 0 20px;
}
.SummaryPageColumnThree{
width: 100%;
width: calc(33% - 15px);
}
.SummaryPageRowOne{

@ -12,6 +12,7 @@ export interface IComponentState{
isBlank: boolean;
prjID: string | number;
isPerm: boolean;
isPermConfigButton: boolean;
noPermDiv: any;
}
@ -22,6 +23,7 @@ export default class SummaryWebPart extends React.Component<ISummaryWebPartProps
isBlank: false,
prjID: '',
isPerm: false,
isPermConfigButton: false,
noPermDiv: <div></div>
}
@ -49,20 +51,26 @@ export default class SummaryWebPart extends React.Component<ISummaryWebPartProps
document.body.appendChild(scripts);
let relUrl = context.pageContext.web.serverRelativeUrl;
let projectCode = relUrl ? relUrl.split('/')[relUrl.split('/').length - 1] : ''; /* 'UNI_UNI_018' */
let projectCode = relUrl ? relUrl.split('/')[relUrl.split('/').length - 1] : ''; /* 'NEW_UNI_002' */
let web = new Web('http://portal.vertex.spb.ru/PMIS');
let thisWeb = new Web('http://portal.vertex.spb.ru/PMIS/' + projectCode);
thisWeb.lists.getByTitle('CustomPerm').items.get().then(e => {
if(e.length){
this.setState({ isPerm: true })
}else{
thisWeb.lists.getByTitle('CustomPerm').items.get().then((e:any) => {
let permWP = null;
e.forEach(el=>{
if (el.Title == 'PermEdit') this.setState({isPermConfigButton: true})
if (el.Title == 'WPSummary') this.setState({ isPerm: true }); permWP = true;
})
if (!permWP){
this.setState({
noPermDiv: <MessageBar messageBarType={MessageBarType.error} isMultiline={false} dismissButtonAriaLabel="Close">
{'Отсутствует доступ к странице'}
</MessageBar>})
}
})
web.lists.getById('eeba7db6-4c28-41a2-a54e-82a2aaf0ca15').items.filter("Code_project eq '" + projectCode +"'").select('ID').get().then(e=>{
@ -77,28 +85,41 @@ export default class SummaryWebPart extends React.Component<ISummaryWebPartProps
})
}
public relocate = () => {
public relocate = (loc:string) => {
const { prjID } = this.state;
location.href = 'http://portal.vertex.spb.ru/PMIS/SitePages/EditForm.aspx?itemId=' + prjID;
location.href = `http://portal.vertex.spb.ru/PMIS/SitePages/${loc}.aspx?itemId=${prjID}`;
}
public render(): React.ReactElement<ISummaryWebPartProps> {
const { pageData, isLoaded, isBlank, isPerm, noPermDiv } = this.state;
const { pageData, isLoaded, isBlank, isPerm, noPermDiv, isPermConfigButton } = this.state;
return isPerm ? isLoaded ? (
return isPerm || isPermConfigButton ? isLoaded ? (
<div style={{ display: "flex", flexDirection: "column", overflowX: 'auto' }}>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<PrimaryButton
text="Изменение карточки проекта"
onClick={this.relocate}
style={{fontSize: '13px'}}
/>
<div>
{isPermConfigButton ? <PrimaryButton
text="Настройка прав проекта"
onClick={()=>this.relocate('PermForm')}
style={{fontSize: '13px'}}
/> : null}
{isPerm && <PrimaryButton
text="Изменение карточки проекта"
onClick={()=>this.relocate('EditForm')}
style={{ fontSize: '13px', marginRight: '10px', marginLeft: '10px'}}
/>}
<PrimaryButton
text="Просмотреть все свойства"
onClick={() => this.relocate('DispForm')}
style={{ fontSize: '13px' }}
/>
</div>
</div>
<SummaryGlobalComponent
{isPerm && <SummaryGlobalComponent
data={pageData}
rowsOrder={this.props.rowsOrder}
context={this.props.context}
/>
/>}
</div>
) : isBlank ? (
<div></div>

@ -27,7 +27,7 @@ export default class TaskStatusesChart extends React.Component<IComponentProps,
}
public render(): React.ReactElement<IComponentProps> {
const { taskStats } = this.props;
let chartTitle = 'Текущee состояние проекта (выполняемых задач: '+( Number(taskStats.exec) + Number(taskStats.plan) + Number(taskStats.compl))+' шт.)'
let chartTitle = 'Текущee состояние проекта (всего задач: '+( Number(taskStats.exec) + Number(taskStats.plan) + Number(taskStats.compl))+' шт.)'
return (
<div >
<div><h1 style={{textAlign: 'center', fontSize: '13px', color: '#666',textTransform: 'uppercase'}}>{chartTitle}</h1></div>

@ -1,4 +1,4 @@
export interface DeviationTasks {
Departments: any;
}
Departments: any;
}
Loading…
Cancel
Save