Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
// When enabled, will trim trailing whitespace when you save a file.
"files.trimTrailingWhitespace": true,

// Controls if the editor should automatically close brackets after opening them
"editor.autoClosingBrackets": false,
// Controls if the editor should automatically close brackets after opening them
"editor.autoClosingBrackets": false,

// Controls whether the editor should render whitespace characters
"editor.renderWhitespace": true,

// Controls if the editor will insert spaces for tabs. Accepted values: "auto", true, false. If set to "auto", the value will be guessed when a file is opened.
"editor.insertSpaces": true,
// Controls if the editor will insert spaces for tabs. Accepted values: "auto", true, false. If set to "auto", the value will be guessed when a file is opened.
"editor.insertSpaces": true,

"files.exclude": {
"**/.git": true,
Expand Down
8 changes: 8 additions & 0 deletions examples/todo-app/gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

let build = require('web-library-build');

build.tslint.isEnabled = () => false;
build.sass.isEnabled =() => true;

build.initialize(require('gulp'));
17 changes: 17 additions & 0 deletions examples/todo-app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<title>Test Page</title>

<link rel="stylesheet" type="text/css" href="https://appsforoffice.microsoft.com/fabric/2.2.0/fabric.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react-dom.min.js"></script>
</head>
<body>
<script type="text/javascript" src="dist/fabric-react-example.js"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions examples/todo-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "fabric-react-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"react-addons-update": "^0.14.0",
"web-library-build": "^0.1.3"
},
"dependencies": {
"es6-promise": "^3.2.1",
"load-themed-styles": "^1.2.0",
"office-ui-fabric": "^2.6.1",
"office-ui-fabric-react": "^0.33.0",
"react": "^0.14.0",
"react-dom": "^0.14.0"
}
}
166 changes: 166 additions & 0 deletions examples/todo-app/src/DataProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import update = require('react-addons-update');
import { findIndex } from 'office-ui-fabric-react/lib/utilities/array';
import { ITodoItem, IDataProvider } from './types/index';

const ADD_ITEMS_DELAY = 500;

