added some styling and async createList action

This commit is contained in:
Kemal S 2019-05-23 15:30:28 +02:00
parent 64aed858ae
commit b4e7e8b194
8 changed files with 122 additions and 32 deletions

View File

@ -1,5 +1,5 @@
import { action, computed, observable, runInAction } from "mobx";
import { RootStore } from "./RootStore";
import { observable, action, computed } from "mobx";
export enum ApplicationStatus {
Loading = "Loading",
@ -26,7 +26,7 @@ export class AppStore {
}
@action
private setInitialState() {
private setInitialState(): void {
this.status = ApplicationStatus.CreateList;
this.listTitle = null;
this.items = [];
@ -50,18 +50,27 @@ export class AppStore {
}
@action
public confirmListCreation(listTitle: string) {
this.status = ApplicationStatus.CreateItems;
this.listTitle = listTitle;
public async createList(listTitle: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
// Mock creating list
setTimeout(() => {
runInAction(() => {
this.status = ApplicationStatus.CreateItems;
this.listTitle = listTitle;
resolve();
});
}, 1000);
});
}
@action
public addListItem(item: IFakeItem) {
public addListItem(item: IFakeItem): void {
this.items.push(item);
}
@action
public confirmItems() {
public confirmItems(): void {
this.status = ApplicationStatus.Completed;
}
}

View File

@ -26,7 +26,6 @@ export class ConfigStore {
@action
private loadConfigration() {
this.isLoading = false;
this.applicationTitle = "Default Application Title";
this.allowImportantItems = true;
this.rootStore.appStore.isLoadingConfiguration = false;
}

View File

@ -21,7 +21,7 @@
"description": { "default": "An example of a webpart using mobx for managing the application state" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "MobxTutorial"
"ApplicationTitle": "Mobx Tutorial Title (change in webpart properties) 😎"
}
}]
}

View File

@ -11,14 +11,21 @@ import MobxTutorialProvider from './components/MobxTutorialProvider';
configure({ enforceActions: "always" });
export interface IMobxTutorialWebPartProps {
description: string;
ApplicationTitle: string;
}
export default class MobxTutorialWebPart extends BaseClientSideWebPart<IMobxTutorialWebPartProps> {
private readonly dependencies = { rootStore: new RootStore() };
public render(): void {
protected onInit() {
return new Promise<void>((resolve, reject) => {
const { configStore } = this.dependencies.rootStore;
configStore.setApplicationTitle(this.properties.ApplicationTitle);
resolve();
});
}
public render(): void {
const element: React.ReactElement<{}> = React.createElement(
MobxTutorialProvider,
{
@ -30,7 +37,7 @@ export default class MobxTutorialWebPart extends BaseClientSideWebPart<IMobxTuto
}
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
if (propertyPath === "Application title") {
if (propertyPath === "ApplicationTitle") {
const { configStore } = this.dependencies.rootStore;
configStore.setApplicationTitle(newValue);
}
@ -55,8 +62,8 @@ export default class MobxTutorialWebPart extends BaseClientSideWebPart<IMobxTuto
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('Application title', {
label: strings.AppTitleFieldLabel
PropertyPaneTextField('ApplicationTitle', {
label: strings.AppTitleFieldLabel,
})
]
}

View File

@ -1,3 +0,0 @@
export interface IMobxTutorialProps {
description: string;
}

View File

@ -0,0 +1,72 @@
import { inject, observer } from "mobx-react";
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import * as React from 'react';
import { AppStore } from '../../../stores/AppStore';
import { Stores } from "../../../stores/RootStore";
export type ListCreatorStoreProps = {
appStore: AppStore;
};
export type ListCreatorProps = Partial<ListCreatorStoreProps>;
export type ListCreatorState = {
loading: boolean;
errorMessage: string;
listTitle: string;
};
@inject(Stores.AppStore)
@observer
export class ListCreator extends React.Component<ListCreatorProps, ListCreatorState> {
public state = {
loading: false,
errorMessage: undefined,
listTitle: null
};
public render(): React.ReactElement<ListCreatorProps> {
const spinner = (<Spinner size={SpinnerSize.xSmall} label="Creating list ..." labelPosition="right" />);
return (
<div>
<TextField
label="List title"
errorMessage={this.state.errorMessage}
onChange={this._onChangeListTitle}
value={this.state.listTitle}
/>
<PrimaryButton
onClick={() => this.createList()}
disabled={this.state.loading}
>
{this.state.loading ? spinner : "Create List"}
</PrimaryButton>
</div>
);
}
public async createList() {
if (this.state.listTitle && this.state.listTitle.length > 0) {
this.setState({ ...this.state, loading: true, errorMessage: undefined });
await this.props.appStore.createList("MOCK TITLE");
this.setState({ ...this.state, loading: false });
}
else {
this.setState({ ...this.state, errorMessage: "Required" });
}
}
private _onChangeListTitle = (ev: React.FormEvent<HTMLInputElement>, newValue?: string) => {
if (newValue === "" && newValue.length === 0) {
this.setState({ ...this.state, listTitle: newValue, errorMessage: "Required" });
}
else {
this.setState({ ...this.state, listTitle: newValue });
}
};
}

View File

@ -9,8 +9,6 @@
.row {
@include ms-Grid-row;
@include ms-fontColor-white;
background-color: $ms-color-themeDark;
padding: 20px;
}
@ -24,17 +22,10 @@
.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 {
@ -51,7 +42,7 @@
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
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;
@ -71,4 +62,4 @@
display: inline-block;
}
}
}
}

View File

@ -6,6 +6,8 @@ import { ConfigStore } from '../../../stores/ConfigStore';
import { Stores } from '../../../stores/RootStore';
import { FakeItemContainer } from './FakeItemContainer';
import { ProgressIndicator } from './ProgressIndicator';
import { ListCreator } from './ListCreator';
import styles from './MobxTutorial.module.scss';
export type MobxTutorialStoreProps = {
appStore: AppStore;
@ -24,10 +26,23 @@ export class MobxTutorial extends React.Component<MobxTutorialProps, {}> {
return (<Spinner size={SpinnerSize.large} label="Loading... please hodl" ariaLive="assertive" labelPosition="left" />);
return (
<div>
<h1>{configStore.applicationTitle}</h1>
<ProgressIndicator></ProgressIndicator>
<FakeItemContainer></FakeItemContainer>
<div className={styles.mobxTutorial}>
<div className={styles.row}>
<div className={styles.title}>{configStore.applicationTitle}</div>
<ProgressIndicator></ProgressIndicator>
</div>
<div className={styles.row}>
<div className={styles.subTitle}>1) Create List</div>
<ListCreator></ListCreator>
</div>
<div className={styles.row}>
<div className={styles.subTitle}>2) Create Items</div>
<FakeItemContainer></FakeItemContainer>
</div>
</div>
);
}