Bucket configurator

This commit is contained in:
petkir 2020-06-20 21:53:13 +02:00
parent 4b92db1f95
commit 12903a8596
7 changed files with 230 additions and 13 deletions

View File

@ -55,7 +55,7 @@ export default class KanbanBucket extends React.Component<IKanbanBucketProps, IK
const { bucket, bucketheadline, color, buckettasks,
tasksettings, percentageComplete,
allowAddTask, overBucket, leavingTaskId, leavingBucket } = this.props;
debugger;
return (
<div
className={classNames({ [styles.bucket]: true, [styles.dragover]: !!(overBucket && overBucket === bucket) })}

View File

@ -0,0 +1,178 @@
import * as React from 'react';
//import styles from './KanbanBucketConfigurator.module.scss';
import * as strings from 'KanbanBoardStrings';
import { TextField, MaskedTextField } from 'office-ui-fabric-react/lib/TextField';
import { Stack, IStackProps, IStackStyles } from 'office-ui-fabric-react/lib/Stack';
import { Slider } from 'office-ui-fabric-react/lib/Slider';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle';
import { cloneDeep, clone, isEqual } from '@microsoft/sp-lodash-subset';
import {
ColorPicker,
ChoiceGroup,
IChoiceGroupOption,
getColorFromString,
IColor,
IColorPickerStyles,
IColorPickerProps,
PrimaryButton,
DefaultButton,
ThemeSettingName,
} from 'office-ui-fabric-react/lib/index';
import { IKanbanBucket } from './IKanbanBucket';
export interface IKanbanBucketConfiguratorProps {
index: number;
bucket: IKanbanBucket;
update: (index: number, value: IKanbanBucket) => void;
}
export interface IKanbanBucketConfiguratorState {
bucket?: IKanbanBucket;
// showHeadline: boolean;
useColor: boolean;
}
export default class KanbanBucketConfigurator extends React.Component<IKanbanBucketConfiguratorProps, IKanbanBucketConfiguratorState> {
constructor(props: IKanbanBucketConfiguratorProps) {
super(props);
this.state = {
// showHeadline: false,
useColor: false
};
}
public componentDidMount(): void {
this.resetState();
}
public componentDidUpdate(prevProps: IKanbanBucketConfiguratorProps): void {
if (prevProps.bucket && this.props.bucket && !isEqual(this.props.bucket, prevProps.bucket)) {
this.resetState();
}
}
public render(): React.ReactElement<IKanbanBucketConfiguratorProps> {
/*
const columnProps: Partial<IStackProps> = {
gap: 15,
styles: { root: { width: 300 } },
};*/
/*
const colorPickerStyles: Partial<IColorPickerStyles> = {
panel: { padding: 12 },
root: {
maxWidth: 352,
minWidth: 352,
},
colorRectangle: { height: 268 },
};*/
const statebucket = this.state.bucket;
if (!statebucket) {
return (<div></div>);
}
return (
<Stack>
<TextField label={strings.BucketConfigInternalName} disabled defaultValue={statebucket.bucket} />
{/* <Toggle label={strings.BucketConfigUseCustomHeadline} onText="On" offText="Off" inlineLabel
checked={this.state.showHeadline}
onChange={(ev, checked) => { this.setState({ showHeadline: checked }); }} />
*/}
<TextField label={strings.BucketConfigHeadline} defaultValue={statebucket.bucketheadline}
onChanged={(value: string) => {
const bucket = clone(this.state.bucket);
bucket.bucketheadline = value;
this.setState({ bucket: bucket });
}}
/>
<Slider
label={strings.BucketConfigPercentageComplete}
max={100}
value={statebucket.percentageComplete}
ariaValueText={(value: number) => `${value} ${strings.Percent}`}
valueFormat={(value: number) => `${value}%`}
showValue
onChange={(value: number) => {
const bucket = clone(this.state.bucket);
bucket.percentageComplete = value;
this.setState({ bucket: bucket });
}}
/>
<Toggle label={strings.BucketConfigAllowAddTask} onText="On" offText="Off" inlineLabel
checked={statebucket.allowAddTask}
onChange={(ev, checked) => {
const bucket = clone(this.state.bucket);
bucket.allowAddTask = checked;
this.setState({ bucket: bucket });
}} />
<Toggle label={strings.BucketConfigUseColor} onText="On" offText="Off" inlineLabel
checked={this.state.useColor}
onChange={(ev, checked) => { this.setState({ useColor: checked }); }} />
{this.state.useColor && (<ColorPicker
color={statebucket.color}
// alphaSliderHidden={false}
// showPreview={true}
onChange={(ev: any, colorObj: IColor) => {
const bucket = clone(this.state.bucket);
bucket.color = colorObj.str;
this.setState({ bucket: bucket });
}
}
// The ColorPicker provides default English strings for visible text.
// If your app is localized, you MUST provide the `strings` prop with localized strings.
/*
FluentUI
strings={{
// By default, the sliders will use the text field labels as their aria labels.
// If you'd like to provide more detailed instructions, you can use these props.
alphaAriaLabel: 'Alpha slider: Use left and right arrow keys to change value, hold shift for a larger jump',
transparencyAriaLabel:
'Transparency slider: Use left and right arrow keys to change value, hold shift for a larger jump',
hueAriaLabel: 'Hue slider: Use left and right arrow keys to change value, hold shift for a larger jump',
}}
*/
/>
)}
<Stack>
<PrimaryButton text={strings.BucketConfigSave} onClick={this.submitData.bind(this)} />
{/* <!-- TODO Confirmation --!> */}
<DefaultButton text={strings.BucketConfigReset} onClick={this.resetState.bind(this)} />
</Stack>
</Stack>
);
}
private resetState():void {
const newbucket: IKanbanBucket = clone(this.props.bucket);
this.setState({
bucket: newbucket,
// showHeadline: newbucket.bucketheadline && newbucket.bucketheadline.length > 0,
useColor: newbucket.color && newbucket.color.length > 0
});
}
private submitData():void {
debugger;
const newbucket: IKanbanBucket = clone(this.state.bucket);
if (!this.state.useColor) {
newbucket.color = undefined;
}
/*
if (!this.state.showHeadline) {
newbucket.color = undefined;
}
*/
if (this.props.update) {
this.props.update(this.props.index, newbucket);
}
}
}

View File

@ -16,7 +16,7 @@ import { IStackStyles, Stack } from 'office-ui-fabric-react/lib/Stack';
import { clone } from '@microsoft/sp-lodash-subset';
import { CommandBar } from 'office-ui-fabric-react/lib/CommandBar';
import { stringIsNullOrEmpty } from '@pnp/common';
import { TooltipHost } from 'office-ui-fabric-react';
export interface IKanbanComponentProps {
@ -86,7 +86,7 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
{
buckets.map((b) => {
const merge = { ...b, ...this.state }
const merge = { ...b, ...this.state };
return (<KanbanBucket
key={b.bucket}
{...merge}
@ -275,7 +275,7 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
private internalAddTask(targetbucket?: string) {
let bucket: IKanbanBucket = undefined;
if (bucket) {
const buckets = this.props.buckets.filter((p) => p.bucket === targetbucket)
const buckets = this.props.buckets.filter((p) => p.bucket === targetbucket);
if (buckets.length === 1) {
bucket = clone(buckets[0]);
} else {
@ -414,5 +414,5 @@ export default class KanbanComponent extends React.Component<IKanbanComponentPro
onClick: () => console.log('Info')
}
];
};
}
}

View File

@ -1,8 +1,10 @@
import * as React from 'react';
import KanbanComponent from './KanbanComponent';
import KanbanBucketConfigurator from './KanbanBucketConfigurator';
import { IKanbanBucket } from './IKanbanBucket';
import { IKanbanTask, KanbanTaskMamagedPropertyType } from './IKanbanTask';
import { findIndex } from "lodash";
import { cloneDeep, clone } from '@microsoft/sp-lodash-subset';
export interface IMockKanbanProps { }
@ -35,7 +37,7 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
value: '<p>test<b>Bold</b></p>'
},
{
name: 'Prop2',
displayName: 'Prop2 Display',
@ -69,7 +71,6 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
buckets={buckets}
tasks={tasks}
tasksettings={{
showLabels: true,
showPriority: true,
showAssignedTo: true,
showTaskDetailsButton: true
@ -82,23 +83,43 @@ export class MockKanban extends React.Component<IMockKanbanProps, IMockKanbanSta
}}
showCommandbar={true}
/>
<div>
<h2>
Bucket Configuration sample
</h2>
{
this.state.buckets.map((b, i) =>
<KanbanBucketConfigurator
key={'BucketConfig' + i}
index={i}
bucket={b}
update={this.updateBucket.bind(this)}
/>
)
}
</div>
</div>
);
}
private updateBucket(index: number, value: IKanbanBucket) {
debugger;
const cstate = cloneDeep(this.state);
cstate.buckets[index] = clone(value);
this.setState(cstate);
}
private _toggleCompleted(taskId: string): void {
private _toggleCompleted(taskId: string): void {
//TODO
}
private _allowMove(taskId: string, prevBucket: IKanbanBucket, targetBucket: IKanbanBucket): boolean {
private _allowMove(taskId: string, prevBucket: IKanbanBucket, targetBucket: IKanbanBucket): boolean {
if (prevBucket.bucket === 'Test2' && targetBucket.bucket === 'Test3') {
return false;
}
return true;
}
private _moved(taskId: string, targetBucket: IKanbanBucket): void {
private _moved(taskId: string, targetBucket: IKanbanBucket): void {
const elementsIndex = findIndex(this.state.tasks, element => element.taskId == taskId);
let newArray = [...this.state.tasks];
newArray[elementsIndex].bucket = targetBucket.bucket;

View File

@ -13,6 +13,15 @@ define([], function () {
"EditTaskDlgHeadline": "Edit Task",
"AssignedTo": "Assigned to",
"HtmlDescription": "Description",
"Priority": "Priority"
"Priority": "Priority",
"BucketConfigInternalName": "Internal Name",
"BucketConfigHeadline": "Headline",
"BucketConfigPercentageComplete": "Bucket State Percentage Complete",
"BucketConfigAllowAddTask": "Add Task?",
"BucketConfigUseColor": "Use Color?",
"BucketConfigSave": "Save",
"BucketConfigReset": "Reset",
"Percent":"percent"
}
});

View File

@ -13,7 +13,16 @@ declare interface IKanbanBoardStrings {
AssignedTo: string;
HtmlDescription: string;
Priority:string;
Priority: string;
BucketConfigInternalName: string;
BucketConfigHeadline: string;
BucketConfigPercentageComplete: string;
BucketConfigAllowAddTask: string;
BucketConfigUseColor: string;
BucketConfigSave: string;
BucketConfigReset: string;
Percent: string;
}
declare module 'KanbanBoardStrings' {