/**
* DataProvider the class used to maintain the client side data.
*
* It interact with data provider to sync data items with sharepoint list.
* It also maintain the loading state to tell React Component once the action is
* started of finished.
*/
export default class DataProvider implements IDataProvider {
/**
* The counter used to identify the latest server call.
* If the current call is not the latest one, we don't want to update the list
* to mess up with the out of date data with data in this store.
*/
private _items: ITodoItem[];
private _isLoading: boolean;
private _listeners: Array<() => void>;

/**
* The items store in the local. It only contains the data recently fetched from server.
*/
public get items(): Array<ITodoItem> { return this._items; }
public set items(value: Array<ITodoItem>) {
this._items = value;
this._emitChange();
}

/**
* Whether there is unfinished server request currently.
*/
public get isLoading(): boolean { return this._isLoading; }
public set isLoading(value: boolean) {
this._isLoading = value;
this._emitChange();
}

constructor() {
this._items = [
{
id: '61b59681-2a82-4a51-b221-8c35e333ae89',
title: 'Finish Sample Todo web part before dev kitchen',
isComplete: false
},
{
id: '94a844ae-0c6a-4820-8042-dbc386bdf930',
title: 'Finish All the work in Todo web part before dev kitchen',
isComplete: false
},
{
id: '5fa55618-90f9-4b5f-b12d-60c9fb1fc7f0',
title: 'SharePoint API investigation for Todo web part',
isComplete: true
},
{
id: '2ae54c74-1395-4a49-8dd2-4857efdd0e5e',
title: 'Bug fixing of Pivot Control',
isComplete: true
}
];
this._isLoading = false;

this._listeners = [];
this.createItem = this.createItem.bind(this);
this.deleteItem = this.deleteItem.bind(this);
this.toggleComplete = this.toggleComplete.bind(this);
}

/**
* Create a new item and add it to the list through data provider.
*/
public createItem(title: string): Promise<ITodoItem[]> {
this.isLoading = true;

return new Promise<ITodoItem[]>((resolve) => {
const newItem: ITodoItem = {
id: this._generateGuid(),
title: title,
isComplete: false
};

setTimeout(() => {
this.items = this.items.concat(newItem);
this.isLoading = false;
resolve(this.items);
}, ADD_ITEMS_DELAY);
});
}

/**
* Delete a item from the list through data provider.
*/
public deleteItem(delItem: ITodoItem): Promise<ITodoItem[]> {
return new Promise<ITodoItem[]>((resolve) => {
this.items =
this.items.filter((item: ITodoItem) => item.id !== delItem.id);
resolve(this.items);
});
}

/**
* Toggle the complete state of an item by.
*
* Will call updateItem function to update complete state of this item.
*/
public toggleComplete(item: ITodoItem): Promise<ITodoItem[]> {
// Create a new Item in which the PercentComplete value has been changed.
const newItem: ITodoItem = update(item, {
isComplete: { $set: item.isComplete === true ? false : true }
});

return new Promise<ITodoItem[]>((resolve, reject) => {
const index: number =
findIndex(
this.items,
(item: ITodoItem) => item.id === newItem.id
);
if (index !== -1) {
this.items[index] = newItem;
this.items = this.items.slice(0);
resolve(this.items);
} else {
reject(new Error(`Item to update doesn't exist.`));
}
});
}

/**
* Add listener to the provider.
*
* Once the store has a change of state and emit that change, the listeners will be called.
*/
public addListener(listener: () => void): void {
this._listeners.push(listener);
}

/**
* Remove the registered listener.
*
* You must remove the listener registered by addListener method when you are not going to use it anymore.
*/
public removeListener(listener: () => void): void {
const listenerIdx: number = this._listeners.indexOf(listener);
if (listenerIdx > -1) {
this._listeners.splice(listenerIdx, 1);
}
}

/**
* Emit the changes in the store to all listeners.
*/
private _emitChange(): void {
this._listeners.forEach((listener: () => void) => listener());
}

private _generateGuid(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
}
93 changes: 93 additions & 0 deletions examples/todo-app/src/components/Todo.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
@import "../../node_modules/office-ui-fabric/dist/sass/Fabric.Common";

.todo {
padding: 28px 40px 60px 40px;
max-width: 640px;
margin: 0 auto;
border: 2px $ms-color-neutralLighter solid;
@include ms-font-m;

.topRow {
position: relative;
}

.todoHeading {
display: inline-block;
}

.todoPivot {
padding-top: 24px;
}

.todoForm {
display: table-row;

.textField {
display: table-cell;
width: 100%;
}
.addButton {
display: table-cell;
@include margin-left(16px);
white-space: nowrap;
}
}

.todoList {
margin-top: 20px;
border-top: 1px $ms-color-neutralLight solid;

.todoItem {
border: 1px $ms-color-neutralLight solid;
border-top: none;

.itemTaskRow {
padding: 16px 20px;

.deleteButton {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0px;
@include margin-right(16px);

&:hover, &:focus {
color: $ms-color-themePrimary;
}
}
}

&.isHidden {
display: none;
}

&.isCompleted {
border-bottom: 1px $ms-color-white solid;
border-left: 1px $ms-color-neutralLighter solid;
border-right: 1px $ms-color-neutralLighter solid;
@include ms-bgColor-neutralLighter;
}
}
}

.workingOnItSpinner {
display: inline-block;
position: absolute;
top: 0;
bottom: 0;
margin: auto;
height: 33.33333%;
line-height: 1.5em;
padding: 0px 24px;
}

.fetchingTasksSpinner {
display: flex;
justify-content: center;
padding: 24px 0px;
}

@media only screen and (max-width:640px) {
padding: 20px 20px;
}
}
Loading