Skip to content

Instantly share code, notes, and snippets.

@ypcode
Created December 29, 2017 20:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ypcode/90545dc7a3d30ebc6a90547da8bfc17f to your computer and use it in GitHub Desktop.
Save ypcode/90545dc7a3d30ebc6a90547da8bfc17f to your computer and use it in GitHub Desktop.
import * as React from 'react';
import styles from './WebApiClient.module.scss';
import { IWebApiClientProps } from './IWebApiClientProps';
import { escape } from '@microsoft/sp-lodash-subset';
import {
CommandBar,
DetailsList,
ISelection,
Selection,
SelectionMode,
Panel,
TextField,
PrimaryButton,
DefaultButton
} from 'office-ui-fabric-react';
import { IBusinessDocument } from '../../../entities/IBusinessDocument';
import { BusinessDocumentsServiceKey, IBusinessDocumentsService } from '../../../services/BusinessDocumentsService';
import { ApiConfigServiceKey, IApiConfigService } from '../../../services/ApiConfigService';
export interface IWebApiClientState {
businessDocuments?: IBusinessDocument[];
selectedDocument?: IBusinessDocument;
selection?: ISelection;
isAdding?: boolean;
isEditing?: boolean;
selectedView?: 'All' | 'My';
}
export default class WebApiClient extends React.Component<IWebApiClientProps, IWebApiClientState> {
private businessDocsService: IBusinessDocumentsService;
private apiConfig: IApiConfigService;
private authenticated: boolean;
constructor(props: IWebApiClientProps) {
super(props);
this.state = {
businessDocuments: [],
selectedDocument: null,
isAdding: false,
isEditing: false,
selectedView: 'All',
selection: new Selection({
onSelectionChanged: this._onSelectionChanged.bind(this)
})
};
}
public componentWillMount() {
this.props.serviceScope.whenFinished(() => {
this.businessDocsService = this.props.serviceScope.consume(BusinessDocumentsServiceKey);
this.apiConfig = this.props.serviceScope.consume(ApiConfigServiceKey);
this._loadDocuments();
});
}
private _loadDocuments(stateRefresh?: IWebApiClientState, forceView?: 'All' | 'My') {
let { selectedView } = this.state;
let effectiveView = forceView || selectedView;
// After being authenticated
this._executeOrDelayUntilAuthenticated(() => {
switch (effectiveView) {
case 'All':
// Load all business documents when component is being mounted
this.businessDocsService.getAllBusinessDocuments().then((docs) => {
let state = stateRefresh || {};
state.businessDocuments = docs;
this.setState(state);
});
break;
case 'My':
// Load My business documents when component is being mounted
this.businessDocsService.getMyBusinessDocuments().then((docs) => {
let state = stateRefresh || {};
state.businessDocuments = docs;
this.setState(state);
});
break;
}
});
}
private _executeOrDelayUntilAuthenticated(action: Function): void {
if (this.authenticated) {
console.log('Is authenticated');
action();
} else {
console.log('Still not authenticated');
setTimeout(() => {
this._executeOrDelayUntilAuthenticated(action);
}, 1000);
}
}
private _onSelectionChanged() {
let { selection } = this.state;
let selectedDocuments = selection.getSelection() as IBusinessDocument[];
let selectedDocument = selectedDocuments && selectedDocuments.length == 1 && selectedDocuments[0];
console.log('SELECTED DOCUMENT: ', selectedDocument);
this.setState({
selectedDocument: selectedDocument || null
});
}
private _buildCommands() {
let { selectedDocument } = this.state;
const add = {
key: 'add',
name: 'Create',
icon: 'Add',
onClick: () => this.addNewBusinessDocument()
};
const edit = {
key: 'edit',
name: 'Edit',
icon: 'Edit',
onClick: () => this.editCurrentBusinessDocument()
};
const remove = {
key: 'remove',
name: 'Remove',
icon: 'Remove',
onClick: () => this.removeCurrentBusinessDocument()
};
let commands = [ add ];
if (selectedDocument) {
commands.push(edit, remove);
}
return commands;
}
private _buildFarCommands() {
let { selectedDocument, selectedView } = this.state;
const views = {
key: 'views',
name: selectedView == 'All' ? 'All' : "I'm in charge of",
icon: 'View',
subMenuProps: {
items: [
{
key: 'viewAll',
name: 'All',
icon: 'ViewAll',
onClick: () => this.selectView('All')
},
{
key: 'inChargeOf',
name: "I'm in charge of",
icon: 'AccountManagement',
onClick: () => this.selectView('My')
}
]
}
};
let commands = [ views ];
return commands;
}
public selectView(view: 'All' | 'My') {
this.setState({
selectedView: view
});
this._loadDocuments(null, view);
}
public addNewBusinessDocument() {
this.setState({
isAdding: true,
selectedDocument: {
Id: 0,
Name: 'New document.docx',
Purpose: '',
InCharge: ''
}
});
}
public editCurrentBusinessDocument() {
let { selectedDocument } = this.state;
if (!selectedDocument) {
return;
}
this.setState({
isEditing: true
});
}
public removeCurrentBusinessDocument() {
let { selectedDocument } = this.state;
if (!selectedDocument) {
return;
}
if (confirm('Are you sure ?')) {
this._executeOrDelayUntilAuthenticated(() => {
this.businessDocsService
.removeBusinessDocument(selectedDocument.Id)
.then(() => {
alert('Document is removed !');
this._loadDocuments();
})
.catch((error) => {
console.log(error);
alert('Document CANNOT be removed !');
});
});
}
}
private onValueChange(property: string, value: string) {
let { selectedDocument } = this.state;
if (!selectedDocument) {
return;
}
selectedDocument[property] = value;
}
private onApply() {
let { selectedDocument, isAdding, isEditing } = this.state;
if (isAdding) {
this._executeOrDelayUntilAuthenticated(() => {
this.businessDocsService
.createBusinessDocument(selectedDocument)
.then(() => {
alert('Document is created !');
this._loadDocuments({
selectedDocument: null,
isAdding: false,
isEditing: false
});
})
.catch((error) => {
console.log(error);
alert('Document CANNOT be created !');
});
});
} else if (isEditing) {
this._executeOrDelayUntilAuthenticated(() => {
this.businessDocsService
.updateBusinessDocument(selectedDocument.Id, selectedDocument)
.then(() => {
alert('Document is updated !');
this._loadDocuments({
selectedDocument: null,
isAdding: false,
isEditing: false
});
})
.catch((error) => {
console.log(error);
alert('Document CANNOT be updated !');
});
});
}
}
private onCancel() {
this.setState({
selectedDocument: null,
isAdding: false,
isEditing: false
});
}
public render(): React.ReactElement<IWebApiClientProps> {
let { businessDocuments, selection, selectedDocument, isAdding, isEditing } = this.state;
return (
<div className={styles.webApiClient}>
<div className={styles.container}>
<iframe
src={this.apiConfig.appRedirectUri}
style={{ display: 'none' }}
onLoad={() => (this.authenticated = true)}
/>
<CommandBar items={this._buildCommands()} farItems={this._buildFarCommands()} />
<DetailsList
items={businessDocuments}
columns={[
{
key: 'id',
name: 'Id',
fieldName: 'Id',
minWidth: 15,
maxWidth: 30
},
{
key: 'docName',
name: 'Name',
fieldName: 'Name',
minWidth: 100,
maxWidth: 200
},
{
key: 'docPurpose',
name: 'Purpose',
fieldName: 'Purpose',
minWidth: 100,
maxWidth: 200
},
{
key: 'inChargeOf',
name: "Who's in charge",
fieldName: 'InCharge',
minWidth: 100,
maxWidth: 200
}
]}
selectionMode={SelectionMode.single}
selection={selection}
/>
{selectedDocument &&
(isAdding || isEditing) && (
<Panel isOpen={true}>
<TextField
label="Name"
value={selectedDocument.Name}
onChanged={(v) => this.onValueChange('Name', v)}
/>
<TextField
label="Purpose"
value={selectedDocument.Purpose}
onChanged={(v) => this.onValueChange('Purpose', v)}
/>
<TextField
label="InCharge"
value={selectedDocument.InCharge}
onChanged={(v) => this.onValueChange('InCharge', v)}
/>
<PrimaryButton text="Apply" onClick={() => this.onApply()} />
<DefaultButton text="Cancel" onClick={() => this.onCancel()} />
</Panel>
)}
</div>
</div>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment