Skip to content

Commit b095ee2

Browse files
committed
Merge branch 'master' into janwil-pickerdropdown
2 parents 5dc05fc + bdbf0f2 commit b095ee2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1615
-61
lines changed

package-lock.json

+544-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"name": "onenotepicker",
3-
"version": "2.3.5",
3+
"version": "2.4.0",
44
"files": [
55
"dist/**/*"
66
],
77
"dependencies": {
88
"bulma": "^0.4.2",
9-
"onenoteapi": "2.0.5",
9+
"onenoteapi": "2.0.6",
1010
"react": "^15.6.2",
1111
"react-dom": "^15.6.2"
1212
},

sampleApp/sample.tsx

+29-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { OneNotePicker } from '../src/oneNotePicker';
55
import { GlobalProps } from '../src/props/globalProps';
66
import { OneNoteDataProvider } from '../src/providers/oneNoteDataProvider';
77
import { Notebook } from '../src/oneNoteDataStructures/notebook';
8+
import { Section } from '../src/oneNoteDataStructures/section';
89
import { OneNoteItemUtils } from '../src/oneNoteDataStructures/oneNoteItemUtils';
910
import { NotebookListUpdater } from '../src/oneNoteDataStructures/notebookListUpdater';
1011
import { SampleOneNoteDataProvider } from './sampleOneNoteDataProvider';
@@ -73,11 +74,37 @@ oneNoteDataProvider.getNotebooks().then((notebooks) => {
7374
onAccessibleSelection: (selectedItemId: string) => {
7475
globalProps.globals.ariaSelectedId = selectedItemId;
7576
let notebookName = findNotebook(notebooks, selectedItemId);
76-
if(defaultDropdownLabel === "")
77-
defaultDropdownLabel = notebookName;
77+
if (defaultDropdownLabel === "")
78+
defaultDropdownLabel = notebookName;
7879
// todo this changes the label but you can't click to make a selection?
7980
render(globalProps, globalProps.globals.notebookListUpdater!.get());
8081
renderDropdown(globalProps, globalProps.globals.notebookListUpdater!.get(), defaultDropdownLabel, true);
82+
},
83+
onNotebookCreated: (notebook: Notebook) => {
84+
// Allow max one creation
85+
globalProps.globals.callbacks.onNotebookCreated = undefined;
86+
87+
if (globalProps.globals.notebookListUpdater) {
88+
globalProps.globals.notebookListUpdater.addNotebook(notebook);
89+
globalProps.globals.selectedId = notebook.id;
90+
}
91+
92+
// tslint:disable-next-line:no-console
93+
console.log(`Notebook created: ${notebook.name}`);
94+
95+
render(globalProps, globalProps.globals.notebookListUpdater!.get());
96+
},
97+
onSectionCreated: (section: Section) => {
98+
// TODO (machiam) Introduce a way of only allowing max one section creation per parent
99+
// tslint:disable-next-line:no-console
100+
console.log(`Section created: ${section.name}`);
101+
102+
if (globalProps.globals.notebookListUpdater) {
103+
globalProps.globals.notebookListUpdater!.addSection(section);
104+
globalProps.globals.selectedId = section.id;
105+
}
106+
107+
render(globalProps, globalProps.globals.notebookListUpdater!.get());
81108
}
82109
},
83110
selectedId: initialSelectedId,

sampleApp/sampleOneNoteDataProvider.ts

+36
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as OneNoteApi from '../node_modules/onenoteapi/target/oneNoteApi';
33

44
import { OneNoteDataProvider } from '../src/providers/oneNoteDataProvider';
55
import { Notebook } from '../src/oneNoteDataStructures/notebook';
6+
import { SectionGroup } from '../src/oneNoteDataStructures/sectionGroup';
67
import { Section } from '../src/oneNoteDataStructures/section';
78
import { SharedNotebookApiProperties } from '../src/oneNoteDataStructures/sharedNotebook';
89
import { Page } from '../src/oneNoteDataStructures/page';
@@ -194,6 +195,41 @@ const mockResponse: OneNoteApi.ResponsePackage<any> = {
194195
};
195196

196197
export class SampleOneNoteDataProvider implements OneNoteDataProvider {
198+
createNotebook(name: string): Promise<Notebook> {
199+
const notebook: Notebook = {
200+
expanded: false,
201+
sectionGroups: [],
202+
sections: [],
203+
webUrl: '',
204+
apiUrl: '',
205+
parent: undefined,
206+
id: '' + Math.random(),
207+
name: name
208+
};
209+
return Promise.resolve(notebook);
210+
}
211+
212+
createSectionUnderNotebook(parent: Notebook, name: string): Promise<Section> {
213+
return Promise.resolve(this.createSection(parent, name));
214+
}
215+
216+
createSectionUnderSectionGroup(parent: SectionGroup, name: string): Promise<Section> {
217+
return Promise.resolve(this.createSection(parent, name));
218+
}
219+
220+
private createSection(parent: Notebook | SectionGroup, name: string): Section {
221+
return {
222+
expanded: false,
223+
pages: undefined,
224+
apiUrl: '',
225+
webUrl: '',
226+
clientUrl: '',
227+
parent: parent,
228+
id: '' + Math.random(),
229+
name: name
230+
};
231+
}
232+
197233
getNotebooks(expands?: number, excludeReadOnlyNotebooks?: boolean): Promise<Notebook[]> {
198234
const responseTransformer = new OneNoteApiResponseTransformer();
199235
const notebooks = responseTransformer.transformNotebooks(mockResponse.parsedResponse.value);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Strings } from '../../strings';
2+
import { Constants } from '../../constants';
3+
4+
export class CreateNewNotebookCommonProperties {
5+
getId(): string {
6+
return Constants.TreeView.createNewNotebookId;
7+
}
8+
9+
getName(): string {
10+
return Strings.get('Label.CreateNotebook');
11+
}
12+
13+
isSelected(): boolean {
14+
return false;
15+
}
16+
17+
isAriaSelected(): boolean {
18+
return false;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as React from 'react';
2+
3+
import { NodeRenderStrategy } from '../treeView/nodeRenderStrategy';
4+
import { ErrorInfoIconSvg } from '../icons/errorInfoIcon.svg';
5+
import { Strings } from '../../strings';
6+
import { CreateNewNotebookCommonProperties } from './createNewNotebookCommonProperties';
7+
import { CreateNewNotebookRowTemplate } from './createNewNotebookRowTemplate';
8+
9+
export class CreateNewNotebookErrorRenderStrategy extends CreateNewNotebookCommonProperties implements NodeRenderStrategy {
10+
onClickBinded = () => { };
11+
12+
// We don't listen for enter as we assume that we want the user to change the name before
13+
// re-attempting the create
14+
constructor(
15+
private notebookNameInputValue: string,
16+
private onChangeBinded: (event: React.ChangeEvent<HTMLInputElement>) => void) {
17+
super();
18+
}
19+
20+
element(): JSX.Element {
21+
// TODO (machiam) error info should have a popover as per redlines
22+
return (
23+
<CreateNewNotebookRowTemplate>
24+
<div className='picker-label'>
25+
<input
26+
className='create-input'
27+
type='text'
28+
placeholder={Strings.get('Input.CreateNotebookPlaceholder')}
29+
autoComplete='off'
30+
value={this.notebookNameInputValue}
31+
onChange={this.onChangeBinded} />
32+
</div>
33+
<div className='error-info-icon'>
34+
<ErrorInfoIconSvg />
35+
</div>
36+
</CreateNewNotebookRowTemplate>
37+
);
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import * as React from 'react';
2+
3+
import { NodeRenderStrategy } from '../treeView/nodeRenderStrategy';
4+
import { SpinnerIconSvg } from '../icons/spinnerIcon.svg';
5+
import { CreateNewNotebookCommonProperties } from './createNewNotebookCommonProperties';
6+
import { CreateNewNotebookRowTemplate } from './createNewNotebookRowTemplate';
7+
8+
export class CreateNewNotebookInProgressRenderStrategy extends CreateNewNotebookCommonProperties implements NodeRenderStrategy {
9+
onClickBinded = () => { };
10+
11+
constructor(private name: string) {
12+
super();
13+
}
14+
15+
element(): JSX.Element {
16+
return (
17+
<CreateNewNotebookRowTemplate>
18+
<div className='picker-label'>
19+
<label>{this.name}</label>
20+
<div className='create-spinner'>
21+
<SpinnerIconSvg />
22+
</div>
23+
</div>
24+
</CreateNewNotebookRowTemplate>
25+
);
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import * as React from 'react';
2+
3+
import { NodeRenderStrategy } from '../treeView/nodeRenderStrategy';
4+
import { ErrorInfoIconSvg } from '../icons/errorInfoIcon.svg';
5+
import { Strings } from '../../strings';
6+
import { NameValidator } from '../../nameValidator';
7+
import { CreateNewNotebookCommonProperties } from './createNewNotebookCommonProperties';
8+
import { CreateNewNotebookRowTemplate } from './createNewNotebookRowTemplate';
9+
10+
export class CreateNewNotebookInputRenderStrategy extends CreateNewNotebookCommonProperties implements NodeRenderStrategy {
11+
onClickBinded = () => { };
12+
13+
constructor(
14+
private notebookNameInputValue: string,
15+
private onEnterBinded: (event) => void,
16+
private onChangeBinded: (event: React.ChangeEvent<HTMLInputElement>) => void,
17+
private inputRefBinded: (node: HTMLInputElement) => void) {
18+
super();
19+
}
20+
21+
element(): JSX.Element {
22+
// TODO (machiam) error info should have a popover as per redlines
23+
return (
24+
<CreateNewNotebookRowTemplate>
25+
<div className='picker-label'>
26+
<input
27+
className='create-input'
28+
ref={this.inputRefBinded}
29+
type='text'
30+
name='notebookName'
31+
placeholder={Strings.get('Input.CreateNotebookPlaceholder')}
32+
autoComplete='off'
33+
value={this.notebookNameInputValue}
34+
onKeyPress={this.onKeyPress.bind(this)}
35+
onChange={this.onChangeBinded} />
36+
</div>
37+
<div className='error-info-icon' style={this.showError() ? { } : { visibility: 'hidden' }}>
38+
<ErrorInfoIconSvg />
39+
</div>
40+
</CreateNewNotebookRowTemplate>
41+
);
42+
}
43+
44+
private showError(): boolean {
45+
return !!NameValidator.validateNotebookName(this.notebookNameInputValue);
46+
}
47+
48+
private onKeyPress(event): void {
49+
if (event.key === 'Enter') {
50+
this.onEnterBinded(event);
51+
}
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import * as React from 'react';
2+
3+
import { NodeRenderStrategy } from '../treeView/nodeRenderStrategy';
4+
import { CreateNewNotebookNotStartedRenderStrategy } from './createNewNotebookNotStartedRenderStrategy';
5+
import { CreateNewNotebookInputRenderStrategy } from './createNewNotebookInputRenderStrategy';
6+
import { CreateNewNotebookInProgressRenderStrategy } from './createNewNotebookInProgressRenderStrategy';
7+
import { CreateNewNotebookErrorRenderStrategy } from './createNewNotebookErrorRenderStrategy';
8+
import { InnerGlobals } from '../../props/globalProps';
9+
import { CreateEntityNode } from '../treeView/createEntityNode';
10+
11+
export interface CreateNewNotebookNodeProps extends InnerGlobals {
12+
level: number;
13+
tabbable: boolean;
14+
}
15+
16+
/**
17+
* Presentation component that extends the 'Create' UX with notebook-specific
18+
* UI.
19+
*/
20+
export class CreateNewNotebookNode extends React.Component<CreateNewNotebookNodeProps, {}> {
21+
constructor() {
22+
super();
23+
24+
this.notStartedRenderStrategy = this.notStartedRenderStrategy.bind(this);
25+
this.inputRenderStrategy = this.inputRenderStrategy.bind(this);
26+
this.createErrorRenderStrategy = this.createErrorRenderStrategy.bind(this);
27+
this.inProgressRenderStrategy = this.inProgressRenderStrategy.bind(this);
28+
this.createNotebook = this.createNotebook.bind(this);
29+
}
30+
31+
private notStartedRenderStrategy(onClick: () => void): NodeRenderStrategy {
32+
return new CreateNewNotebookNotStartedRenderStrategy(onClick);
33+
}
34+
35+
private inputRenderStrategy(
36+
inputValue: string,
37+
onEnter: () => void,
38+
onInputChange: (evt: React.ChangeEvent<HTMLInputElement>) => void,
39+
setInputRefAndFocus: (node: HTMLInputElement) => void): NodeRenderStrategy {
40+
return new CreateNewNotebookInputRenderStrategy(inputValue, onEnter, onInputChange, setInputRefAndFocus);
41+
}
42+
43+
private createErrorRenderStrategy(inputValue: string, onInputChange: (evt: React.ChangeEvent<HTMLInputElement>) => void): NodeRenderStrategy {
44+
return new CreateNewNotebookErrorRenderStrategy(inputValue, onInputChange);
45+
}
46+
47+
private inProgressRenderStrategy(inputValue: string): NodeRenderStrategy {
48+
return new CreateNewNotebookInProgressRenderStrategy(inputValue);
49+
}
50+
51+
private createNotebook(name: string): Promise<void> {
52+
return this.props.oneNoteDataProvider!.createNotebook(name).then((notebook) => {
53+
return this.props.callbacks.onNotebookCreated!(notebook);
54+
});
55+
}
56+
57+
render() {
58+
return (
59+
<CreateEntityNode
60+
{...this.props}
61+
notStartedRenderStrategy={this.notStartedRenderStrategy}
62+
inputRenderStrategy={this.inputRenderStrategy}
63+
createErrorRenderStrategy={this.createErrorRenderStrategy}
64+
inProgressRenderStrategy={this.inProgressRenderStrategy}
65+
createEntity={this.createNotebook}>
66+
</CreateEntityNode>
67+
);
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as React from 'react';
2+
3+
import { NodeRenderStrategy } from '../treeView/nodeRenderStrategy';
4+
import { AddIconSvg } from '../icons/addIcon.svg';
5+
import { ChevronSvg } from '../icons/chevron.svg';
6+
import { Strings } from '../../strings';
7+
import { CreateNewNotebookCommonProperties } from './createNewNotebookCommonProperties';
8+
9+
export class CreateNewNotebookNotStartedRenderStrategy extends CreateNewNotebookCommonProperties implements NodeRenderStrategy {
10+
onClickBinded = this.onClick;
11+
12+
constructor(private onClick: () => void) {
13+
super();
14+
}
15+
16+
element(): JSX.Element {
17+
return (
18+
<div className='notebook'>
19+
<div className='chevron-icon closed' style={{ visibility: 'hidden' }}>
20+
<ChevronSvg />
21+
</div>
22+
<div className='picker-icon'>
23+
<AddIconSvg />
24+
</div>
25+
<div className='picker-label'>
26+
<label className='create-label'>{Strings.get('Label.CreateNotebook')}</label>
27+
</div>
28+
</div>
29+
);
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import { ChevronSvg } from '../icons/chevron.svg';
3+
import { NotebookClosedIconSvg } from '../icons/notebookClosedIcon.svg';
4+
5+
export class CreateNewNotebookRowTemplate extends React.Component<{}, {}> {
6+
render() {
7+
return (
8+
<div className='notebook'>
9+
<div className='chevron-icon closed' style={{ visibility: 'hidden' }}>
10+
<ChevronSvg />
11+
</div>
12+
<div className='picker-icon'>
13+
<NotebookClosedIconSvg />
14+
</div>
15+
{this.props.children}
16+
</div>
17+
);
18+
}
19+
}

0 commit comments

Comments
 (0)