added components to display data (unfinished)

This commit is contained in:
Kemal S 2019-05-22 12:59:23 +02:00
parent 70df646e63
commit 64aed858ae
11 changed files with 108 additions and 24 deletions

View File

@ -2,6 +2,7 @@ import { RootStore } from "./RootStore";
import { observable, action, computed } from "mobx"; import { observable, action, computed } from "mobx";
export enum ApplicationStatus { export enum ApplicationStatus {
Loading = "Loading",
CreateList = "Create List", CreateList = "Create List",
CreateItems = "Create Items", CreateItems = "Create Items",
Completed = "Completed" Completed = "Completed"
@ -14,7 +15,8 @@ export interface IFakeItem {
export class AppStore { export class AppStore {
@observable public isLoading: boolean; @observable public isLoadingConfiguration: boolean;
@observable public isLoadingOtherStuff: boolean;
@observable public status: ApplicationStatus; @observable public status: ApplicationStatus;
@observable public listTitle: string; @observable public listTitle: string;
@observable public items: IFakeItem[]; @observable public items: IFakeItem[];
@ -28,7 +30,8 @@ export class AppStore {
this.status = ApplicationStatus.CreateList; this.status = ApplicationStatus.CreateList;
this.listTitle = null; this.listTitle = null;
this.items = []; this.items = [];
this.isLoading = true; this.isLoadingConfiguration = true;
this.isLoadingOtherStuff = false;
} }
@computed @computed
@ -36,6 +39,16 @@ export class AppStore {
return `The current status is: ${this.status}`; return `The current status is: ${this.status}`;
} }
@computed
public get importantItems(): IFakeItem[] {
return this.items.filter(x => x.important);
}
@computed
public get isLoading(): boolean {
return this.isLoadingConfiguration || this.isLoadingOtherStuff;
}
@action @action
public confirmListCreation(listTitle: string) { public confirmListCreation(listTitle: string) {
this.status = ApplicationStatus.CreateItems; this.status = ApplicationStatus.CreateItems;

View File

@ -1,5 +1,5 @@
import { action, observable } from "mobx";
import { RootStore } from "./RootStore"; import { RootStore } from "./RootStore";
import { observable, action, runInAction } from "mobx";
export class ConfigStore { export class ConfigStore {
@ -13,7 +13,7 @@ export class ConfigStore {
// Mock REST call for fetching configuration data, 5 seconds // Mock REST call for fetching configuration data, 5 seconds
setTimeout(() => { setTimeout(() => {
this.loadConfigration(); this.loadConfigration();
}, 5000); }, 1000);
} }
@action @action
@ -26,9 +26,9 @@ export class ConfigStore {
@action @action
private loadConfigration() { private loadConfigration() {
this.isLoading = false; this.isLoading = false;
this.applicationTitle = "So cool man"; this.applicationTitle = "Default Application Title";
this.allowImportantItems = true; this.allowImportantItems = true;
this.rootStore.appStore.isLoading = false; this.rootStore.appStore.isLoadingConfiguration = false;
} }
@action @action

View File

@ -1,5 +1,5 @@
import { ConfigStore } from "./ConfigStore";
import { AppStore } from "./AppStore"; import { AppStore } from "./AppStore";
import { ConfigStore } from "./ConfigStore";
export enum Stores { export enum Stores {
AppStore = "appStore", AppStore = "appStore",
@ -9,12 +9,9 @@ export enum Stores {
export class RootStore { export class RootStore {
public readonly appStore: AppStore; public readonly appStore: AppStore;
public readonly configStore: ConfigStore; public readonly configStore: ConfigStore;
public readonly rootStore: RootStore;
constructor() { constructor() {
this.rootStore = this;
this.configStore = new ConfigStore(this); this.configStore = new ConfigStore(this);
this.appStore = new AppStore(this); this.appStore = new AppStore(this);
} }
} }

View File

@ -5,7 +5,7 @@ import { configure } from "mobx";
import * as strings from 'MobxTutorialWebPartStrings'; import * as strings from 'MobxTutorialWebPartStrings';
import * as React from 'react'; import * as React from 'react';
import * as ReactDom from 'react-dom'; import * as ReactDom from 'react-dom';
import { IMobxTutorialProps } from './components/IMobxTutorialProps'; import { RootStore } from '../../stores/RootStore';
import MobxTutorialProvider from './components/MobxTutorialProvider'; import MobxTutorialProvider from './components/MobxTutorialProvider';
configure({ enforceActions: "always" }); configure({ enforceActions: "always" });
@ -15,16 +15,27 @@ export interface IMobxTutorialWebPartProps {
} }
export default class MobxTutorialWebPart extends BaseClientSideWebPart<IMobxTutorialWebPartProps> { export default class MobxTutorialWebPart extends BaseClientSideWebPart<IMobxTutorialWebPartProps> {
private readonly dependencies = { rootStore: new RootStore() };
public render(): void { public render(): void {
const element: React.ReactElement<{}> = React.createElement( const element: React.ReactElement<{}> = React.createElement(
MobxTutorialProvider, MobxTutorialProvider,
{ {
stores: { ...this.dependencies.rootStore }
} }
); );
ReactDom.render(element, this.domElement); ReactDom.render(element, this.domElement);
} }
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
if (propertyPath === "Application title") {
const { configStore } = this.dependencies.rootStore;
configStore.setApplicationTitle(newValue);
}
}
protected onDispose(): void { protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement); ReactDom.unmountComponentAtNode(this.domElement);
} }
@ -44,8 +55,8 @@ export default class MobxTutorialWebPart extends BaseClientSideWebPart<IMobxTuto
{ {
groupName: strings.BasicGroupName, groupName: strings.BasicGroupName,
groupFields: [ groupFields: [
PropertyPaneTextField('description', { PropertyPaneTextField('Application title', {
label: strings.DescriptionFieldLabel label: strings.AppTitleFieldLabel
}) })
] ]
} }

View File

@ -0,0 +1,22 @@
import * as React from 'react';
import { IFakeItem } from '../../../stores/AppStore';
export type DetailedFakeItemViewerProps = {
items: IFakeItem[];
};
export class DetailedFakeItemViewer extends React.Component<DetailedFakeItemViewerProps, {}> {
public state = {
items: []
};
public render(): React.ReactElement<DetailedFakeItemViewerProps> {
const { items } = this.props;
return (
<div>
<ul>{items.map(x => <li>{x.title} {x.important ? '!IMPORTANT' : null}</li>)}</ul>
</div>
);
}
}

View File

@ -0,0 +1,32 @@
import { inject, observer } from "mobx-react";
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import * as React from 'react';
import { AppStore } from "../../../stores/AppStore";
import { Stores } from '../../../stores/RootStore';
import { DetailedFakeItemViewer } from "./DetailedFakeItemViewer";
export type FakeItemContainerStoreProps = {
appStore: AppStore;
};
export type FakeItemContainerOwnProps = {};
export type FakeItemContainerProps = Partial<FakeItemContainerStoreProps> & FakeItemContainerOwnProps;
@inject(Stores.AppStore)
@observer
export class FakeItemContainer extends React.Component<FakeItemContainerProps, {}> {
public render(): React.ReactElement<FakeItemContainerProps> {
const { appStore } = this.props;
return (
<div>
<PrimaryButton
text="Add Fake Item"
onClick={() => { appStore.addListItem({ title: "dsf", important: true }); }}
allowDisabledFocus={true}
/>
Count items: {appStore.items.length} | Count important items: {appStore.importantItems.length}
<DetailedFakeItemViewer items={appStore.items}></DetailedFakeItemViewer>
</div>
);
}
}

View File

@ -1,25 +1,33 @@
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import * as React from 'react'; import * as React from 'react';
import { AppStore } from '../../../stores/AppStore'; import { AppStore } from '../../../stores/AppStore';
import { ConfigStore } from '../../../stores/ConfigStore';
import { Stores } from '../../../stores/RootStore'; import { Stores } from '../../../stores/RootStore';
import { FakeItemContainer } from './FakeItemContainer';
import { ProgressIndicator } from './ProgressIndicator'; import { ProgressIndicator } from './ProgressIndicator';
export type MobxTutorialStoreProps = { export type MobxTutorialStoreProps = {
appStore: AppStore; appStore: AppStore;
configStore: ConfigStore;
}; };
export type MobxTutorialProps = Partial<MobxTutorialStoreProps>; export type MobxTutorialProps = Partial<MobxTutorialStoreProps>;
@inject(Stores.AppStore) @inject(Stores.AppStore, Stores.ConfigurationStore)
@observer @observer
export class MobxTutorial extends React.Component<MobxTutorialProps, {}> { export class MobxTutorial extends React.Component<MobxTutorialProps, {}> {
public render(): React.ReactElement<MobxTutorialProps> { public render(): React.ReactElement<MobxTutorialProps> {
const { appStore } = this.props; const { appStore, configStore } = this.props;
if (appStore.isLoading)
return (<Spinner size={SpinnerSize.large} label="Loading... please hodl" ariaLive="assertive" labelPosition="left" />);
return ( return (
<div> <div>
{appStore.isLoading ? "LOADING" : null} <h1>{configStore.applicationTitle}</h1>
<ProgressIndicator></ProgressIndicator> <ProgressIndicator></ProgressIndicator>
<FakeItemContainer></FakeItemContainer>
</div> </div>
); );
} }

View File

@ -1,14 +1,16 @@
import { Provider } from "mobx-react"; import { Provider } from "mobx-react";
import * as React from 'react'; import * as React from 'react';
import { RootStore } from '../../../stores/RootStore';
import { MobxTutorial } from './MobxTutorial'; import { MobxTutorial } from './MobxTutorial';
export default class MobxTutorialProvider extends React.Component<{}, {}> { export type MobxTutorialProviderOwnProps = {
private readonly dependencies = { rootStore: new RootStore() }; stores: {};
};
export default class MobxTutorialProvider extends React.Component<MobxTutorialProviderOwnProps, {}> {
public render(): React.ReactElement<{}> { public render(): React.ReactElement<{}> {
return ( return (
<Provider {...this.dependencies.rootStore}> <Provider {...this.props.stores}>
<MobxTutorial></MobxTutorial> <MobxTutorial></MobxTutorial>
</Provider> </Provider>
); );

View File

@ -15,7 +15,6 @@ export type ProgressIndicatorProps = Partial<ProgressIndicatorStoreProps> & Prog
export class ProgressIndicator extends React.Component<ProgressIndicatorProps, {}> { export class ProgressIndicator extends React.Component<ProgressIndicatorProps, {}> {
public render(): React.ReactElement<ProgressIndicatorProps> { public render(): React.ReactElement<ProgressIndicatorProps> {
const { appStore } = this.props; const { appStore } = this.props;
return (<>{appStore.appStatus}</>); return (<>{appStore.appStatus}</>);
} }
} }

View File

@ -1,7 +1,7 @@
define([], function() { define([], function() {
return { return {
"PropertyPaneDescription": "Description", "PropertyPaneDescription": "Application configuration",
"BasicGroupName": "Group Name", "BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field" "AppTitleFieldLabel": "Application Title Field"
} }
}); });

View File

@ -1,7 +1,7 @@
declare interface IMobxTutorialWebPartStrings { declare interface IMobxTutorialWebPartStrings {
PropertyPaneDescription: string; PropertyPaneDescription: string;
BasicGroupName: string; BasicGroupName: string;
DescriptionFieldLabel: string; AppTitleFieldLabel: string;
} }
declare module 'MobxTutorialWebPartStrings' { declare module 'MobxTutorialWebPartStrings' {