Skip to content

Commit 5dc05fc

Browse files
committed
Abstract away picker properties to dropdown, refactor dropdown labels, and make dropdown popup have responsive scss
1 parent b051619 commit 5dc05fc

12 files changed

+191
-9
lines changed

Diff for: .vs/OneNotePicker-JS/v15/.suo

3.5 KB
Binary file not shown.

Diff for: .vs/ProjectSettings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"CurrentProjectSetting": null
3+
}

Diff for: .vs/slnx.sqlite

148 KB
Binary file not shown.

Diff for: .vscode/launch.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "Launch Program",
11+
"program": "${workspaceFolder}\\--open",
12+
"outFiles": [
13+
"${workspaceFolder}/**/*.js"
14+
]
15+
}
16+
]
17+
}

Diff for: package-lock.json

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

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@types/history": "^4.5.2",
1818
"@types/jasmine": "^2.5.51",
1919
"@types/node": "^7.0.29",
20-
"@types/react": "^15.6.2",
20+
"@types/react": "^15.6.15",
2121
"@types/react-dom": "^15.5.6",
2222
"@types/sinon": "^2.3.1",
2323
"@types/webpack": "^2.2.15",

Diff for: sampleApp/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
<body style="min-height:100%" dir="ltr">
1212
<div id="oneNotePicker" style="width:350px;height:350px;margin:50px;overflow-y:scroll"></div>
13+
<div id="oneNotePickerDropdown" style="width:350px;height:350px;margin:50px" ></div>
1314
<button tabIndex="0">Ok</button>
1415
<button tabIndex="0">Back</button>
1516
<script src="dist/sample.js"></script>

Diff for: sampleApp/sample.tsx

+31-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Notebook } from '../src/oneNoteDataStructures/notebook';
88
import { OneNoteItemUtils } from '../src/oneNoteDataStructures/oneNoteItemUtils';
99
import { NotebookListUpdater } from '../src/oneNoteDataStructures/notebookListUpdater';
1010
import { SampleOneNoteDataProvider } from './sampleOneNoteDataProvider';
11+
import { OneNotePickerDropdown } from '../src/oneNotePickerDropdown';
1112

1213
const oneNoteDataProvider: OneNoteDataProvider = new SampleOneNoteDataProvider();
1314

@@ -18,6 +19,15 @@ const render = (globalProps: GlobalProps, notebooks: Notebook[]) => {
1819
);
1920
};
2021

