diff --git a/package.json b/package.json index 45fe159..91094d4 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,11 @@ "dependencies": { "@types/jest": "24.0.11", "@types/node": "11.12.2", + "@types/rc-tree": "^1.11.3", "@types/react": "16.8.10", "@types/react-dom": "16.8.3", "@types/react-router-dom": "^4.3.1", + "rc-tree": "^1.15.2", "react": "^16.8.6", "react-dom": "^16.8.6", "react-router-dom": "^5.0.0", diff --git a/src/assets/images/theme/tree-leaf1.gif b/src/assets/images/theme/tree-leaf1.gif new file mode 100644 index 0000000..ac34c41 Binary files /dev/null and b/src/assets/images/theme/tree-leaf1.gif differ diff --git a/src/assets/images/theme/tree-leaf2.gif b/src/assets/images/theme/tree-leaf2.gif new file mode 100644 index 0000000..6408cf1 Binary files /dev/null and b/src/assets/images/theme/tree-leaf2.gif differ diff --git a/src/assets/images/theme/tree-line.gif b/src/assets/images/theme/tree-line.gif new file mode 100644 index 0000000..aab1527 Binary files /dev/null and b/src/assets/images/theme/tree-line.gif differ diff --git a/src/assets/images/theme/tree-parent1.gif b/src/assets/images/theme/tree-parent1.gif new file mode 100644 index 0000000..ac2389d Binary files /dev/null and b/src/assets/images/theme/tree-parent1.gif differ diff --git a/src/assets/images/theme/tree-parent2.gif b/src/assets/images/theme/tree-parent2.gif new file mode 100644 index 0000000..d35fc5a Binary files /dev/null and b/src/assets/images/theme/tree-parent2.gif differ diff --git a/src/assets/images/theme/tree-root.gif b/src/assets/images/theme/tree-root.gif new file mode 100644 index 0000000..960a061 Binary files /dev/null and b/src/assets/images/theme/tree-root.gif differ diff --git a/src/assets/tree.json b/src/assets/tree.json new file mode 100644 index 0000000..0a9447d --- /dev/null +++ b/src/assets/tree.json @@ -0,0 +1 @@ +{"index_id":"3","title":"Public","num_items":"32","child_indexes":[{"index_id":"6","title":"Pupil Colloquium","num_items":"0","child_indexes":[{"index_id":"216","title":"2007, Hamamatsu","num_items":"48","child_indexes":[]},{"index_id":"7","title":"2005, Bear Mountain","num_items":"113","child_indexes":[]},{"index_id":"81","title":"2003, Crete","num_items":"123","child_indexes":[]},{"index_id":"8","title":"2001, Asilomar","num_items":"128","child_indexes":[]},{"index_id":"82","title":"1999, Nottingham","num_items":"96","child_indexes":[]},{"index_id":"217","title":"1997, Point Clear","num_items":"93","child_indexes":[]}]}]} \ No newline at end of file diff --git a/src/components/IndexTreeBlock.module.css b/src/components/IndexTreeBlock.module.css new file mode 100644 index 0000000..eeb0acf --- /dev/null +++ b/src/components/IndexTreeBlock.module.css @@ -0,0 +1,62 @@ +.indexTree { + border-top: 1px solid #9ab5cf; + border-left: 1px solid #9ab5cf; + border-bottom: 1px solid #404040; + border-right: 1px solid #404040; + background-color: white; + height: 250px; + width: 175px; + overflow: auto; +} + +.formButton { + margin: 3px 3px 10px; +} + +.indexTree li span { + color: blue; + font-size: 12px; + font-weight: bold; +} + +.indexTree li span:hover { + color: #ff9900; +} + +.indexTree:global(.rc-tree li ul) { + padding: 0 0 0 10px; +} + +.indexTree:global(.rc-tree li span.rc-tree-switcher) { + height: 19px; + width: 21px; +} + +.indexTree:global(.rc-tree > li:first-child > span.rc-tree-switcher.rc-tree-switcher_open), .indexTree:global(.rc-tree > li:first-child > span.rc-tree-switcher.rc-tree-switcher_close) { + background: url(../assets/images/theme/tree-root.gif); + width: 14px; +} + +.indexTree:global(.rc-tree > li:first-child > ul) { + padding: 0 0 0 7px; +} + +.indexTree:global(.rc-tree li:not(:last-child) ul.rc-tree-child-tree.rc-tree-child-tree-open) { + background: url(../assets/images/theme/tree-line.gif) repeat-y; +} + +.indexTree:global(.rc-tree li:not(:last-child) > span.rc-tree-switcher-noop) { + background: url(../assets/images/theme/tree-leaf1.gif) +} + +.indexTree:global(.rc-tree li:last-child > span.rc-tree-switcher-noop) { + background: url(../assets/images/theme/tree-leaf2.gif) +} + +.indexTree:global(.rc-tree li:not(:last-child) > span.rc-tree-switcher_open), .indexTree:global(.rc-tree li:not(:last-child) > span.rc-tree-switcher_close) { + background: url(../assets/images/theme/tree-parent1.gif) +} + +.indexTree:global(.rc-tree li:last-child > span.rc-tree-switcher_open), .indexTree:global(.rc-tree li:last-child > span.rc-tree-switcher_close) { + background: url(../assets/images/theme/tree-parent2.gif) +} \ No newline at end of file diff --git a/src/components/IndexTreeBlock.tsx b/src/components/IndexTreeBlock.tsx new file mode 100644 index 0000000..41b836a --- /dev/null +++ b/src/components/IndexTreeBlock.tsx @@ -0,0 +1,104 @@ +import React, { Component } from 'react'; +import { RouteComponentProps, StaticContext, withRouter } from 'react-router'; +import Tree, { TreeNode, InternalTreeNodeProps, ExpandData, SelectData } from 'rc-tree'; +import styles from './IndexTreeBlock.module.css'; +import 'rc-tree/assets/index.css'; + +import treeJson from '../assets/tree.json'; + +interface IProps extends RouteComponentProps<{}, StaticContext, any> { } + +interface IState { + expandableKeys?: string[]; + treeElement?: JSX.Element[]; + expandedKeys?: string[]; + selectedKeys?: string[]; +} + +interface ITreeJson { + index_id: string; + title: string; + num_items: string; + child_indexes: ITreeJson[]; +} + +class IndexTreeBlock extends Component { + + public state: IState = { + treeElement: [], + expandedKeys: [], + selectedKeys: [] + }; + + constructor(props: IProps) { + super(props); + this.handleClickOpenAll = this.handleClickOpenAll.bind(this); + this.handleClickCloseAll = this.handleClickCloseAll.bind(this); + this.handleExpand = this.handleExpand.bind(this); + this.handleSelect = this.handleSelect.bind(this); + } + + handleClickOpenAll() { + this.setState({ expandedKeys: this.state.expandableKeys }) + } + + handleClickCloseAll() { + this.setState({ expandedKeys: [] }) + } + + handleExpand(expandedKeys: string[], e: ExpandData): void { + this.setState({ expandedKeys }); + } + + handleSelect(selectedKeys: string[], e: SelectData): void { + const url = '/database/list/' + e.node.props.eventKey; + this.props.history.push(url); + this.setState({ selectedKeys: [] }); + } + + componentDidMount() { + this.loadTreeData(); + } + + loadTreeData() { + const expandedKeys: string[] = []; + const loop = (data: ITreeJson[]) => { + return data.map((item: ITreeJson) => { + let title: string = item.title; + if (parseInt(item.num_items) > 0) { + title += ' (' + item.num_items + ')'; + } + if (item.child_indexes.length > 0) { + expandedKeys.push(item.index_id); + return ( + + {loop(item.child_indexes)} + + ); + } + return (); + }); + }; + const data: ITreeJson[] = [treeJson]; + const treeData: JSX.Element[] = loop(data); + this.setState({ treeElement: treeData }); + this.setState({ expandedKeys: expandedKeys }); + this.setState({ expandableKeys: expandedKeys }); + } + + render() { + return ( +
+ + + + {this.state.treeElement} + +
+ ); + } +} + +export default withRouter(IndexTreeBlock); \ No newline at end of file diff --git a/src/components/LeftColumn.tsx b/src/components/LeftColumn.tsx index 2e37b27..1a395bb 100644 --- a/src/components/LeftColumn.tsx +++ b/src/components/LeftColumn.tsx @@ -3,6 +3,7 @@ import styles from './LeftColumn.module.css'; import MainMenuBlock from './MainMenuBlock'; import SearchBlock from './SearchBlock'; +import IndexTreeBlock from './IndexTreeBlock'; class LeftColumn extends Component { render() { @@ -23,7 +24,7 @@ class LeftColumn extends Component {

Index Tree

- Index Tree +
diff --git a/src/components/SearchBlock.tsx b/src/components/SearchBlock.tsx index 0de8514..7780879 100644 --- a/src/components/SearchBlock.tsx +++ b/src/components/SearchBlock.tsx @@ -21,7 +21,6 @@ class SearchBlock extends Component { super(props); this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); - console.log(props.location); } updateState(key: string, value: string) { diff --git a/yarn.lock b/yarn.lock index c80e330..422e568 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1014,6 +1014,13 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== +"@types/rc-tree@^1.11.3": + version "1.11.3" + resolved "https://registry.yarnpkg.com/@types/rc-tree/-/rc-tree-1.11.3.tgz#b40c096c54bab2a56b88de813af47b96e7e82b00" + integrity sha512-RxWXGy5PiR02TyZ1fNuqmBIeLylUOSIHLuWpnRswI18N2lpAqzXLaJhIctnGcn0OXjYss96EEJddL8tLFXuvNQ== + dependencies: + "@types/react" "*" + "@types/react-dom@16.8.3": version "16.8.3" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.3.tgz#6131b7b6158bc7ed1925a3374b88b7c00481f0cb" @@ -1279,6 +1286,13 @@ acorn@^6.0.1, acorn@^6.0.7: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +add-dom-event-listener@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz#6a92db3a0dd0abc254e095c0f1dc14acbbaae310" + integrity sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw== + dependencies: + object-assign "4.x" + address@1.0.3, address@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -1794,7 +1808,7 @@ babel-register@^6.26.0: mkdirp "^0.5.1" source-map-support "^0.4.15" -babel-runtime@^6.22.0, babel-runtime@^6.26.0: +babel-runtime@6.x, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -2341,6 +2355,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@2.x, classnames@^2.2.5: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + clean-css@4.2.x: version "4.2.1" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" @@ -2484,11 +2503,23 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +component-classes@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/component-classes/-/component-classes-1.2.6.tgz#c642394c3618a4d8b0b8919efccbbd930e5cd691" + integrity sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE= + dependencies: + component-indexof "0.0.3" + component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= +component-indexof@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-indexof/-/component-indexof-0.0.3.tgz#11d091312239eb8f32c8f25ae9cb002ffe8d3c24" + integrity sha1-EdCRMSI5648yyPJa6csAL/6NPCQ= + compressible@~2.0.14: version "2.0.16" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.16.tgz#a49bf9858f3821b64ce1be0296afc7380466a77f" @@ -3885,7 +3916,7 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fbjs@^0.8.0: +fbjs@^0.8.0, fbjs@^0.8.16: version "0.8.17" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= @@ -6005,6 +6036,11 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -6020,6 +6056,25 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + +lodash.keys@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -6653,7 +6708,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@4.1.1, object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -7874,7 +7929,7 @@ prompts@^0.1.9: kleur "^2.0.1" sisteransi "^0.1.1" -prop-types@^15.6.2: +prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7990,7 +8045,7 @@ querystringify@^2.0.0: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg== -raf@3.4.1: +raf@3.4.1, raf@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -8036,6 +8091,43 @@ raw-body@2.3.3: iconv-lite "0.4.23" unpipe "1.0.0" +rc-animate@^3.0.0-rc.5: + version "3.0.0-rc.6" + resolved "https://registry.yarnpkg.com/rc-animate/-/rc-animate-3.0.0-rc.6.tgz#04288eefa118e0cae214536c8a903ffaac1bc3fb" + integrity sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg== + dependencies: + babel-runtime "6.x" + classnames "^2.2.5" + component-classes "^1.2.6" + fbjs "^0.8.16" + prop-types "15.x" + raf "^3.4.0" + rc-util "^4.5.0" + react-lifecycles-compat "^3.0.4" + +rc-tree@^1.15.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-1.15.2.tgz#a0d6f20fa2bdbe51d829d5ceea74a407b04bfea9" + integrity sha512-VPXLA/GdV6U9N8evpl4rmjRsBkw5BoweqWjcVBVwYGzBtonNIFpdc+bnb7TDmd6S3mKOM7mXPbiSr2GKYdj4hA== + dependencies: + babel-runtime "^6.23.0" + classnames "2.x" + prop-types "^15.5.8" + rc-animate "^3.0.0-rc.5" + rc-util "^4.5.1" + react-lifecycles-compat "^3.0.4" + warning "^3.0.0" + +rc-util@^4.5.0, rc-util@^4.5.1: + version "4.6.0" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.6.0.tgz#ba33721783192ec4f3afb259e182b04e55deb7f6" + integrity sha512-rbgrzm1/i8mgfwOI4t1CwWK7wGe+OwX+dNa7PVMgxZYPBADGh86eD4OcJO1UKGeajIMDUUKMluaZxvgraQIOmw== + dependencies: + add-dom-event-listener "^1.1.0" + babel-runtime "6.x" + prop-types "^15.5.10" + shallowequal "^0.2.2" + rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -8113,6 +8205,11 @@ react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + react-router-dom@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.0.tgz#542a9b86af269a37f0b87218c4c25ea8dcf0c073" @@ -8807,6 +8904,13 @@ shallow-clone@^1.0.0: kind-of "^5.0.0" mixin-object "^2.0.1" +shallowequal@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-0.2.2.tgz#1e32fd5bcab6ad688a4812cb0cc04efc75c7014e" + integrity sha1-HjL9W8q2rWiKSBLLDMBO/HXHAU4= + dependencies: + lodash.keys "^3.1.2" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -9858,6 +9962,13 @@ walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= + dependencies: + loose-envify "^1.0.0" + watch@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"