ManagedProperties Added to Task
This commit is contained in:
parent
fa41aaad50
commit
b53b9a7f5f
|
@ -0,0 +1,8 @@
|
|||
import {IKanbanTask} from './IKanbanTask';
|
||||
import { IKanbanBucket } from './IKanbanBucket';
|
||||
|
||||
export interface IKanbanBoardRenderers{
|
||||
task?: (task:IKanbanTask) => JSX.Element ;
|
||||
bucketHeadline?: (bucket:IKanbanBucket) => JSX.Element ;
|
||||
taskDetail?: (task:IKanbanTask) => JSX.Element ;
|
||||
}
|
|
@ -2,4 +2,5 @@ export interface IKanbanBoardTaskSettings {
|
|||
showLabels: boolean;
|
||||
showPriority: boolean;
|
||||
showAssignedTo: boolean;
|
||||
showTaskDetailsButton: boolean;
|
||||
}
|
|
@ -2,5 +2,26 @@ export interface IKanbanTask {
|
|||
taskId: number | string;
|
||||
title: string;
|
||||
isCompleted?: boolean;
|
||||
bucket:string;
|
||||
bucket: string;
|
||||
mamagedProperties?: IKanbanTaskManagedProps[];
|
||||
|
||||
}
|
||||
|
||||
export interface IKanbanTaskManagedProps {
|
||||
name: string;
|
||||
displayName?: string;
|
||||
type: KanbanTaskMamagedPropertyType;
|
||||
value: any;
|
||||
renderer?: (name: string, value: object, type:KanbanTaskMamagedPropertyType) => JSX.Element;
|
||||
}
|
||||
|
||||
export enum KanbanTaskMamagedPropertyType {
|
||||
|
||||
string,
|
||||
number,
|
||||
percent,
|
||||
html,
|
||||
person,
|
||||
persons,
|
||||
complex
|
||||
}
|
|
@ -20,6 +20,9 @@ export interface IKanbanBucketProps extends IKanbanBucket {
|
|||
onDragLeave: (event, targetbucket: string) => void;
|
||||
onDrop: (event, targetbucket: string) => void;
|
||||
|
||||
|
||||
|
||||
|
||||
leavingTaskId?: number | string;
|
||||
leavingBucket?: string;
|
||||
overBucket?: string;
|
||||
|
|
|
@ -3,8 +3,16 @@ import styles from './KanbanComponent.module.scss';
|
|||
import { IKanbanTask } from './IKanbanTask';
|
||||
import { IKanbanBoardTaskSettings } from './IKanbanBoardTaskSettings';
|
||||
import { IKanbanBoardTaskActions } from './IKanbanBoardTaskActions';
|
||||
import { IKanbanBoardRenderers } from './IKanbanBoardRenderers';
|
||||
import { IKanbanBucket } from './IKanbanBucket';
|
||||
import KanbanBucket from './KanbanBucket';
|
||||
import KanbanTaskManagedProp from './KanbanTaskManagedProp';
|
||||
|
||||
import { Dialog, DialogType, DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
|
||||
import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';
|
||||
import { IStackStyles, Stack } from 'office-ui-fabric-react/lib/Stack';
|
||||
|
||||
|
||||
|
||||
import { CommandBar } from 'office-ui-fabric-react/lib/CommandBar';
|
||||
|
||||
|
@ -14,6 +22,7 @@ export interface IKanbanComponentProps {
|
|||
tasksettings: IKanbanBoardTaskSettings;
|
||||
taskactions: IKanbanBoardTaskActions;
|
||||
showCommandbar?: boolean;
|
||||
renderers?: IKanbanBoardRenderers;
|
||||
/*
|
||||
showCommandbarNew: boolean;
|
||||
allowDialog: boolean; TODO im mock
|
||||
|
@ -24,6 +33,8 @@ export interface IKanbanComponentState {
|
|||
leavingTaskId?: number | string;
|
||||
leavingBucket?: string;
|
||||
overBucket?: string;
|
||||
openDialog: boolean;
|
||||
openTaskId?: number | string;
|
||||
}
|
||||
|
||||
export default class KanbanComponent extends React.Component<IKanbanComponentProps, IKanbanComponentState> {
|
||||
|
@ -32,6 +43,7 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
openDialog: false,
|
||||
leavingTaskId: null,
|
||||
leavingBucket: null,
|
||||
overBucket: null
|
||||
|
@ -40,6 +52,7 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
|
|||
|
||||
public render(): React.ReactElement<IKanbanComponentProps> {
|
||||
const { buckets, tasks, tasksettings, taskactions, showCommandbar } = this.props;
|
||||
const { openDialog } = this.state;
|
||||
const { leavingBucket, leavingTaskId, overBucket } = this.state
|
||||
return (
|
||||
<div>
|
||||
|
@ -60,22 +73,92 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
|
|||
buckettasks={tasks.filter((x) => x.bucket == b.bucket)}
|
||||
tasksettings={tasksettings}
|
||||
taskactions={taskactions}
|
||||
openDetails={(x) => alert(x)}
|
||||
openDetails={this.openDialog.bind(this)}
|
||||
onDrop={this.onDrop.bind(this)}
|
||||
onDragLeave={this.onDragLeave.bind(this)}
|
||||
onDragOver={this.onDragOver.bind(this)}
|
||||
onDragStart={this.onDragStart.bind(this)}
|
||||
|
||||
/>)
|
||||
/>);
|
||||
|
||||
}
|
||||
|
||||
)}
|
||||
</div>
|
||||
{openDialog && (this.renderDetails())}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderDetails(): JSX.Element {
|
||||
debugger;
|
||||
const renderer = this.props.renderers && this.props.renderers.taskDetail ? this.props.renderers.taskDetail : this.internalTaskDetailRenderer;
|
||||
const tasks = this.props.tasks.filter(t => t.taskId == this.state.openTaskId);
|
||||
|
||||
if (tasks.length == 1) {
|
||||
const task = tasks[0];
|
||||
|
||||
return (<Dialog
|
||||
minWidth={600}
|
||||
hidden={!this.state.openDialog}
|
||||
onDismiss={this.closeDialog.bind(this)}
|
||||
dialogContentProps={{
|
||||
type: DialogType.largeHeader,
|
||||
title: task.title,
|
||||
subText: ''
|
||||
}}
|
||||
modalProps={{
|
||||
isBlocking: false,
|
||||
styles: { main: { minWidth: 600 } }
|
||||
}}
|
||||
>
|
||||
{renderer(task)}
|
||||
</Dialog>);
|
||||
}
|
||||
|
||||
// Error Not found or more than one
|
||||
throw "Error Not found or more than one";
|
||||
return (<div></div>);
|
||||
|
||||
}
|
||||
|
||||
private internalTaskDetailRenderer(task: IKanbanTask): JSX.Element {
|
||||
return (<Stack>
|
||||
{/* <Stack horizontal horizontalAlign="stretch">
|
||||
<Stack.Item align="auto" styles={rowStyle1}>
|
||||
<span>% Complete</span>
|
||||
</Stack.Item>
|
||||
<Stack.Item align="stretch" styles={rowStyle2}>
|
||||
<span>{task.bucket}</span>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
<KanbanTaskManagedProp name:'person' ... key={p.name+i} />
|
||||
*/}
|
||||
{task.mamagedProperties && (
|
||||
task.mamagedProperties.map((p, i) => {
|
||||
return (
|
||||
<KanbanTaskManagedProp {...p} key={p.name + i} />
|
||||
);
|
||||
})
|
||||
)}
|
||||
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
private closeDialog(ev?: React.MouseEvent<HTMLButtonElement>) {
|
||||
this.setState({
|
||||
openDialog: false,
|
||||
openTaskId: undefined
|
||||
});
|
||||
}
|
||||
private openDialog(taskid: number | string) {
|
||||
this.setState({
|
||||
openDialog: true,
|
||||
openTaskId: taskid
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private onDragLeave(event): void {
|
||||
console.log('onDragLeave');
|
||||
/* if (this.bucketRef.current.classList.contains(styles.dragover)) {
|
||||
|
@ -126,19 +209,19 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
|
|||
}*/
|
||||
if (event.dataTransfer.getData("sourcebucket") !== targetbucket) {
|
||||
const sourcebucket = event.dataTransfer.getData("sourcebucket");
|
||||
const source = this.props.buckets.filter(s=>s.bucket == sourcebucket)[0];
|
||||
const target = this.props.buckets.filter(s=>s.bucket == targetbucket)[0];
|
||||
const source = this.props.buckets.filter(s => s.bucket == sourcebucket)[0];
|
||||
const target = this.props.buckets.filter(s => s.bucket == targetbucket)[0];
|
||||
const taskId = event.dataTransfer.getData("taskId");
|
||||
if(this.props.taskactions) {
|
||||
let allowMove= true;
|
||||
if(this.props.taskactions.allowMove) {
|
||||
allowMove= this.props.taskactions.allowMove(taskId,
|
||||
if (this.props.taskactions) {
|
||||
let allowMove = true;
|
||||
if (this.props.taskactions.allowMove) {
|
||||
allowMove = this.props.taskactions.allowMove(taskId,
|
||||
source,
|
||||
target
|
||||
);
|
||||
}
|
||||
if(allowMove && this.props.taskactions.moved) {
|
||||
this.props.taskactions.moved(taskId,target);
|
||||
if (allowMove && this.props.taskactions.moved) {
|
||||
this.props.taskactions.moved(taskId, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@ import {IKanbanTask} from './IKanbanTask';
|
|||
import {IKanbanBoardTaskSettings} from './IKanbanBoardTaskSettings';
|
||||
import {IKanbanBoardTaskActions} from './IKanbanBoardTaskActions';
|
||||
import classNames from 'classnames';
|
||||
import { IconNames } from 'office-ui-fabric-react';
|
||||
|
||||
export interface IKanbanTaskProps extends IKanbanTask,IKanbanBoardTaskSettings,IKanbanBoardTaskActions {
|
||||
|
||||
|
||||
openDetails?: (taskId: number | string) => void;
|
||||
openDetails: (taskId: number | string) => void;
|
||||
onDragStart:(event) => void;
|
||||
isMoving:boolean;
|
||||
}
|
||||
|
@ -24,7 +25,7 @@ export default class KanbanTask extends React.Component<IKanbanTaskProps, IKanba
|
|||
}
|
||||
public render(): React.ReactElement<IKanbanTaskProps> {
|
||||
|
||||
const { title, showLabels, showPriority, showAssignedTo, isCompleted,isMoving } = this.props;
|
||||
const { title, showLabels, showPriority, showAssignedTo, isCompleted,isMoving,showTaskDetailsButton } = this.props;
|
||||
const showCompleted = !!this.props.toggleCompleted;
|
||||
const iconCompleted = { iconName: isCompleted ? 'RadioBtnOn' : 'RadioBtnOff' };
|
||||
return (
|
||||
|
@ -42,6 +43,15 @@ export default class KanbanTask extends React.Component<IKanbanTaskProps, IKanba
|
|||
/>)
|
||||
}
|
||||
<div className={styles.title}>{title}</div>
|
||||
{ showTaskDetailsButton && (
|
||||
<IconButton
|
||||
iconProps={{iconName:'More'}}
|
||||
title={strings.OpenDetails}
|
||||
ariaLabel={strings.OpenDetails}
|
||||
onClick={this._openDetails.bind(this)}
|
||||
/>)
|
||||
}
|
||||
|
||||
</div>
|
||||
<div className={styles.membersAndLabels}>
|
||||
{showAssignedTo && (<div className={styles.assignedto}></div>)}
|
||||
|
@ -58,5 +68,13 @@ export default class KanbanTask extends React.Component<IKanbanTaskProps, IKanba
|
|||
}
|
||||
}
|
||||
|
||||
private _openDetails():void {
|
||||
debugger;
|
||||
if(this.props.openDetails) {
|
||||
this.props.openDetails(this.props.taskId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.rowcol1{
|
||||
flex-basis: 30%;
|
||||
}
|
||||
.rowcol2{
|
||||
flex-basis: 70%;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
|
||||
|
||||
import * as React from 'react';
|
||||
import styles from './KanbanTaskManagedProp.module.scss';
|
||||
import { IKanbanTaskManagedProps, KanbanTaskMamagedPropertyType } from './IKanbanTask';
|
||||
import { IStackStyles, Stack } from 'office-ui-fabric-react/lib/Stack';
|
||||
import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser';
|
||||
|
||||
export interface IKanbanTaskManagedPropProps extends IKanbanTaskManagedProps { }
|
||||
|
||||
export interface IKanbanTaskManagedPropState { }
|
||||
|
||||
export default class KanbanTaskManagedProp extends React.Component<IKanbanTaskManagedPropProps, IKanbanTaskManagedPropState> {
|
||||
public render(): React.ReactElement<IKanbanTaskManagedPropProps> {
|
||||
const { displayName, name } = this.props;
|
||||
return (
|
||||
<Stack horizontal horizontalAlign="stretch">
|
||||
<Stack.Item align="auto" className={styles.rowcol1}>
|
||||
<span>{displayName ? displayName : name}</span>
|
||||
</Stack.Item>
|
||||
<Stack.Item align="stretch" className={styles.rowcol2}>
|
||||
{this.renderValue()}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
private renderValue() {
|
||||
const { name, type, value } = this.props;
|
||||
if (this.props.renderer) {
|
||||
return this.props.renderer(name, value, type);
|
||||
}
|
||||
switch (this.props.type) {
|
||||
case KanbanTaskMamagedPropertyType.string:
|
||||
return (<span>{value} </span>);
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.number:
|
||||
return (<span>{'' + value} </span>);
|
||||
//TODO maybe Formater
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.percent:
|
||||
return (<span>{`${(value as any) * 100}%`} </span>);
|
||||
//TODO maybe better Formater
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.html:
|
||||
return (<span>{ReactHtmlParser(value)}</span>);
|
||||
//TODO maybe better Formater
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.person:
|
||||
return (<span>TODO</span>);
|
||||
//TODO
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.persons:
|
||||
return (<span>TODO</span>);
|
||||
//TODO
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.complex:
|
||||
return (<span>{JSON.stringify(value)}</span>);
|
||||
break;
|
||||
default:
|
||||
throw "Unknow KanbanTaskMamagedPropertyType";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
import KanbanComponent from './KanbanComponent';
|
||||
import { IKanbanBucket } from './IKanbanBucket';
|
||||
import { IKanbanTask } from './IKanbanTask';
|
||||
import { IKanbanTask, KanbanTaskMamagedPropertyType } from './IKanbanTask';
|
||||
import { findIndex } from "lodash";
|
||||
|
||||
export interface IMockKanbanProps { }
|
||||
|
@ -17,19 +17,45 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
buckets:[
|
||||
{bucket:'Not Started', bucketheadline:'Not Started Head',percentageComplete:0, color:'yellow' ,allowAddTask:true},
|
||||
{bucket:'Test1', bucketheadline:'Test1 Head',percentageComplete:10, color:'orange',allowAddTask:true },
|
||||
{bucket:'Test2', bucketheadline:'Test2 Head',percentageComplete:50, color:'green' },
|
||||
{bucket:'Test3', bucketheadline:'Test3 Head',percentageComplete:50, color:'#FF0000' },
|
||||
{bucket:'Test4', bucketheadline:'Test4 Head',percentageComplete:0 ,allowAddTask:true }
|
||||
buckets: [
|
||||
{ bucket: 'Not Started', bucketheadline: 'Not Started Head', percentageComplete: 0, color: 'yellow', allowAddTask: true },
|
||||
{ bucket: 'Test1', bucketheadline: 'Test1 Head', percentageComplete: 10, color: 'orange', allowAddTask: true },
|
||||
{ bucket: 'Test2', bucketheadline: 'Test2 Head', percentageComplete: 50, color: 'green' },
|
||||
{ bucket: 'Test3', bucketheadline: 'Test3 Head', percentageComplete: 50, color: '#FF0000' },
|
||||
{ bucket: 'Test4', bucketheadline: 'Test4 Head', percentageComplete: 0, allowAddTask: true }
|
||||
],
|
||||
tasks: [
|
||||
{taskId: 1, title:'test1',bucket:'Not Started'},
|
||||
{taskId: 2, title:'test2',bucket:'Not Started'},
|
||||
{taskId: 3, title:'test3',bucket:'Not Started'},
|
||||
{taskId: '4', title:'test 4',bucket:'Test4'},
|
||||
{taskId: '5', title:'test 5',bucket:'Test3'},
|
||||
{
|
||||
taskId: 1, title: 'test1', bucket: 'Not Started',
|
||||
mamagedProperties: [
|
||||
{
|
||||
name: 'Prop1',
|
||||
displayName: 'Prop1 Display',
|
||||
type: KanbanTaskMamagedPropertyType.html,
|
||||
value: '<p>test<b>Bold</b></p>'
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
name: 'Prop2',
|
||||
displayName: 'Prop2 Display',
|
||||
type: KanbanTaskMamagedPropertyType.complex,
|
||||
value: '<p>test<b>Bold</b></p>',
|
||||
renderer: (name, value, type) => { return (<span>SampleRenderer</span>); }
|
||||
},
|
||||
{
|
||||
name: 'Prop3',
|
||||
displayName: 'String',
|
||||
type: KanbanTaskMamagedPropertyType.string,
|
||||
value: 'Hallo World'
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
{ taskId: 2, title: 'test2', bucket: 'Not Started' },
|
||||
{ taskId: 3, title: 'test3', bucket: 'Not Started' },
|
||||
{ taskId: '4', title: 'test 4', bucket: 'Test4' },
|
||||
{ taskId: '5', title: 'test 5', bucket: 'Test3' },
|
||||
|
||||
]
|
||||
};
|
||||
|
@ -45,7 +71,8 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
|
|||
tasksettings={{
|
||||
showLabels: true,
|
||||
showPriority: true,
|
||||
showAssignedTo: true
|
||||
showAssignedTo: true,
|
||||
showTaskDetailsButton: true
|
||||
}
|
||||
}
|
||||
taskactions={{
|
||||
|
@ -62,10 +89,10 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
|
|||
|
||||
|
||||
private _toggleCompleted(taskId: number | string): void {
|
||||
//TODO
|
||||
//TODO
|
||||
}
|
||||
private _allowMove(taskId: number | string, prevBucket: IKanbanBucket, targetBucket: IKanbanBucket): boolean {
|
||||
if(prevBucket.bucket ==='Test2' && targetBucket.bucket ==='Test3') {
|
||||
if (prevBucket.bucket === 'Test2' && targetBucket.bucket === 'Test3') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -73,10 +100,10 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
|
|||
|
||||
private _moved(taskId: number | string, targetBucket: IKanbanBucket): void {
|
||||
debugger;
|
||||
const elementsIndex = findIndex( this.state.tasks ,element => element.taskId == taskId );
|
||||
const elementsIndex = findIndex(this.state.tasks, element => element.taskId == taskId);
|
||||
let newArray = [...this.state.tasks];
|
||||
newArray[elementsIndex].bucket = targetBucket.bucket;
|
||||
this.setState({tasks:newArray});
|
||||
this.setState({ tasks: newArray });
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"CompleteButton": "complete",
|
||||
"IsCompleted": "IsCompleted",
|
||||
"IsNotCompleted": "IsNotCompleted",
|
||||
"AddTask": "AddTask"
|
||||
"CompleteButton": "Complete",
|
||||
"IsCompleted": "Is Completed",
|
||||
"IsNotCompleted": "Is Not Completed",
|
||||
"AddTask": "Add Task",
|
||||
"OpenDetails":"Open Details"
|
||||
}
|
||||
});
|
|
@ -3,6 +3,7 @@ declare interface IKanbanBoardStrings {
|
|||
IsCompleted: string;
|
||||
IsNotCompleted: string;
|
||||
AddTask: string;
|
||||
OpenDetails: string;
|
||||
}
|
||||
|
||||
declare module 'KanbanBoardStrings' {
|
||||
|
|
Loading…
Reference in New Issue