Skip to content

Commit

Permalink
Dialog validation. Adjusting mappings on view changes. Default backlog
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismason committed Jan 12, 2018
1 parent 6d79e46 commit 44fb0c1
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 26 deletions.
14 changes: 9 additions & 5 deletions src/Kanban.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class KanbanBoardToolsAction {
modal: true
};

hostDialogService.openDialog(dialogControlContributionId, hostDialogOptions).then(dialog => {
hostDialogService.openDialog(dialogControlContributionId, hostDialogOptions, context).then(dialog => {

this._dialog = dialog;
tc.TelemetryClient.getClient(telemetrySettings).trackEvent("Dialog opened");
Expand Down Expand Up @@ -81,7 +81,11 @@ export class KanbanBoardToolsAction {
}
}

VSS.register("kanban-board-tools-menu", (context) => {
let action = new KanbanBoardToolsAction();
return action;
});
const kanbanMenuHandler = {
execute: (actionContext) => {
let action = new KanbanBoardToolsAction();
action.execute(actionContext);
}
};

VSS.register("kanban-board-tools-menu", kanbanMenuHandler);
16 changes: 10 additions & 6 deletions src/KanbanDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@ import { initializeIcons } from "@uifabric/icons";
import { DialogView } from "src/Views/Dialog/Components/DialogView";
import "./KanbanDialog.scss";

export interface KanbanDialogOptions {
onClose?: () => void;
}

export class KanbanDialog {
private _onValidationUpdated: (isValid: boolean) => void;
private kanbanDialogNode: HTMLElement;

public show(options?: KanbanDialogOptions) {
public show() {
const configuration = VSS.getConfiguration();
const boardId = configuration.id;
this.kanbanDialogNode = document.getElementById("dialogContent");
ReactDOM.render(<DialogView {...options} />, this.kanbanDialogNode);
ReactDOM.render(<DialogView id={boardId} onIsValidUpdated={this._onValidationUpdated} />, this.kanbanDialogNode);
}

public close() {
Expand All @@ -36,6 +34,12 @@ export class KanbanDialog {
public onValidationUpdated(callback: (isValid: boolean) => void) {
this._onValidationUpdated = callback;
}

private _onIsValidUpdate = (isValid: boolean) => {
if (this._onValidationUpdated) {
this._onValidationUpdated(isValid);
}
}
}

initializeIcons();
Expand Down
15 changes: 14 additions & 1 deletion src/Shared/ServicesClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ export class ServicesClient {
private _sourceTeamSettings: Models.IBoardSettings;
private _destinationTeamSettings: Models.IBoardSettings[];
private _currentMappings: IBoardColumnDifferences[];
private _currentBacklogLevel: string;

constructor() {
constructor(private _defaultBacklogLevel: string) {
this._currentTeamProperties = {
team: null,
context: null,
Expand Down Expand Up @@ -84,6 +85,17 @@ export class ServicesClient {
this._currentTeamProperties.team = await this.getTeam();
this._currentTeamProperties.context = this.getTeamContext();
this._currentTeamProperties.settings = await this.getTeamSettingsAsync(this._currentTeamProperties.context);
for (let backlogIndex = 0; backlogIndex < this._currentTeamProperties.settings.backlogSettings.length; backlogIndex++) {
const backlog = this._currentTeamProperties.settings.backlogSettings[backlogIndex];
if (backlog.boardId === this._defaultBacklogLevel) {
this._currentBacklogLevel = backlog.boardName;
break;
}
}
}

public get currentBacklogLevel(): string {
return this._currentBacklogLevel;
}

public async loadSelectedTeam(teamName: string, isMultiselect: boolean = false): Promise<void> {
Expand Down Expand Up @@ -322,6 +334,7 @@ export class ServicesClient {
cardSettings: cardSettings,
columns: columns,
rows: rows,
boardId: board.id,
fields: board !== null ? board.fields : null
};
settings.backlogSettings.push(boardSettings);
Expand Down
29 changes: 27 additions & 2 deletions src/Views/CopySettings/Actions/CopySettingsActionsCreator.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,43 @@
import { CopySettingsActionsHub } from "src/Views/CopySettings/Actions/CopySettingsActions";
import { DialogActionsCreator } from "src/Views/Dialog/Actions/DialogActionsCreator";
import { ServicesClient } from "src/Shared/ServicesClient";
import { CopyState } from "src/Views/CopySettings/Stores/CopySettingsStoreHub";
import { ViewState } from "src/Views/Dialog/Models/DialogInterfaces";

export class CopySettingsActionsCreator {
constructor(
private _copySettingsActionsHub: CopySettingsActionsHub,
private _dialogActionsCreator: DialogActionsCreator,
private _client: ServicesClient,
private _getState: () => CopyState
) { }

public loadTeams() {
this._copySettingsActionsHub.setTeamsLoading.invoke(true);
this._validateUI();
this._client.loadCurrentTeam().then(() => {
return this._client.getTeamsAsync(true);
}).then(teams => {
this._copySettingsActionsHub.setAvailableTeams.invoke(teams);
this._copySettingsActionsHub.setTeamsLoading.invoke(false);
this._validateUI();
});
}

public selectTeam(teamName: string) {
this._copySettingsActionsHub.setBacklogsLoading.invoke(true);
this._validateUI();
this._client.loadSelectedTeam(teamName).then(() => {
let commonLevels = this._client.commonBackgroundLevels;
let mappings = this._client.currentMappings;
this._copySettingsActionsHub.setAvailableBacklogLevels.invoke(commonLevels);
this._copySettingsActionsHub.setSelectedBacklogLevels.invoke(this._copyArray(commonLevels));
let defaultBoardLevel = [];
defaultBoardLevel.push(this._client.currentBacklogLevel);
this._copySettingsActionsHub.setSelectedBacklogLevels.invoke(defaultBoardLevel);
this._copySettingsActionsHub.setCurrentMappings.invoke(mappings);
this._copySettingsActionsHub.setCanDoAdvancedMapping.invoke(this._canEnableAdvancedMapping());
this._copySettingsActionsHub.setBacklogsLoading.invoke(false);
this._validateUI();
});
}

Expand All @@ -46,16 +54,19 @@ export class CopySettingsActionsCreator {
this._copySettingsActionsHub.setSelectedBacklogLevels.invoke(currentLevels);
}
this._copySettingsActionsHub.setCanDoAdvancedMapping.invoke(this._canEnableAdvancedMapping());
this._validateUI();
}

public enabledAdvancedMappings(enabled: boolean) {
this._copySettingsActionsHub.setCanDoAdvancedMapping.invoke(this._canEnableAdvancedMapping() && !enabled);
this._copySettingsActionsHub.setShowAdvancedMapping.invoke(enabled);
this._validateUI();
}

public updateViewState(viewState: ViewState) {
if (this._client.setViewState(viewState)) {

this._copySettingsActionsHub.setCurrentMappings.invoke(this._client.currentMappings);
this._validateUI();
}
}

Expand All @@ -71,4 +82,18 @@ export class CopySettingsActionsCreator {
}
return newArray;
}

private _validateUI() {
const state = this._getState();
let isValid = false;
if (!state.copySettingsState.backlogsLoading &&
!state.copySettingsState.teamsLoading &&
!state.copySettingsState.showAdvancedMappings &&
state.copySettingsState.selectedBacklogLevels &&
state.copySettingsState.selectedBacklogLevels.length >= 1
) {
isValid = true;
}
this._dialogActionsCreator.setDialogIsValid(isValid);
}
}
8 changes: 7 additions & 1 deletion src/Views/CopySettings/Components/AdvancedItemMapping.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface IAdvancedItemMappingProps {
show: boolean;
headerText: string;
onClosed: () => void;
onMappingChanged: (id: string) => void;
mappings: IBoardColumnDifferences[];
selectedLevels: string[];
}
Expand Down Expand Up @@ -94,11 +95,16 @@ export class AdvancedItemMapping extends React.Component<IAdvancedItemMappingPro
<Dropdown
options={dropdownOptions}
selectedKey={item.sourceColumn.id}
label={item.targetColumn.name} />
label={item.targetColumn.name}
onChanged={this._onMappingChanged} />
</div>
);
}

private _onMappingChanged = (item: IDropdownOption) => {
this.props.onMappingChanged(item.key.toString());
}

private _onRenderGroupHeader = (props: IGroupDividerProps): JSX.Element => {
return (
<div className={css("ms-font-xl")}>
Expand Down
12 changes: 9 additions & 3 deletions src/Views/CopySettings/Components/CopySettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ export class CopySettingsView extends React.Component<ICopySettingsViewProps, Co

const copySettingsActionsHub = new CopySettingsActionsHub();
this._copySettingsStoreHub = new CopySettingsStoreHub(copySettingsActionsHub);
this._servicesClient = new ServicesClient();
this._servicesClient = new ServicesClient(props.sharedState.dialogState.currentBoardId);
this._copySettingsActionsCreator = new CopySettingsActionsCreator(
copySettingsActionsHub,
props.sharedActions,
this._servicesClient,
this._copySettingsStoreHub.getCopyState
);

this.state = this._copySettingsStoreHub.state;
}

Expand All @@ -49,7 +49,8 @@ export class CopySettingsView extends React.Component<ICopySettingsViewProps, Co
}

public componentWillUpdate(nextProps: ICopySettingsViewProps, nextState: CopyState) {
this._servicesClient.setViewState(nextProps.sharedState.dialogState.view);
this._copySettingsActionsCreator.updateViewState(nextProps.sharedState.dialogState.view);
// this._servicesClient.setViewState(nextProps.sharedState.dialogState.view);
}

public render() {
Expand Down Expand Up @@ -90,6 +91,7 @@ export class CopySettingsView extends React.Component<ICopySettingsViewProps, Co
headerText={Constants.MappingsHeader}
onClosed={this._onAdvancedMappingClosed}
mappings={this.state.copySettingsState.currentMappings}
onMappingChanged={this._onMappingChanged}
selectedLevels={this.state.copySettingsState.selectedBacklogLevels} />
</div>
</div>
Expand All @@ -115,4 +117,8 @@ export class CopySettingsView extends React.Component<ICopySettingsViewProps, Co
private _onAdvancedMappingClosed = () => {
this._copySettingsActionsCreator.enabledAdvancedMappings(false);
}

private _onMappingChanged = (id: string) => {

}
}
1 change: 1 addition & 0 deletions src/Views/CopySettings/Models/CopySettingsInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface IBacklogBoardSettings {
cardRules: WorkContracts.BoardCardRuleSettings;
columns: WorkContracts.BoardColumn[];
rows: WorkContracts.BoardRow[];
boardId: string;
fields: WorkContracts.BoardFields;
}

Expand Down
13 changes: 11 additions & 2 deletions src/Views/Dialog/Components/DialogView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { DialogContent } from "src/Views/Dialog/Components/DialogContent";

import "./DialogView.scss";

export interface IDialogViewProps { }
export interface IDialogViewProps {
id: string;
onIsValidUpdated: (isValid: boolean) => void;
}

export class DialogView extends React.Component<IDialogViewProps, CommonDialogState> {
private _dialogActionsCreator: DialogActionsCreator;
Expand All @@ -18,7 +21,7 @@ export class DialogView extends React.Component<IDialogViewProps, CommonDialogSt
super(props);

const dialogActionsHub = new DialogActionsHub();
this._dialogStoreHub = new DialogStoreHub(dialogActionsHub);
this._dialogStoreHub = new DialogStoreHub(dialogActionsHub, props.id);
this._dialogActionsCreator = new DialogActionsCreator(dialogActionsHub);

this.state = this._dialogStoreHub.state;
Expand All @@ -32,6 +35,12 @@ export class DialogView extends React.Component<IDialogViewProps, CommonDialogSt
this._dialogStoreHub.dialogStore.removeChangedListener(this._updateDialogState);
}

public componentDidUpdate(prevProps: IDialogViewProps, prevState: CommonDialogState) {
if (this.state != null) {
this.props.onIsValidUpdated(this.state.dialogState.isDialogValid);
}
}

public render() {
return (
<DialogContent dialogActionsCreator={this._dialogActionsCreator} state={this._dialogStoreHub.state} />
Expand Down
1 change: 1 addition & 0 deletions src/Views/Dialog/Models/DialogInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export enum ViewState {
}

export interface DialogState {
currentBoardId: string;
isDialogValid: boolean;
view: ViewState;
}
14 changes: 10 additions & 4 deletions src/Views/Dialog/Stores/DialogStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ import { DialogActionsHub } from "src/Views/Dialog/Actions/DialogActions";
import { DialogState, ViewState } from "src/Views/Dialog/Models/DialogInterfaces";

export class DialogStore extends VSSStore.Store {
public state: DialogState = {
isDialogValid: false,
view: ViewState.Start
};
public state: DialogState = null;

constructor(defaultBoard: string) {
super();
this.state = {
isDialogValid: false,
view: ViewState.Start,
currentBoardId: defaultBoard
};
}

onSetDialogValid = (isValid: boolean) => {
this.state.isDialogValid = isValid;
Expand Down
5 changes: 3 additions & 2 deletions src/Views/Dialog/Stores/DialogStoreHub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ export class DialogStoreHub implements IDisposable {
public dialogStore: DialogStore;

constructor(
private _dialogActionsHub: DialogActionsHub
private _dialogActionsHub: DialogActionsHub,
private _initialBoard: string
) {
this.dialogStore = this._createDialogStore();
}

private _createDialogStore() {
const dialogStore = new DialogStore();
const dialogStore = new DialogStore(this._initialBoard);
this._dialogActionsHub.selectViewState.addListener(dialogStore.onSetViewState);
this._dialogActionsHub.setDialogValidState.addListener(dialogStore.onSetDialogValid);
return dialogStore;
Expand Down

0 comments on commit 44fb0c1

Please sign in to comment.