22+
const renderDropdown = (globalProps: GlobalProps, notebooks: Notebook[], label: string, popupVisible: boolean) => {
23+
ReactDOM.render(
24+
<OneNotePickerDropdown globals={globalProps.globals} notebooks={notebooks} dropdownLabel={label} popupDirection={'bottom'} popupVisible={popupVisible}/>,
25+
document.getElementById('oneNotePickerDropdown') as HTMLElement
26+
);
27+
};
28+
29+
export let defaultDropdownLabel = "";
30+
2131
oneNoteDataProvider.getNotebooks().then((notebooks) => {
2232
for (let i = 0; i < notebooks.length; i++) {
2333
OneNoteItemUtils.prune(notebooks[i]);
@@ -35,36 +45,54 @@ oneNoteDataProvider.getNotebooks().then((notebooks) => {
3545
notebookListUpdater: updater,
3646
callbacks: {
3747
onNotebookHierarchyUpdated: (newNotebookHierarchy) => {
48+
let latestNotebook = newNotebookHierarchy[newNotebookHierarchy.length - 1].name;
49+
if(defaultDropdownLabel === "")
50+
defaultDropdownLabel = latestNotebook;
3851
render(globalProps, newNotebookHierarchy);
52+
renderDropdown(globalProps, newNotebookHierarchy, defaultDropdownLabel, true);
3953
},
4054
onSectionSelected: (section, breadcrumbs) => {
4155
globalProps.globals.selectedId = section.id;
42-
56+
defaultDropdownLabel = section.name;
4357
// tslint:disable-next-line:no-console
4458
console.log(breadcrumbs.map(x => x.name).join(' > '));
4559

4660
render(globalProps, globalProps.globals.notebookListUpdater!.get());
61+
renderDropdown(globalProps, globalProps.globals.notebookListUpdater!.get(), defaultDropdownLabel, false);
4762
},
4863
onPageSelected: (page, breadcrumbs) => {
4964
globalProps.globals.selectedId = page.id;
50-
65+
defaultDropdownLabel = page.name;
5166
// tslint:disable-next-line:no-console
5267
console.log(breadcrumbs.map(x => x.name).join(' > '));
68+
console.log(breadcrumbs[breadcrumbs.length -1].name)
5369

5470
render(globalProps, globalProps.globals.notebookListUpdater!.get());
71+
renderDropdown(globalProps, globalProps.globals.notebookListUpdater!.get(), defaultDropdownLabel, false);
5572
},
5673
onAccessibleSelection: (selectedItemId: string) => {
5774
globalProps.globals.ariaSelectedId = selectedItemId;
58-
75+
let notebookName = findNotebook(notebooks, selectedItemId);
76+
if(defaultDropdownLabel === "")
77+
defaultDropdownLabel = notebookName;
78+
// todo this changes the label but you can't click to make a selection?
5979
render(globalProps, globalProps.globals.notebookListUpdater!.get());
80+
renderDropdown(globalProps, globalProps.globals.notebookListUpdater!.get(), defaultDropdownLabel, true);
6081
}
6182
},
6283
selectedId: initialSelectedId,
6384
ariaSelectedId: initialSelectedId
6485
}
6586
};
87+
let notebookName = findNotebook(notebooks, initialSelectedId)
6688
render(globalProps, notebooks);
89+
renderDropdown(globalProps, notebooks, notebookName, false);
6790
}).catch((value) => {
6891
// tslint:disable-next-line:no-console
6992
console.error(value);
7093
});
94+
95+
export function findNotebook(notebooks, itemid) {
96+
let notebook = OneNoteItemUtils.find(notebooks, item => item.id === itemid);
97+
return notebook ? notebook.name : "";
98+
}

Diff for: src/dropdownRender.tsx

Whitespace-only changes.

Diff for: src/oneNotePicker.scss

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ svg.spinner {
170170
background-color: #FFFFFF;
171171
border: 1px solid rgba(22, 35, 58, 0.26);
172172
max-height: 140px;
173+
width: 100%;
173174
}
174175

175176
.popup-upwards {

Diff for: src/oneNotePickerDropdown.tsx

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import * as React from 'react';
2+
3+
import { OneNotePickerProps, OneNotePicker } from './oneNotePicker';
4+
import { OneNoteSingleNotebookPickerProps, OneNoteSingleNotebookPicker } from './oneNoteSingleNotebookPicker';
5+
import { GlobalProps } from './props/globalProps';
6+
7+
export interface OneNotePickerDropdownState {
8+
popupVisible: boolean;
9+
}
10+
11+
12+
export interface PickerProperties extends GlobalProps {
13+
popupVisible: boolean;
14+
dropdownLabel: string;
15+
popupDirection: 'bottom' | 'top';
16+
popupContentOverride?: JSX.Element;
17+
}
18+
19+
export abstract class GenericOneNotePickerDropdown<T extends PickerProperties> extends React.Component<T, OneNotePickerDropdownState> {
20+
private wrapperRef: Node;
21+
22+
constructor(props: T) {
23+
super(props);
24+
this.state = {
25+
popupVisible: props.popupVisible
26+
};
27+
this.handleClickOutside = this.handleClickOutside.bind(this);
28+
this.setWrapperRef = this.setWrapperRef.bind(this);
29+
}
30+
31+
componentWillReceiveProps(nextProps: T) {
32+
this.state = {
33+
popupVisible: nextProps.popupVisible
34+
}
35+
}
36+
37+
onClick() {
38+
this.setState({
39+
popupVisible: !this.state.popupVisible
40+
});
41+
}
42+
43+
onPickerItemClicked() {
44+
this.setState({
45+
popupVisible: false
46+
});
47+
}
48+
49+
private setWrapperRef(node) {
50+
this.wrapperRef = node as Node;
51+
}
52+
53+
private handleClickOutside(event) {
54+
if (this.wrapperRef && !this.wrapperRef.contains(event.target) && this.state.popupVisible) {
55+
this.setState({
56+
popupVisible: false
57+
});
58+
}
59+
}
60+
61+
componentDidMount() {
62+
document.addEventListener('mousedown', this.handleClickOutside);
63+
}
64+
65+
componentWillUnmount() {
66+
document.removeEventListener('mousedown', this.handleClickOutside);
67+
}
68+
69+
70+
abstract createTag(arg: T): JSX.Element;
71+
72+
render() {
73+
// TODO (machiam/jane) We should not modify props. We should copy to new object before passing it down.
74+
const newCallbacks = { ...this.props.globals.callbacks };
75+
76+
if (newCallbacks.onSectionSelected) {
77+
const decorated = newCallbacks.onSectionSelected;
78+
newCallbacks.onSectionSelected = (section, breadcrumbs) => {
79+
this.onPickerItemClicked();
80+
decorated(section, breadcrumbs);
81+
};
82+
}
83+
84+
if (newCallbacks.onPageSelected) {
85+
const decorated = newCallbacks.onPageSelected;
86+
newCallbacks.onPageSelected = (page, breadcrumbs) => {
87+
this.onPickerItemClicked();
88+
decorated(page, breadcrumbs);
89+
};
90+
}
91+
92+
this.props.globals.callbacks = newCallbacks;
93+
94+
return (
95+
<div className='picker-dropdown' ref={this.setWrapperRef}>
96+
<div className='picker-dropdown-padding'>
97+
<a className='picker-dropdown-toggle' onClick={this.onClick.bind(this)}>
98+
<div className='dropdown-arrow-container'>
99+
<svg version='1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>
100+
<polygon id='XMLID_10_' points='3.5,7 4.4,6.1 8,9.7 11.7,6.1 12.6,7 8,11.5' />
101+
</svg>
102+
</div>
103+
<div className='picker-dropdown-toggle-label' title={this.props.dropdownLabel}>
104+
{this.props.dropdownLabel}
105+
</div>
106+
</a>
107+
</div>
108+
{this.state.popupVisible ?
109+
<div className={'picker-popup ' + (this.props.popupDirection === 'top' ? 'popup-upwards' : '')}>
110+
{this.props.popupContentOverride ? this.props.popupContentOverride : this.createTag(this.props)}
111+
</div> :
112+
undefined}
113+
</div>
114+
);
115+
116+
117+
}
118+
119+
}
120+
121+
export class OneNotePickerDropdown extends GenericOneNotePickerDropdown<OneNotePickerProps & PickerProperties> {
122+
createTag(args: OneNotePickerProps) {
123+
return <OneNotePicker {...args} />;
124+
}
125+
}
126+
127+
export class OneNoteSingleNotebookDropdown extends GenericOneNotePickerDropdown<OneNoteSingleNotebookPickerProps & PickerProperties> {
128+
createTag(args: OneNoteSingleNotebookPickerProps) {
129+
return <OneNoteSingleNotebookPicker {...args} />;
130+
}
131+
}

Diff for: src/props/globalProps.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface GlobalProps {
1616
export interface InnerGlobals {
1717
focusOnMount: boolean;
1818

19+
1920
oneNoteDataProvider: OneNoteDataProvider | undefined;
2021
notebookListUpdater: NotebookListUpdater | undefined;
2122
callbacks: OneNotePickerCallbacks;

0 commit comments

Comments
 (0)