From 832639987e56495fbc549f11599956ab1e110553 Mon Sep 17 00:00:00 2001 From: Yoshihiro OKUMURA Date: Mon, 26 Aug 2019 20:15:20 +0900 Subject: [PATCH] add initial code of dynamic brain platform. --- .gitignore | 12 + etc/common.inc.php | 197 ++ etc/config.inc.php | 9 + etc/dumpCredits.php | 156 ++ etc/dumpMediaWiki.php | 198 ++ etc/dumpPico.php | 163 ++ etc/dumpXooNIps.php | 1176 ++++++++++++ etc/fixMediaWikiDumpData.php | 180 ++ etc/simpflink.csv | 465 +++++ package.json | 42 +- public/.htaccess | 8 + public/favicon.ico | Bin 3870 -> 3638 bytes public/index.html | 32 +- public/logo192.png | Bin 5347 -> 0 bytes public/logo512.png | Bin 9664 -> 0 bytes public/manifest.json | 18 +- src/App.css | 35 +- src/App.tsx | 36 +- src/common/AppRoot.tsx | 85 + src/common/CenterColumn.tsx | 65 + src/common/Footer.tsx | 31 + src/common/Header.tsx | 58 + src/common/LeftColumn.tsx | 58 + src/common/MainContent.tsx | 50 + src/common/XoopsPathRedirect.tsx | 40 + src/common/assets/images/mlang_english.gif | Bin 0 -> 175 bytes src/common/assets/images/mlang_japanese.gif | Bin 0 -> 126 bytes src/common/assets/images/no_avatar.gif | Bin 0 -> 985 bytes src/common/assets/images/pagact.gif | Bin 0 -> 121 bytes src/common/assets/images/paginact.gif | Bin 0 -> 121 bytes src/common/assets/images/pagneutral.gif | Bin 0 -> 121 bytes .../assets/images/rank3dbf8e94a6f72.gif | Bin 0 -> 905 bytes .../assets/images/rank3dbf8e9e7d88d.gif | Bin 0 -> 1276 bytes .../assets/images/rank3dbf8ea81e642.gif | Bin 0 -> 894 bytes .../assets/images/rank3dbf8eb1a72e7.gif | Bin 0 -> 856 bytes .../assets/images/rank3dbf8edf15093.gif | Bin 0 -> 789 bytes .../assets/images/rank3dbf8ee8681cd.gif | Bin 0 -> 779 bytes .../assets/images/rank3e632f95e81ca.gif | Bin 0 -> 475 bytes .../assets/images/smil3dbd4bf386b36.gif | Bin 0 -> 210 bytes .../assets/images/smil3dbd4d4e4c4f2.gif | Bin 0 -> 204 bytes .../assets/images/smil3dbd4d6422f04.gif | Bin 0 -> 174 bytes .../assets/images/smil3dbd4d75edb5e.gif | Bin 0 -> 204 bytes .../assets/images/smil3dbd4d8676346.gif | Bin 0 -> 176 bytes .../assets/images/smil3dbd4d99c6eaa.gif | Bin 0 -> 207 bytes .../assets/images/smil3dbd4daabd491.gif | Bin 0 -> 170 bytes .../assets/images/smil3dbd4dbc14f3f.gif | Bin 0 -> 210 bytes .../assets/images/smil3dbd4dcd7b9f4.gif | Bin 0 -> 278 bytes .../assets/images/smil3dbd4ddd6835f.gif | Bin 0 -> 202 bytes .../assets/images/smil3dbd4df1944ee.gif | Bin 0 -> 678 bytes .../assets/images/smil3dbd4e02c5440.gif | Bin 0 -> 263 bytes .../assets/images/smil3dbd4e1748cc9.gif | Bin 0 -> 209 bytes .../assets/images/smil3dbd4e29bbcc7.gif | Bin 0 -> 492 bytes .../assets/images/smil3dbd4e398ff7b.gif | Bin 0 -> 205 bytes .../assets/images/smil3dbd4e4c2e742.gif | Bin 0 -> 4959 bytes .../assets/images/smil3dbd4e5e7563a.gif | Bin 0 -> 736 bytes .../assets/images/smil3dbd4e7853679.gif | Bin 0 -> 273 bytes src/common/assets/main-menu.json | 38 + src/common/assets/theme/images/arrow.png | Bin 0 -> 709 bytes .../assets/theme/images/banner_physiome.png | Bin 0 -> 1274 bytes .../assets/theme/images/banner_riken-cbs.png | Bin 0 -> 3894 bytes .../assets/theme/images/banner_riken.png | Bin 0 -> 2225 bytes .../assets/theme/images/banner_xoonips.png | Bin 0 -> 2154 bytes src/common/assets/theme/images/bg.png | Bin 0 -> 309 bytes src/common/assets/theme/images/brain-bike.png | Bin 0 -> 196036 bytes src/common/assets/theme/images/i.png | Bin 0 -> 351 bytes src/common/assets/theme/images/icon_jnode.png | Bin 0 -> 3357 bytes src/common/assets/theme/images/indent.png | Bin 0 -> 155 bytes .../assets/theme/images/indent_hover.png | Bin 0 -> 155 bytes src/common/assets/theme/images/logo.png | Bin 0 -> 10134 bytes src/common/assets/theme/images/plate.png | Bin 0 -> 103 bytes src/common/assets/theme/images/plateB.gif | Bin 0 -> 155 bytes .../assets/theme/images/plate_bottom.png | Bin 0 -> 152 bytes src/common/assets/theme/images/plate_top.png | Bin 0 -> 152 bytes src/common/assets/theme/style.css | 312 +++ src/common/assets/xoops.css | 17 + src/common/blocks/MainMenu.tsx | 28 + src/common/blocks/SelectLang.tsx | 34 + src/common/lib/LangFlag.tsx | 38 + src/common/lib/LinkImage.tsx | 58 + src/common/lib/Loading.tsx | 12 + src/common/lib/NoticeSiteHasBeenArchived.tsx | 15 + src/common/lib/PageNotFound.tsx | 52 + src/common/lib/UserRankStarImage.tsx | 45 + src/common/lib/XoopsCode.tsx | 138 ++ src/config.ts | 17 + src/credits/Credits.tsx | 31 + src/credits/CreditsAboutUs.tsx | 24 + src/credits/CreditsPage.tsx | 46 + src/credits/CreditsXoopsPathRedirect.tsx | 53 + src/credits/block/CreditsMenu.tsx | 27 + src/credits/lib/CreditsUtils.ts | 73 + src/custom/blocks/Welcome.tsx | 78 + src/database/Database.module.css | 70 + src/database/Database.tsx | 44 + src/database/DatabaseAdvancedSearch.tsx | 48 + src/database/DatabaseDetailItem.tsx | 89 + .../DatabaseSearchByAdvancedKeyword.tsx | 56 + src/database/DatabaseSearchByIndexId.tsx | 88 + src/database/DatabaseSearchByItemType.tsx | 73 + src/database/DatabaseSearchByKeyword.tsx | 60 + src/database/DatabaseTop.module.css | 13 + src/database/DatabaseTop.tsx | 40 + src/database/DatabaseXoopsPathRedirect.tsx | 150 ++ src/database/assets/images/icon_binder.gif | Bin 0 -> 369 bytes src/database/assets/images/icon_book.gif | Bin 0 -> 375 bytes .../assets/images/icon_conference.gif | Bin 0 -> 427 bytes src/database/assets/images/icon_data.gif | Bin 0 -> 402 bytes src/database/assets/images/icon_files.gif | Bin 0 -> 433 bytes src/database/assets/images/icon_folder.gif | Bin 0 -> 1508 bytes src/database/assets/images/icon_memo.gif | Bin 0 -> 166 bytes src/database/assets/images/icon_model.gif | Bin 0 -> 409 bytes src/database/assets/images/icon_paper.gif | Bin 0 -> 479 bytes .../assets/images/icon_presentation.gif | Bin 0 -> 423 bytes src/database/assets/images/icon_simulator.gif | Bin 0 -> 562 bytes src/database/assets/images/icon_stimulus.gif | Bin 0 -> 302 bytes src/database/assets/images/icon_tool.gif | Bin 0 -> 399 bytes src/database/assets/images/icon_url.gif | Bin 0 -> 574 bytes src/database/assets/images/simpf_button.png | Bin 0 -> 6596 bytes src/database/assets/images/star.gif | Bin 0 -> 538 bytes src/database/assets/images/tree_line.png | Bin 0 -> 112 bytes src/database/assets/images/tree_node.png | Bin 0 -> 1251 bytes src/database/blocks/IndexTree.module.css | 90 + src/database/blocks/IndexTree.tsx | 113 ++ src/database/blocks/Rankings.module.css | 28 + src/database/blocks/Rankings.tsx | 66 + src/database/blocks/RecentContents.module.css | 28 + src/database/blocks/RecentContents.tsx | 39 + src/database/blocks/Search.tsx | 90 + .../item-type/binder/BinderAdvancedSearch.tsx | 26 + .../item-type/binder/BinderDetail.tsx | 95 + src/database/item-type/binder/BinderList.tsx | 28 + src/database/item-type/binder/BinderTop.tsx | 15 + src/database/item-type/binder/index.tsx | 13 + .../item-type/book/BookAdvancedSearch.tsx | 38 + src/database/item-type/book/BookDetail.tsx | 35 + src/database/item-type/book/BookList.tsx | 31 + src/database/item-type/book/BookTop.tsx | 15 + src/database/item-type/book/index.tsx | 13 + .../conference/ConferenceAdvancedSearch.tsx | 57 + .../item-type/conference/ConferenceDetail.tsx | 36 + .../item-type/conference/ConferenceList.tsx | 33 + .../item-type/conference/ConferenceTop.tsx | 19 + .../item-type/conference/ConferenceUtil.tsx | 37 + src/database/item-type/conference/index.tsx | 13 + .../item-type/data/DataAdvancedSearch.tsx | 46 + src/database/item-type/data/DataDetail.tsx | 44 + src/database/item-type/data/DataList.tsx | 31 + src/database/item-type/data/DataTop.tsx | 19 + src/database/item-type/data/DataUtil.tsx | 23 + src/database/item-type/data/index.tsx | 13 + .../item-type/files/FilesAdvancedSearch.tsx | 30 + src/database/item-type/files/FilesDetail.tsx | 33 + src/database/item-type/files/FilesList.tsx | 30 + src/database/item-type/files/FilesTop.tsx | 17 + src/database/item-type/files/FilesUtil.tsx | 5 + src/database/item-type/files/index.tsx | 13 + src/database/item-type/index.tsx | 179 ++ .../item-type/lib/AdvancedSearchBase.tsx | 189 ++ src/database/item-type/lib/DetailBase.tsx | 43 + src/database/item-type/lib/ListBase.tsx | 50 + src/database/item-type/lib/TopBase.tsx | 47 + src/database/item-type/lib/field/Author.tsx | 21 + .../item-type/lib/field/ChangeLog.tsx | 28 + .../item-type/lib/field/Contributer.tsx | 18 + .../item-type/lib/field/CreativeCommons.tsx | 56 + src/database/item-type/lib/field/DateTime.tsx | 21 + .../item-type/lib/field/Description.tsx | 18 + .../lib/field/FileDownloadButton.module.css | 21 + .../lib/field/FileDownloadButton.tsx | 55 + src/database/item-type/lib/field/FileSize.tsx | 17 + .../item-type/lib/field/FreeKeyword.tsx | 18 + src/database/item-type/lib/field/ItemFile.tsx | 50 + .../item-type/lib/field/ItemIndex.tsx | 26 + src/database/item-type/lib/field/Language.tsx | 35 + .../field/LicenseAgreementDialog.module.css | 38 + .../lib/field/LicenseAgreementDialog.tsx | 115 ++ .../item-type/lib/field/Preview.module.css | 23 + src/database/item-type/lib/field/Preview.tsx | 84 + .../item-type/lib/field/PublicationDate.tsx | 19 + src/database/item-type/lib/field/Readme.tsx | 15 + .../item-type/lib/field/RelatedTo.tsx | 74 + src/database/item-type/lib/field/Rights.tsx | 23 + .../item-type/lib/field/SimPFLinkIcon.tsx | 25 + src/database/item-type/lib/field/index.tsx | 39 + .../item-type/memo/MemoAdvancedSearch.tsx | 28 + src/database/item-type/memo/MemoDetail.tsx | 33 + src/database/item-type/memo/MemoList.tsx | 30 + src/database/item-type/memo/MemoTop.tsx | 15 + src/database/item-type/memo/index.tsx | 13 + .../item-type/model/ModelAdvancedSearch.tsx | 35 + src/database/item-type/model/ModelDetail.tsx | 43 + src/database/item-type/model/ModelList.tsx | 31 + src/database/item-type/model/ModelTop.tsx | 19 + src/database/item-type/model/ModelUtil.tsx | 23 + src/database/item-type/model/index.tsx | 13 + .../item-type/paper/PaperAdvancedSearch.tsx | 39 + src/database/item-type/paper/PaperDetail.tsx | 37 + src/database/item-type/paper/PaperList.tsx | 38 + src/database/item-type/paper/PaperTop.tsx | 15 + src/database/item-type/paper/PaperUtil.tsx | 22 + src/database/item-type/paper/index.tsx | 13 + .../PresentationAdvancedSearch.tsx | 46 + .../presentation/PresentationDetail.tsx | 37 + .../presentation/PresentationList.tsx | 33 + .../presentation/PresentationTop.tsx | 18 + .../presentation/PresentationUtil.tsx | 23 + src/database/item-type/presentation/index.tsx | 13 + .../simulator/SimulatorAdvancedSearch.tsx | 44 + .../item-type/simulator/SimulatorDetail.tsx | 44 + .../item-type/simulator/SimulatorList.tsx | 31 + .../item-type/simulator/SimulatorTop.tsx | 19 + .../item-type/simulator/SimulatorUtil.tsx | 23 + src/database/item-type/simulator/index.tsx | 13 + .../stimulus/StimulusAdvancedSearch.tsx | 44 + .../item-type/stimulus/StimulusDetail.tsx | 44 + .../item-type/stimulus/StimulusList.tsx | 31 + .../item-type/stimulus/StimulusTop.tsx | 19 + .../item-type/stimulus/StimulusUtil.tsx | 23 + src/database/item-type/stimulus/index.tsx | 13 + .../item-type/tool/ToolAdvancedSearch.tsx | 46 + src/database/item-type/tool/ToolDetail.tsx | 43 + src/database/item-type/tool/ToolList.tsx | 29 + src/database/item-type/tool/ToolTop.tsx | 19 + src/database/item-type/tool/ToolUtil.tsx | 23 + src/database/item-type/tool/index.tsx | 13 + .../item-type/url/UrlAdvancedSearch.tsx | 28 + src/database/item-type/url/UrlDetail.tsx | 32 + src/database/item-type/url/UrlList.tsx | 28 + src/database/item-type/url/UrlTop.tsx | 17 + src/database/item-type/url/UrlUtil.tsx | 28 + src/database/item-type/url/index.tsx | 13 + src/database/lib/AdvancedSearchQuery.ts | 95 + src/database/lib/DatabaseListIndex.tsx | 58 + src/database/lib/DatabaseListItem.module.css | 11 + src/database/lib/DatabaseListItem.tsx | 241 +++ src/database/lib/IndexUtil.ts | 95 + src/database/lib/ItemUtil.ts | 702 +++++++ src/functions.ts | 130 ++ src/index.css | 14 +- src/index.tsx | 2 + src/logo.svg | 7 - src/mediawiki/MediaWiki.tsx | 100 + src/mediawiki/MediaWikiXoopsPathRedirect.tsx | 35 + src/mediawiki/assets/style.css | 261 +++ src/mediawiki/lib/MediaWikiUtils.ts | 47 + src/pico/Pico.tsx | 61 + src/pico/PicoCategory.tsx | 84 + src/pico/PicoContent.tsx | 109 ++ src/pico/PicoIndex.tsx | 34 + src/pico/PicoMenu.tsx | 92 + src/pico/PicoXoopsPathRedirect.tsx | 43 + src/pico/assets/pico_main.css | 140 ++ src/pico/lib/PicoUtils.ts | 180 ++ yarn.lock | 1682 +++++++++++------ 254 files changed, 12433 insertions(+), 664 deletions(-) create mode 100644 etc/common.inc.php create mode 100644 etc/config.inc.php create mode 100644 etc/dumpCredits.php create mode 100644 etc/dumpMediaWiki.php create mode 100644 etc/dumpPico.php create mode 100644 etc/dumpXooNIps.php create mode 100644 etc/fixMediaWikiDumpData.php create mode 100644 etc/simpflink.csv create mode 100644 public/.htaccess delete mode 100644 public/logo192.png delete mode 100644 public/logo512.png create mode 100644 src/common/AppRoot.tsx create mode 100644 src/common/CenterColumn.tsx create mode 100644 src/common/Footer.tsx create mode 100644 src/common/Header.tsx create mode 100644 src/common/LeftColumn.tsx create mode 100644 src/common/MainContent.tsx create mode 100644 src/common/XoopsPathRedirect.tsx create mode 100644 src/common/assets/images/mlang_english.gif create mode 100644 src/common/assets/images/mlang_japanese.gif create mode 100644 src/common/assets/images/no_avatar.gif create mode 100644 src/common/assets/images/pagact.gif create mode 100644 src/common/assets/images/paginact.gif create mode 100644 src/common/assets/images/pagneutral.gif create mode 100644 src/common/assets/images/rank3dbf8e94a6f72.gif create mode 100644 src/common/assets/images/rank3dbf8e9e7d88d.gif create mode 100644 src/common/assets/images/rank3dbf8ea81e642.gif create mode 100644 src/common/assets/images/rank3dbf8eb1a72e7.gif create mode 100644 src/common/assets/images/rank3dbf8edf15093.gif create mode 100644 src/common/assets/images/rank3dbf8ee8681cd.gif create mode 100644 src/common/assets/images/rank3e632f95e81ca.gif create mode 100644 src/common/assets/images/smil3dbd4bf386b36.gif create mode 100644 src/common/assets/images/smil3dbd4d4e4c4f2.gif create mode 100644 src/common/assets/images/smil3dbd4d6422f04.gif create mode 100644 src/common/assets/images/smil3dbd4d75edb5e.gif create mode 100644 src/common/assets/images/smil3dbd4d8676346.gif create mode 100644 src/common/assets/images/smil3dbd4d99c6eaa.gif create mode 100644 src/common/assets/images/smil3dbd4daabd491.gif create mode 100644 src/common/assets/images/smil3dbd4dbc14f3f.gif create mode 100644 src/common/assets/images/smil3dbd4dcd7b9f4.gif create mode 100644 src/common/assets/images/smil3dbd4ddd6835f.gif create mode 100644 src/common/assets/images/smil3dbd4df1944ee.gif create mode 100644 src/common/assets/images/smil3dbd4e02c5440.gif create mode 100644 src/common/assets/images/smil3dbd4e1748cc9.gif create mode 100644 src/common/assets/images/smil3dbd4e29bbcc7.gif create mode 100644 src/common/assets/images/smil3dbd4e398ff7b.gif create mode 100644 src/common/assets/images/smil3dbd4e4c2e742.gif create mode 100644 src/common/assets/images/smil3dbd4e5e7563a.gif create mode 100644 src/common/assets/images/smil3dbd4e7853679.gif create mode 100644 src/common/assets/main-menu.json create mode 100644 src/common/assets/theme/images/arrow.png create mode 100644 src/common/assets/theme/images/banner_physiome.png create mode 100644 src/common/assets/theme/images/banner_riken-cbs.png create mode 100644 src/common/assets/theme/images/banner_riken.png create mode 100644 src/common/assets/theme/images/banner_xoonips.png create mode 100644 src/common/assets/theme/images/bg.png create mode 100644 src/common/assets/theme/images/brain-bike.png create mode 100644 src/common/assets/theme/images/i.png create mode 100644 src/common/assets/theme/images/icon_jnode.png create mode 100644 src/common/assets/theme/images/indent.png create mode 100644 src/common/assets/theme/images/indent_hover.png create mode 100644 src/common/assets/theme/images/logo.png create mode 100644 src/common/assets/theme/images/plate.png create mode 100644 src/common/assets/theme/images/plateB.gif create mode 100644 src/common/assets/theme/images/plate_bottom.png create mode 100644 src/common/assets/theme/images/plate_top.png create mode 100644 src/common/assets/theme/style.css create mode 100644 src/common/assets/xoops.css create mode 100644 src/common/blocks/MainMenu.tsx create mode 100644 src/common/blocks/SelectLang.tsx create mode 100644 src/common/lib/LangFlag.tsx create mode 100644 src/common/lib/LinkImage.tsx create mode 100644 src/common/lib/Loading.tsx create mode 100644 src/common/lib/NoticeSiteHasBeenArchived.tsx create mode 100644 src/common/lib/PageNotFound.tsx create mode 100644 src/common/lib/UserRankStarImage.tsx create mode 100644 src/common/lib/XoopsCode.tsx create mode 100644 src/config.ts create mode 100644 src/credits/Credits.tsx create mode 100644 src/credits/CreditsAboutUs.tsx create mode 100644 src/credits/CreditsPage.tsx create mode 100644 src/credits/CreditsXoopsPathRedirect.tsx create mode 100644 src/credits/block/CreditsMenu.tsx create mode 100644 src/credits/lib/CreditsUtils.ts create mode 100644 src/custom/blocks/Welcome.tsx create mode 100644 src/database/Database.module.css create mode 100644 src/database/Database.tsx create mode 100644 src/database/DatabaseAdvancedSearch.tsx create mode 100644 src/database/DatabaseDetailItem.tsx create mode 100644 src/database/DatabaseSearchByAdvancedKeyword.tsx create mode 100644 src/database/DatabaseSearchByIndexId.tsx create mode 100644 src/database/DatabaseSearchByItemType.tsx create mode 100644 src/database/DatabaseSearchByKeyword.tsx create mode 100644 src/database/DatabaseTop.module.css create mode 100644 src/database/DatabaseTop.tsx create mode 100644 src/database/DatabaseXoopsPathRedirect.tsx create mode 100644 src/database/assets/images/icon_binder.gif create mode 100644 src/database/assets/images/icon_book.gif create mode 100644 src/database/assets/images/icon_conference.gif create mode 100644 src/database/assets/images/icon_data.gif create mode 100644 src/database/assets/images/icon_files.gif create mode 100644 src/database/assets/images/icon_folder.gif create mode 100644 src/database/assets/images/icon_memo.gif create mode 100644 src/database/assets/images/icon_model.gif create mode 100644 src/database/assets/images/icon_paper.gif create mode 100644 src/database/assets/images/icon_presentation.gif create mode 100644 src/database/assets/images/icon_simulator.gif create mode 100644 src/database/assets/images/icon_stimulus.gif create mode 100644 src/database/assets/images/icon_tool.gif create mode 100644 src/database/assets/images/icon_url.gif create mode 100644 src/database/assets/images/simpf_button.png create mode 100644 src/database/assets/images/star.gif create mode 100644 src/database/assets/images/tree_line.png create mode 100644 src/database/assets/images/tree_node.png create mode 100644 src/database/blocks/IndexTree.module.css create mode 100644 src/database/blocks/IndexTree.tsx create mode 100644 src/database/blocks/Rankings.module.css create mode 100644 src/database/blocks/Rankings.tsx create mode 100644 src/database/blocks/RecentContents.module.css create mode 100644 src/database/blocks/RecentContents.tsx create mode 100644 src/database/blocks/Search.tsx create mode 100644 src/database/item-type/binder/BinderAdvancedSearch.tsx create mode 100644 src/database/item-type/binder/BinderDetail.tsx create mode 100644 src/database/item-type/binder/BinderList.tsx create mode 100644 src/database/item-type/binder/BinderTop.tsx create mode 100644 src/database/item-type/binder/index.tsx create mode 100644 src/database/item-type/book/BookAdvancedSearch.tsx create mode 100644 src/database/item-type/book/BookDetail.tsx create mode 100644 src/database/item-type/book/BookList.tsx create mode 100644 src/database/item-type/book/BookTop.tsx create mode 100644 src/database/item-type/book/index.tsx create mode 100644 src/database/item-type/conference/ConferenceAdvancedSearch.tsx create mode 100644 src/database/item-type/conference/ConferenceDetail.tsx create mode 100644 src/database/item-type/conference/ConferenceList.tsx create mode 100644 src/database/item-type/conference/ConferenceTop.tsx create mode 100644 src/database/item-type/conference/ConferenceUtil.tsx create mode 100644 src/database/item-type/conference/index.tsx create mode 100644 src/database/item-type/data/DataAdvancedSearch.tsx create mode 100644 src/database/item-type/data/DataDetail.tsx create mode 100644 src/database/item-type/data/DataList.tsx create mode 100644 src/database/item-type/data/DataTop.tsx create mode 100644 src/database/item-type/data/DataUtil.tsx create mode 100644 src/database/item-type/data/index.tsx create mode 100644 src/database/item-type/files/FilesAdvancedSearch.tsx create mode 100644 src/database/item-type/files/FilesDetail.tsx create mode 100644 src/database/item-type/files/FilesList.tsx create mode 100644 src/database/item-type/files/FilesTop.tsx create mode 100644 src/database/item-type/files/FilesUtil.tsx create mode 100644 src/database/item-type/files/index.tsx create mode 100644 src/database/item-type/index.tsx create mode 100644 src/database/item-type/lib/AdvancedSearchBase.tsx create mode 100644 src/database/item-type/lib/DetailBase.tsx create mode 100644 src/database/item-type/lib/ListBase.tsx create mode 100644 src/database/item-type/lib/TopBase.tsx create mode 100644 src/database/item-type/lib/field/Author.tsx create mode 100644 src/database/item-type/lib/field/ChangeLog.tsx create mode 100644 src/database/item-type/lib/field/Contributer.tsx create mode 100644 src/database/item-type/lib/field/CreativeCommons.tsx create mode 100644 src/database/item-type/lib/field/DateTime.tsx create mode 100644 src/database/item-type/lib/field/Description.tsx create mode 100644 src/database/item-type/lib/field/FileDownloadButton.module.css create mode 100644 src/database/item-type/lib/field/FileDownloadButton.tsx create mode 100644 src/database/item-type/lib/field/FileSize.tsx create mode 100644 src/database/item-type/lib/field/FreeKeyword.tsx create mode 100644 src/database/item-type/lib/field/ItemFile.tsx create mode 100644 src/database/item-type/lib/field/ItemIndex.tsx create mode 100644 src/database/item-type/lib/field/Language.tsx create mode 100644 src/database/item-type/lib/field/LicenseAgreementDialog.module.css create mode 100644 src/database/item-type/lib/field/LicenseAgreementDialog.tsx create mode 100644 src/database/item-type/lib/field/Preview.module.css create mode 100644 src/database/item-type/lib/field/Preview.tsx create mode 100644 src/database/item-type/lib/field/PublicationDate.tsx create mode 100644 src/database/item-type/lib/field/Readme.tsx create mode 100644 src/database/item-type/lib/field/RelatedTo.tsx create mode 100644 src/database/item-type/lib/field/Rights.tsx create mode 100644 src/database/item-type/lib/field/SimPFLinkIcon.tsx create mode 100644 src/database/item-type/lib/field/index.tsx create mode 100644 src/database/item-type/memo/MemoAdvancedSearch.tsx create mode 100644 src/database/item-type/memo/MemoDetail.tsx create mode 100644 src/database/item-type/memo/MemoList.tsx create mode 100644 src/database/item-type/memo/MemoTop.tsx create mode 100644 src/database/item-type/memo/index.tsx create mode 100644 src/database/item-type/model/ModelAdvancedSearch.tsx create mode 100644 src/database/item-type/model/ModelDetail.tsx create mode 100644 src/database/item-type/model/ModelList.tsx create mode 100644 src/database/item-type/model/ModelTop.tsx create mode 100644 src/database/item-type/model/ModelUtil.tsx create mode 100644 src/database/item-type/model/index.tsx create mode 100644 src/database/item-type/paper/PaperAdvancedSearch.tsx create mode 100644 src/database/item-type/paper/PaperDetail.tsx create mode 100644 src/database/item-type/paper/PaperList.tsx create mode 100644 src/database/item-type/paper/PaperTop.tsx create mode 100644 src/database/item-type/paper/PaperUtil.tsx create mode 100644 src/database/item-type/paper/index.tsx create mode 100644 src/database/item-type/presentation/PresentationAdvancedSearch.tsx create mode 100644 src/database/item-type/presentation/PresentationDetail.tsx create mode 100644 src/database/item-type/presentation/PresentationList.tsx create mode 100644 src/database/item-type/presentation/PresentationTop.tsx create mode 100644 src/database/item-type/presentation/PresentationUtil.tsx create mode 100644 src/database/item-type/presentation/index.tsx create mode 100644 src/database/item-type/simulator/SimulatorAdvancedSearch.tsx create mode 100644 src/database/item-type/simulator/SimulatorDetail.tsx create mode 100644 src/database/item-type/simulator/SimulatorList.tsx create mode 100644 src/database/item-type/simulator/SimulatorTop.tsx create mode 100644 src/database/item-type/simulator/SimulatorUtil.tsx create mode 100644 src/database/item-type/simulator/index.tsx create mode 100644 src/database/item-type/stimulus/StimulusAdvancedSearch.tsx create mode 100644 src/database/item-type/stimulus/StimulusDetail.tsx create mode 100644 src/database/item-type/stimulus/StimulusList.tsx create mode 100644 src/database/item-type/stimulus/StimulusTop.tsx create mode 100644 src/database/item-type/stimulus/StimulusUtil.tsx create mode 100644 src/database/item-type/stimulus/index.tsx create mode 100644 src/database/item-type/tool/ToolAdvancedSearch.tsx create mode 100644 src/database/item-type/tool/ToolDetail.tsx create mode 100644 src/database/item-type/tool/ToolList.tsx create mode 100644 src/database/item-type/tool/ToolTop.tsx create mode 100644 src/database/item-type/tool/ToolUtil.tsx create mode 100644 src/database/item-type/tool/index.tsx create mode 100644 src/database/item-type/url/UrlAdvancedSearch.tsx create mode 100644 src/database/item-type/url/UrlDetail.tsx create mode 100644 src/database/item-type/url/UrlList.tsx create mode 100644 src/database/item-type/url/UrlTop.tsx create mode 100644 src/database/item-type/url/UrlUtil.tsx create mode 100644 src/database/item-type/url/index.tsx create mode 100644 src/database/lib/AdvancedSearchQuery.ts create mode 100644 src/database/lib/DatabaseListIndex.tsx create mode 100644 src/database/lib/DatabaseListItem.module.css create mode 100644 src/database/lib/DatabaseListItem.tsx create mode 100644 src/database/lib/IndexUtil.ts create mode 100644 src/database/lib/ItemUtil.ts create mode 100644 src/functions.ts delete mode 100644 src/logo.svg create mode 100644 src/mediawiki/MediaWiki.tsx create mode 100644 src/mediawiki/MediaWikiXoopsPathRedirect.tsx create mode 100644 src/mediawiki/assets/style.css create mode 100644 src/mediawiki/lib/MediaWikiUtils.ts create mode 100644 src/pico/Pico.tsx create mode 100644 src/pico/PicoCategory.tsx create mode 100644 src/pico/PicoContent.tsx create mode 100644 src/pico/PicoIndex.tsx create mode 100644 src/pico/PicoMenu.tsx create mode 100644 src/pico/PicoXoopsPathRedirect.tsx create mode 100644 src/pico/assets/pico_main.css create mode 100644 src/pico/lib/PicoUtils.ts diff --git a/.gitignore b/.gitignore index 4d29575..c4db695 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,15 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +# database contents +/dl-limit-items.csv +/public/database +/public/credits +/public/documents +/public/hackathon +/public/mediawiki +/src/database/assets/*.json +/src/credits/assets/*.json +/src/pico/assets/*.json +/src/mediawiki/assets/*.json diff --git a/etc/common.inc.php b/etc/common.inc.php new file mode 100644 index 0000000..ce60f39 --- /dev/null +++ b/etc/common.inc.php @@ -0,0 +1,197 @@ + $v) { + if (is_string($v)) { + $v = $textutil->html_numeric_entities($v); + $v = mb_decode_numericentity($v, array(0x0, 0x10000, 0, 0xfffff), 'UTF-8'); + $data[$k] = \Normalizer::normalize(trim($v), \Normalizer::FORM_C); + } elseif (null === $v) { + $data[$k] = ''; + } + } + } + + public static function convertToInt(&$data, $keys, $zerofill = false) + { + foreach ($keys as $key) { + if (isset($data[$key])) { + $data[$key] = '' === $data[$key] ? ($zerofill ? 0 : null) : (int) $data[$key]; + } + } + } + + public static function dropColumn(&$data, $keys) + { + foreach ($keys as $key) { + if (isset($data[$key])) { + unset($data[$key]); + } + } + } + + public static function fileCopy($from, $to) + { + system('rsync -aq '.escapeshellarg($from).' '.escapeshellarg($to), $ret); + + return 0 === $ret; + } + + public static function fixHtml($text) + { + static $config = [ + //'clean' => true, + 'hide-comments' => true, + 'indent' => true, + 'output-xhtml' => true, + 'preserve-entities' => true, + 'show-body-only' => true, + 'wrap' => 0, + 'input-encoding' => 'utf8', + 'output-encoding' => 'utf8', + 'output-bom' => false, + ]; + $text = tidy_repair_string($text, $config); + $text = preg_replace('/]*)>((?:\s*]*>.*<\/caption>)?\s*)]*)>/Us', '\2', $text); + $text = preg_replace('/<\/tr>(\s*)<\/table>/s', '\1', $text); + + return $text; + } + + public static function tableExists($name) + { + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $sql = <<< SQL +SELECT 1 + FROM `${prefix}_${name}` + LIMIT 1 +SQL; + if (!($res = $xoopsDB->query($sql))) { + return false; + } + $xoopsDB->freeRecordSet($res); + + return true; + } + + public static function makeDirectory($dirname) + { + $path = MYDUMPTOOL_OUTPUTDIR.('' !== $dirname ? '/'.$dirname : ''); + if (!is_dir($path)) { + if (!@mkdir($path)) { + exit('Failed to create directory: '.$path.PHP_EOL); + } + } + } + + public static function saveJson($fname, $data) + { + $path = MYDUMPTOOL_OUTPUTDIR.'/'.$fname; + if (false === file_put_contents($path, json_encode($data, JSON_UNESCAPED_UNICODE))) { + exit('Failed to save json file: '.$path.PHP_EOL); + } + } + + public static function fileDownload($url, $fpath) + { + $fp = fopen($fpath, 'w'); + if (false === $fp) { + exit('Failed to open file: '.$fpath.PHP_EOL); + } + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_AUTOREFERER, true); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_FAILONERROR, true); + curl_setopt($curl, CURLOPT_FILE, $fp); + curl_setopt($curl, CURLOPT_TIMEOUT, 10); + $ret = curl_exec($curl); + fclose($fp); + if (false === $ret) { + exit('Failed to download file, unexpected error: '.$url.PHP_EOL); + } + $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if (200 !== $code) { + exit('Failed to download file, invalid status code('.$code.'): '.$url.PHP_EOL); + } + curl_close($curl); + + return true; + } + + public static function getMimeType($fpath) + { + $finfo = finfo_open(FILEINFO_MIME); + $mime = finfo_file($finfo, $fpath); + finfo_close($finfo); + $mime = preg_replace('/(;.*)$/', '', $mime); + + return $mime; + } +} diff --git a/etc/config.inc.php b/etc/config.inc.php new file mode 100644 index 0000000..ac6a14d --- /dev/null +++ b/etc/config.inc.php @@ -0,0 +1,9 @@ +prefix(); + +$table = 'nipfcredits_organization'; +if (!MyDumpTool::tableExists($table)) { + exit('credits module not found'.PHP_EOL); +} +MyDumpTool::makeDirectory('src/credits'); +MyDumpTool::makeDirectory('src/credits/assets'); + +// organization +$organization = []; +$sql = <<< SQL +SELECT + `o`.* + FROM `${prefix}_nipfcredits_organization` AS `o` +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + $organization = $row; +} +$xoopsDB->freeRecordSet($res); +$organization['com_email'] = str_replace('@', ' (at) ', $organization['com_email']); +$organization['com_url'] = XOOPS_URL; +$organization['institute'] = 'Neuroinformatics Unit, RIKEN Center for Brain Science'; +$organization['url'] = 'https://www.ni.riken.jp/'; +$organization['email'] = 'office (at) ni.riken.jp'; +$organization['address'] = 'Hirosawa 2-1, Wako, Saitama, 351-0198 Japan'; +$organization['tel'] = '+81 48 (462) 1111'; + +// member +$member = []; +$sql = <<< SQL +SELECT + `m`.* + FROM `${prefix}_nipfcredits_member` AS `m` + ORDER BY `m`.`weight` +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + $member[] = $row; +} +$xoopsDB->freeRecordSet($res); +$opage = getOrganizationPage($organization, $member); +//var_dump($opage); + +// pages +$pages = []; +$sql = <<< SQL +SELECT + `p`.* + FROM `${prefix}_nipfcredits_page` AS `p` + ORDER BY `p`.`weight` +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + myDumpTool::convertToInt($row, ['pid', 'weight', 'lastupdate']); + $content = replaceOrganization($row['content'], $organization); + $content = MyDumpTool::fixHtml($content); + $content = preg_replace('/href="(?:\.\/|'.preg_quote(XOOPS_URL, '/').'\/modules\/credits\/)?index\.php\?id=(\d+)"/', 'href="/credits/\1"', $content); + $imageUrl = []; + $content = preg_replace_callback('/]*)src="([^"]+)"([^>]*)\/>/Usi', function ($matches) use (&$imageUrl, $row) { + $url = $matches[2]; + if (preg_match('/^(.+)\/([^\/]+\.(:?png|jpg|gif|svg))(\?.+)?$/i', $url, $m)) { + if (!isset($imageUrl[$m[1]])) { + $imageUrl[$m[1]] = count($imageUrl) + 1; + } + $id = $imageUrl[$m[1]]; + $fname = '/credits/images/'.$row['pid'].'/'.$id.'/'.urldecode($m[2]); + $fpath = MYDUMPTOOL_OUTPUTDIR.'/public'.$fname; + if (!file_exists($fpath)) { + MyDumpTool::makeDirectory('public/credits'); + MyDumpTool::makeDirectory('public/credits/images'); + MyDumpTool::makeDirectory('public/credits/images/'.$row['pid']); + MyDumpTool::makeDirectory('public/credits/images/'.$row['pid'].'/'.$id); + if (preg_match('/^\//', $url)) { + $url = XOOPS_URL.$url; + } + MyDumpTool::fileDownload($url, $fpath); + } + $url = '/credits/images/'.$row['pid'].'/'.$id.'/'.$m[2]; + } + + return ''; + }, $content); + $content = preg_replace('/]*)href="(?:'.preg_quote(XOOPS_URL, '/').')?\/modules\/xoonips\/(?:register|edit|user)[^"]*"(?:[^>]*)>(.*)<\/a>/Usi', '\1(closed)', $content); + $row['content'] = $content; + MyDumpTool::dropColumn($row, ['weight']); + $pages[] = $row; +} +$xoopsDB->freeRecordSet($res); +//var_dump($pages); + +$data = [ + 'organization' => $opage, + 'pages' => $pages, +]; +MyDumpTool::saveJson('src/credits/assets/credits.json', $data); + +function replaceOrganization($text, $org) +{ + $textutil = xoonips_getutility('text'); + $map = [ + '{COMMITTEE_NAME}' => $textutil->html_special_chars($org['committee']), + '{COMMITTEE_EMAIL}' => ''.$textutil->html_special_chars($org['com_email']).'(committee email has been closed)', + '{INSTITUTE_NAME}' => $textutil->html_special_chars($org['institute']), + '{INSTITUTE_URL}' => $textutil->html_special_chars($org['url']), + '{INSTITUTE_EMAIL}' => $textutil->html_special_chars($org['email']), + '{INSTITUTE_ADDRESS}' => $textutil->html_special_chars($org['address']), + '{INSTITUTE_TEL}' => $textutil->html_special_chars($org['tel']), + '{PLATFORM_URL}' => XOOPS_URL, + ]; + + return str_replace(array_keys($map), $map, $text); +} + +function getOrganizationPage($org, $member) +{ + $textutil = xoonips_getutility('text'); + $members = []; + foreach ($member as $m) { + $members[] = '
  • '.$textutil->html_special_chars($m['name'].' : '.$m['division']).'
  • '; + } + $members = implode("\n", $members); + $committee = $textutil->html_special_chars($org['committee']); + $institute = $textutil->html_special_chars($org['institute']); + $address = $textutil->html_special_chars($org['address']); + $url = $textutil->html_special_chars($org['url']); + $html = <<< HTML +

    ${committee}

    +
      +
    • Members +
        +${members} +
      +
    • +
    +HTML; + + return $html; +} diff --git a/etc/dumpMediaWiki.php b/etc/dumpMediaWiki.php new file mode 100644 index 0000000..ebb76e6 --- /dev/null +++ b/etc/dumpMediaWiki.php @@ -0,0 +1,198 @@ +makedir(__DIR__.'/data'); + $this->makedir(__DIR__.'/data/src'); + $this->makedir(__DIR__.'/data/src/mediawiki'); + $this->makedir(__DIR__.'/data/src/mediawiki/assets'); + $this->makedir(__DIR__.'/data/public'); + $this->makedir(__DIR__.'/data/public/mediawiki'); + $this->makedir(__DIR__.'/data/public/mediawiki/images'); + $this->makedir(__DIR__.'/data/public/mediawiki/contents'); + $this->makedir(__DIR__.'/temp'); + $this->makedir(__DIR__.'/temp/mediawiki'); + $url = API_URL.'?action=query&list=allpages&aplimit=500&utf8=&format=json'; + $json = $this->fetchData($url); + $data = json_decode($json, true); + $allpages = $data['query']['allpages']; + $num = 0; + $start = 0; + foreach ($allpages as $page) { + if ($num < $start) { + ++$num; + continue; + } + $name = urlencode(str_replace(' ', '_', $page['title'])); + $url = API_URL.'?action=parse&format=json&page='.$name; + $json = $this->fetchData($url); + $data = json_decode($json, true); + $detail = $data['parse']; + echo $num.'('.$detail['revid'].'): '.$page['title'].PHP_EOL; + $mwlist[] = [ + 'id' => (int) $detail['revid'], + 'title' => $page['title'], + ]; + if (!isset($detail['images'])) { + var_dump($json); + var_dump($page); + var_dump($name); + var_dump($data); + exit(); + } + foreach ($detail['images'] as $image) { + $fpath = $this->getImagePath(IMAGE_DIR, $image); + if (!file_exists($fpath)) { + exit('File not found: '.$fpath.PHP_EOL); + } + $dfpath = $this->getImagePath(DEST_IMAGE_DIR, $image); + $pddpath = dirname($dfpath); + $ppddpath = dirname($pddpath); + $this->makedir($ppddpath); + $this->makedir($pddpath); + $this->fileCopy($fpath, $dfpath); + } + $text = $this->fixHtml($detail['text']['*']); + $title = $detail['title']; + $sections = []; + foreach ($detail['sections'] as $section) { + $sections[] = [ + 'toclevel' => $section['toclevel'], + 'line' => $section['line'], + 'number' => $section['number'], + 'anchor' => $section['anchor'], + ]; + } + $data = [ + 'title' => $title, + 'text' => $text, + 'sections' => $sections, + ]; + $fname = __DIR__.'/temp/mediawiki/'.$detail['revid'].'.dump.json'; + file_put_contents($fname, json_encode($data, JSON_UNESCAPED_UNICODE)); + ++$num; + } + $fname = __DIR__.'/data/src/mediawiki/assets/contents.json'; + file_put_contents($fname, json_encode($mwlist, JSON_UNESCAPED_UNICODE)); + + echo "Hello, World!\n"; + } + + public function fixHtml($text) + { + $text = preg_replace('/\[<\/span>
    edit<\/a>\]<\/span><\/span>/Us', '', $text); + $text = preg_replace('/([^<]+)<\/a>/Us', '\1', $text); + $text = preg_replace('/
  • \s*(.*)\s*<\/li>/Us', '
  • \1
  • ', $text); + $text = preg_replace('//Us', '', $text); + $text = trim($text); + + return $text; + } + + public function makedir($path) + { + if (is_dir($path)) { + return true; + } + if (false === @mkdir($path)) { + exit('Failed to create directroy: '.$path.PHP_EOL); + } + + return true; + } + + public function getImagePath($basedir, $fname) + { + $hash = md5($fname); + + return $basedir.'/'.substr($hash, 0, 1).'/'.substr($hash, 0, 2).'/'.$fname; + } + + public function fileCopy($from, $to) + { + system('rsync -aq '.escapeshellarg($from).' '.escapeshellarg($to), $ret); + if (0 !== $ret) { + exit('Failed to copy file: '.$from.' -> '.$to.PHP_EOL); + } + + return 0 === $ret; + } + + public function fetchData($url) + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_AUTOREFERER, true); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_FAILONERROR, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 5); + $ret = curl_exec($curl); + if (false === $ret) { + exit('Failed to fetch data, unexpected error: '.$url.PHP_EOL); + } + $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if (200 !== $code) { + exit('Failed to fetch data, invalid status code('.$code.'): '.$url.PHP_EOL); + } + curl_close($curl); + + return $ret; + } + + public function fileDownload($url, $fpath) + { + $fp = fopen($fpath, 'w'); + if (false === $fp) { + exit('Failed to open file: '.$fpath.PHP_EOL); + } + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_AUTOREFERER, true); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_FAILONERROR, true); + curl_setopt($curl, CURLOPT_FILE, $fp); + curl_setopt($curl, CURLOPT_TIMEOUT, 5); + $ret = curl_exec($curl); + fclose($fp); + if (false === $ret) { + exit('Failed to download file, unexpected error: '.$url.PHP_EOL); + } + $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if (200 !== $code) { + exit('Failed to download file, invalid status code('.$code.'): '.$url.PHP_EOL); + } + curl_close($curl); + + return true; + } +} + +$maintClass = DumpMediaWiki::class; + +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/etc/dumpPico.php b/etc/dumpPico.php new file mode 100644 index 0000000..a76348f --- /dev/null +++ b/etc/dumpPico.php @@ -0,0 +1,163 @@ +prefix(); + $table = $pico.'_contents'; + if (!MyDumpTool::tableExists($table)) { + exit('pico('.$pico.') module not found'.PHP_EOL); + } + MyDumpTool::makeDirectory('public/'.$pico); + MyDumpTool::makeDirectory('public/'.$pico.'/images'); + $moduleHandler = xoops_gethandler('module'); + $module = $moduleHandler->getByDirname($pico); + $moduleConfigHandler = xoops_gethandler('config'); + $moduleConfig = $moduleConfigHandler->getConfigsByDirname($pico); + $permObj = PicoPermission::getInstance(); + $perms = $permObj->getPermissions($pico); + $categoryHandler = new PicoCategoryHandler($pico, $perms); + $contentHandler = new PicoContentHandler($pico); + $cats = $categoryHandler->getAllCategories(); + $confContents = []; + $confCategories = []; + foreach ($cats as $cat) { + $catData = $cat->getData(); + $modConfig = $cat->getOverriddenModConfig(); + $link = pico_common_make_category_link4html($modConfig, $catData, $pico); + MyDumpTool::decode($catData); + $confCategories[] = [ + 'id' => $catData['id'], + 'title' => $catData['cat_title'], + 'desc' => (string) $catData['cat_desc'], + 'pid' => (int) $catData['pid'], + 'weight' => (int) $catData['cat_weight'], + 'link' => $link, + ]; + $contents = $contentHandler->getCategoryContents($cat); + foreach ($contents as $content) { + $data = $content->getData(); + $link = pico_common_make_content_link4html($modConfig, $data); + MyDumpTool::decode($data); + $content = MyDumpTool::fixHtml($data['body_cached']); + $imageId = 1; + $dataId = []; + $content = preg_replace_callback('/]*)src="(.*)"([^>]*)\/>/Us', function ($matches) use (&$imageId, $pico, $data, $link) { + $url = $matches[2]; + if (!preg_match('/^http/', $url)) { + if (preg_match('/^\//', $url)) { + $url = XOOPS_URL.$url; + } else { + $xpath = dirname($link); + $url = XOOPS_URL.'/modules/'.$pico.'/'.$xpath.'/'.$url; + } + } + $fname = '/'.$pico.'/images/'.$data['id'].'_'.$imageId.'.dat'; + $fpath = MYDUMPTOOL_OUTPUTDIR.'/public'.$fname; + MyDumpTool::fileDownload($url, $fpath); + $mime = MyDumpTool::getMimeType($fpath); + switch ($mime) { + case 'image/gif': + $fpath_ = preg_replace('/.dat$/', '.gif', $fpath); + $fname = preg_replace('/.dat$/', '.gif', $fname); + rename($fpath, $fpath_); + $fpath = $fpath_; + break; + case 'image/png': + $fpath_ = preg_replace('/.dat$/', '.png', $fpath); + $fname = preg_replace('/.dat$/', '.png', $fname); + rename($fpath, $fpath_); + $fpath = $fpath_; + break; + case 'image/jpeg': + $fpath_ = preg_replace('/.dat$/', '.jpeg', $fpath); + $fname = preg_replace('/.dat$/', '.jpeg', $fname); + rename($fpath, $fpath_); + $fpath = $fpath_; + break; + default: + exit('unknown mime type '.$mime.' found: '.$fname.' from '.$url.PHP_EOL); + } + ++$imageId; + + return ''; + }, $content); + $content = preg_replace_callback('/
    ]*)href="([^"]+)"([^>]*)>/Us', function ($matches) use (&$dataId, $pico, $data, $link) { + $url = $matches[2]; + if (preg_match('/^(.+)\/([^\/]+\.pdf)(\?.+)?$/', $url, $m)) { + if (!isset($dataId[$m[1]])) { + $dataId[$m[1]] = count($dataId) + 1; + } + $id = $dataId[$m[1]]; + $fname = '/'.$pico.'/data/'.$data['id'].'/'.$id.'/'.urldecode($m[2]); + $fpath = MYDUMPTOOL_OUTPUTDIR.'/public'.$fname; + if (!file_exists($fpath)) { + MyDumpTool::makeDirectory('public/'.$pico.'/data'); + MyDumpTool::makeDirectory('public/'.$pico.'/data/'.$data['id']); + MyDumpTool::makeDirectory('public/'.$pico.'/data/'.$data['id'].'/'.$id); + if (preg_match('/^\//', $url)) { + $url = XOOPS_URL.$url; + } + MyDumpTool::fileDownload($url, $fpath); + } + $url = '/'.$pico.'/data/'.$data['id'].'/'.$id.'/'.$m[2]; + } + + return ''; + }, $content); + $item = [ + 'id' => $data['id'], + 'title' => $data['subject_raw'], + 'content' => $content, + ]; + MyDumpTool::saveJson('public/'.$pico.'/'.$data['id'].'.json', $item); + $confContents[] = [ + 'id' => $item['id'], + 'title' => $data['subject_raw'], + 'cat_id' => (int) $data['cat_id'], + 'weight' => (int) $data['weight'], + 'link' => $link, + ]; + } + } + $moduleinfo = [ + 'name' => $module->get('name'), + 'dirname' => $pico, + 'message' => $moduleConfig['top_message'], + 'show_menuinmoduletop' => (int) $moduleConfig['show_menuinmoduletop'], + 'show_listasindex' => (int) $moduleConfig['show_listasindex'], + 'show_breadcrumbs' => (int) $moduleConfig['show_breadcrumbs'], + 'show_pagenavi' => (int) $moduleConfig['show_pagenavi'], + ]; + MyDumpTool::decode($moduleinfo); + $config[] = [ + 'module' => $moduleinfo, + 'categories' => $confCategories, + 'contents' => $confContents, + ]; +} diff --git a/etc/dumpXooNIps.php b/etc/dumpXooNIps.php new file mode 100644 index 0000000..5ae025b --- /dev/null +++ b/etc/dumpXooNIps.php @@ -0,0 +1,1176 @@ +prefix(); + +$table = 'xoonips_item_basic'; +if (!MyDumpTool::tableExists($table)) { + exit('xoonips module not found'.PHP_EOL); +} +MyDumpTool::makeDirectory('src/database'); +MyDumpTool::makeDirectory('src/database/assets'); +MyDumpTool::makeDirectory('public/database'); +MyDumpTool::makeDirectory('public/database/file'); + +// Recent Contents +$sql = <<< SQL +SELECT + `ib`.`item_id`, `ib`.`doi`, `ib`.`last_update_date`, + GROUP_CONCAT(DISTINCT `it`.`title` ORDER BY `it`.`title_id` ASC SEPARATOR '\n') AS `title` + FROM `${prefix}_xoonips_ranking_new_item` AS `ri` + INNER JOIN `${prefix}_xoonips_item_basic` AS `ib` ON `ri`.`item_id`=`ib`.`item_id` + INNER JOIN `${prefix}_xoonips_index_item_link` AS `iil` ON `ib`.`item_id`=`iil`.`item_id` + INNER JOIN `${prefix}_xoonips_item_title` AS `it` ON `ib`.`item_id`=`it`.`item_id` + WHERE `iil`.`certify_state`=2 + GROUP BY `ib`.`item_id` + ORDER BY `ib`.`last_update_date` DESC +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +$ranking = []; +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('item_id', 'last_update_date')); + $ranking[] = $row; +} +$xoopsDB->freeRecordSet($res); +MyDumpTool::saveJson('src/database/assets/recent-contents.json', $ranking); +unset($ranking); + +// Rankings +$ranking = []; +$rankingLimit = defined('XOONIPS_RANNKING_LIMIT') ? XOONIPS_RANNKING_LIMIT : 10; +// - most accessed items +$ranking['accessed'] = []; +$sql = <<< SQL +SELECT + `ib`.`item_id`, `ib`.`doi`, + GROUP_CONCAT(DISTINCT `it`.`title` ORDER BY `it`.`title_id` ASC SEPARATOR '\n') AS `title`, + `vi`.`count` + FROM `${prefix}_xoonips_ranking_viewed_item` AS `vi` + INNER JOIN `${prefix}_xoonips_item_basic` AS `ib` ON `vi`.`item_id`=`ib`.`item_id` + INNER JOIN `${prefix}_xoonips_item_title` AS `it` ON `ib`.`item_id`=`it`.`item_id` + INNER JOIN `${prefix}_xoonips_index_item_link` AS `iil` ON `ib`.`item_id`=`iil`.`item_id` + WHERE `iil`.`certify_state`=2 + GROUP BY `ib`.`item_id` + ORDER BY `vi`.`count` DESC + LIMIT ${rankingLimit} +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('item_id', 'count')); + $ranking['accessed'][] = $row; +} +$xoopsDB->freeRecordSet($res); +// - most accessed items +$ranking['downloaded'] = []; +$sql = <<< SQL +SELECT + `ib`.`item_id`, `ib`.`doi`, + GROUP_CONCAT(DISTINCT `it`.`title` ORDER BY `it`.`title_id` ASC SEPARATOR '\n') AS `title`, + `di`.`count` + FROM `${prefix}_xoonips_ranking_downloaded_item` AS `di` + INNER JOIN `${prefix}_xoonips_item_basic` AS `ib` ON `di`.`item_id`=`ib`.`item_id` + INNER JOIN `${prefix}_xoonips_item_title` AS `it` ON `ib`.`item_id`=`it`.`item_id` + INNER JOIN `${prefix}_xoonips_index_item_link` AS `iil` ON `ib`.`item_id`=`iil`.`item_id` + WHERE `iil`.`certify_state`=2 + GROUP BY `ib`.`item_id` + ORDER BY `di`.`count` DESC + LIMIT ${rankingLimit} +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('item_id', 'count')); + $ranking['downloaded'][] = $row; +} +$xoopsDB->freeRecordSet($res); +// - most contributed users +$ranking['contributed'] = []; +$sql = <<< SQL +SELECT + `u`.`uid`, `u`.`uname`, `u`.`name`, COUNT(`cu`.`item_id`) AS `count` + FROM `${prefix}_xoonips_ranking_contributing_user` AS `cu` + INNER JOIN `${prefix}_users` AS `u` ON `cu`.`uid`=`u`.`uid` + GROUP BY `u`.`uid` + ORDER BY `count` DESC + LIMIT ${rankingLimit} +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('uid', 'count')); + $ranking['contributed'][] = $row; +} +$xoopsDB->freeRecordSet($res); +// - most searched keywords +$ranking['searched'] = []; +$sql = <<< SQL +SELECT + `sk`.`keyword`, `sk`.`count` + FROM `${prefix}_xoonips_ranking_searched_keyword` AS `sk` + ORDER BY `sk`.`count` DESC + LIMIT ${rankingLimit} +SQL; +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('count')); + $ranking['searched'][] = $row; +} +$xoopsDB->freeRecordSet($res); +MyDumpTool::saveJson('src/database/assets/rankings.json', $ranking); +unset($ranking); + +// get public index with certified item count +$sql = <<< SQL +SELECT + `idx`.*, + `it`.`title`, + (SELECT COUNT(*) + FROM `${prefix}_xoonips_index_item_link` AS `iil` + INNER JOIN `${prefix}_xoonips_item_basic` AS `ib` ON `iil`.`item_id`=`ib`.`item_id` + WHERE `iil`.`index_id`=`idx`.`index_id` AND `iil`.`certify_state`=2 + ) AS `num_items` + FROM `${prefix}_xoonips_index` AS `idx` + INNER JOIN `${prefix}_xoonips_item_title` AS `it` ON `idx`.`index_id`=`it`.`item_id` + WHERE `it`.`title_id`=0 + AND `idx`.`open_level`=1 +SQL; + +$limitItems = array(); +$limitFiles = array(); + +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +$tree = array(); +$root = array(); +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + $tree[$row['index_id']] = $row; + $root[$row['parent_index_id']][$row['sort_number']] = $row['index_id']; +} +$xoopsDB->freeRecordSet($res); +foreach ($root as &$node) { + ksort($node); +} +unset($node); + +$data[] = getTreeNode($tree, $root, 3); +MyDumpTool::saveJson('src/database/assets/tree.json', $data); +unset($data, $root); + +// get simpf link data +$simpflink = parseSimPFLinkFile(); +$simpfurls = []; + +// get public items +$sql = <<< SQL +SELECT + `ib`.*, + GROUP_CONCAT(DISTINCT `it`.`title` ORDER BY `it`.`title_id` ASC SEPARATOR '\n') AS `title`, + `ity`.`display_name` AS `item_type_display_name`, `ity`.`name` AS `item_type_name`, + `u`.`uname`, `u`.`name`, `u`.`email` + FROM `${prefix}_xoonips_item_basic` AS `ib` + INNER JOIN `${prefix}_xoonips_item_title` AS `it` ON `ib`.`item_id`=`it`.`item_id` + INNER JOIN `${prefix}_xoonips_item_type` AS `ity` ON `ib`.`item_type_id`=`ity`.`item_type_id` + INNER JOIN `${prefix}_xoonips_index_item_link` AS `iil` ON `ib`.`item_id`=`iil`.`item_id` + INNER JOIN `${prefix}_xoonips_index` AS `idx` ON `iil`.`index_id`=`idx`.`index_id` + LEFT JOIN `${prefix}_users` AS `u` ON `ib`.`uid`=`u`.`uid` + WHERE `ity`.`display_name` != 'Index' + AND `iil`.`certify_state`=2 + AND `idx`.`open_level`=1 + GROUP BY `ib`.`item_id` + ORDER BY `ib`.`item_id` ASC +SQL; + +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +$items = array(); +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('item_id', 'item_type_id', 'uid', 'last_update_date', 'creation_date', 'publication_year', 'publication_month', 'publication_mday')); + $row['index'] = getIndexes($tree, $row['item_id']); + if (0 === count($row['index'])) { + // no public indexes found. + continue; + } + $row['changelog'] = getChangeLogs($row['item_id']); + $row['related_to'] = getRelatedTo($row['item_id']); + $row['keyword'] = getKeyword($row['item_id']); + $row['file'] = getFile($row['item_id']); + switch ($row['item_type_name']) { + case 'xnpbinder': + appendBinderInfo($row); + break; + case 'xnpbook': + appendBookInfo($row); + break; + case 'xnpconference': + appendConferenceInfo($row); + break; + case 'xnpdata': + appendDataInfo($row); + break; + case 'xnpfiles': + appendFilesInfo($row); + break; + case 'xnpmemo': + appendMemoInfo($row); + break; + case 'xnpmodel': + appendModelInfo($row); + break; + case 'xnppaper': + appendPaperInfo($row); + break; + case 'xnppresentation': + appendPresentationInfo($row); + break; + case 'xnpsimulator': + appendSimulatorInfo($row); + break; + case 'xnpstimulus': + appendStimulusInfo($row); + break; + case 'xnptool': + appendToolInfo($row); + break; + case 'xnpurl': + appendUrlInfo($row); + break; + case 'xnpnimgcenter': + appendNimgcenterInfo($row); + break; + default: + exit('Unsupported item type: '.$row['item_type_name']); + } + if (isset($row['attachment_dl_limit']) && $row['attachment_dl_limit']) { + $found = false; + foreach ($row['file'] as $file) { + if ('preview' !== $file['file_type_name']) { + $limitFiles[] = $file['file_id']; + $found = true; + } + } + if ($found) { + $limitItems[] = array( + 'uname' => $row['uname'], + 'name' => $row['name'], + 'email' => $row['email'], + 'item_id' => $row['item_id'], + 'doi' => $row['doi'], + ); + } + } + MyDumpTool::dropColumn($row, ['email', 'item_type_id']); + if (isset($row['rights']) && isset($row['use_cc']) && isset($row['cc_commercial_use']) && isset($row['cc_modification']) && 1 == $row['use_cc']) { + $label = 'Creative Commons Attribution'; + if (0 == $row['cc_commercial_use']) { + $label .= '-NonCommercial'; + } + switch ($row['cc_modification']) { + case 0: + $label .= '-NoDerivatives'; + break; + case 1: + $label .= '-ShareAlike'; + break; + } + $label .= ' 4.0 International License.'; + $row['rights'] = $label; + } + $items[] = $row; + + $simpfurl = ''; + if ('' != $row['doi'] && isset($simpflink['id'][$row['doi']])) { + $simpfurl = $simpflink['id'][$row['doi']]; + } elseif (isset($simpflink['item_id'][$row['item_id']])) { + $simpfurl = $simpflink['item_id'][$row['item_id']]; + } + if ('' !== $simpfurl) { + $simpfurls[] = [ + 'id' => $row['item_id'], + 'url' => $simpfurl, + ]; + } +} +$xoopsDB->freeRecordSet($res); +MyDumpTool::saveJson('public/database/items.json', $items); +if (!empty($simpfurls)) { + MyDumpTool::saveJson('src/database/assets/simpf-links.json', $simpfurls); +} + +$fp = fopen(MYDUMPTOOL_OUTPUTDIR.'/dl-limit-items.csv', 'w'); +foreach ($limitItems as $row) { + $data = array( + $row['item_id'], + $row['uname'], + $row['name'], + $row['email'], + getItemUrl($row), + ); + fputcsv($fp, $data); +} +fclose($fp); + +// get files +$xconfig_handler = xoonips_getormhandler('xoonips', 'config'); +$fileutil = xoonips_getutility('file'); + +$basePath = $xconfig_handler->getValue('upload_dir'); +$sql = <<< SQL +SELECT + `f`.`file_id`, `f`.`item_id`, `f`.`original_file_name`, + `ft`.`name` AS `file_type_name` + FROM `${prefix}_xoonips_file` AS `f` + INNER JOIN `${prefix}_xoonips_file_type` AS `ft` ON `f`.`file_type_id`=`ft`.`file_type_id` + INNER JOIN `${prefix}_xoonips_index_item_link` AS `iil` ON `f`.`item_id`=`iil`.`item_id` + INNER JOIN `${prefix}_xoonips_index` AS `idx` ON `iil`.`index_id`=`idx`.`index_id` + WHERE `f`.`is_deleted`=0 + AND `ft`.`name` NOT IN('readme' , 'license', 'rights') + AND `iil`.`certify_state`=2 + AND `idx`.`open_level`=1 + GROUP BY `f`.`file_id` + ORDER BY `f`.`file_id` ASC +SQL; + +if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); +} +$filesDir = MYDUMPTOOL_OUTPUTDIR.'/public/database/file'; +while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('file_id', 'item_id')); + $file_id = $row['file_id']; + $item_id = $row['item_id']; + $file_name = $row['original_file_name']; + $file_type = $row['file_type_name']; + if (in_array($file_id, $limitFiles)) { + echo "download limit file found.. skip to copy.. item_id:$item_id, file_id:$file_id".PHP_EOL; + continue; + } + $file_dir = $filesDir.'/'.$file_id; + $src_file = $basePath.'/'.$file_id; + if (!is_dir($file_dir)) { + @mkdir($file_dir); + } + //if (!file_exists($file_dir.'/'.$file_name)) { + if (!MyDumpTool::fileCopy($src_file, $file_dir.'/'.$file_name)) { + echo 'failed to copy file: '.$basePath.'/'.$file_id.PHP_EOL; + } + $htaccess = $file_dir.'/.htaccess'; + $xfilename = str_replace(' ', '\\ ', $file_name); + $data = "RewriteEngine On\nRewriteBase /database/file/$file_id\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteRule .* $xfilename [R=301,L]\n"; + file_put_contents($htaccess, $data); + //} + if ('preview' == $file_type) { + $thumbnail_file = $file_dir.'.png'; + if (!file_exists($thumbnail_file)) { + $mimetype = $fileutil->get_mimetype($src_file, $file_name); + $thumbnail = $fileutil->get_thumbnail($src_file, $mimetype); + if (null !== $thumbnail) { + file_put_contents($thumbnail_file, $thumbnail); + } else { + createThumbnail($src_file, $mimetype, $thumbnail_file); + } + } + } +} +$xoopsDB->freeRecordSet($res); + +// functions + +function getItemUrl($row) +{ + $url = XOONIPS_URL.'/detail.php?'; + if ('' != $row['doi']) { + $url .= XNP_CONFIG_DOI_FIELD_PARAM_NAME.'='.$row['doi']; + } else { + $url .= 'item_id='.$row['item_id']; + } + + return $url; +} + +function getTreeNode($tree, $root, $index_id) +{ + $children = array(); + if (isset($root[$index_id])) { + foreach ($root[$index_id] as $child_index_id) { + $children[] = getTreeNode($tree, $root, $child_index_id); + } + } + + return array( + 'id' => (int) $tree[$index_id]['index_id'], + 'title' => $tree[$index_id]['title'], + 'num_of_items' => (int) $tree[$index_id]['num_items'], + 'children' => $children, + ); +} + +function getIndexes($tree, $item_id) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $sql = <<< SQL +SELECT + `iil`.`index_id` + FROM `${prefix}_xoonips_index_item_link` AS `iil` + WHERE `iil`.`item_id`=$item_id + ORDER BY `iil`.`index_id` +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $indexes = array(); + while ($row = $xoopsDB->fetchArray($res)) { + $index_id = $row['index_id']; + if (isset($tree[$index_id])) { + $idxes = array(); + $idxes[] = $tree[$index_id]['title']; + $parent_id = $tree[$index_id]['parent_index_id']; + while (1 != $parent_id) { + $idxes[] = $tree[$parent_id]['title']; + $parent_id = $tree[$parent_id]['parent_index_id']; + } + $idxes[] = ''; + $indexes[] = array( + 'index_id' => (int) $index_id, + 'title' => trim(implode(' / ', array_reverse($idxes))), + ); + } + } + $xoopsDB->freeRecordSet($res); + + return $indexes; +} + +function getChangeLogs($item_id) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $sql = <<< SQL +SELECT `log_date`, `log` + FROM `${prefix}_xoonips_changelog` + WHERE `item_id`=$item_id + ORDER BY `log_date` DESC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $ret = array(); + while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('log_date')); + $ret[] = $row; + } + $xoopsDB->freeRecordSet($res); + + return $ret; +} + +function getRelatedTo($item_id) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $sql = <<< SQL +SELECT `item_id` + FROM `${prefix}_xoonips_related_to` + WHERE `parent_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $ret = array(); + while ($row = $xoopsDB->fetchArray($res)) { + $ret[] = (int) $row['item_id']; + } + $xoopsDB->freeRecordSet($res); + + return $ret; +} + +function getKeyword($item_id) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xoonips_item_keyword` + WHERE `item_id`=$item_id + ORDER BY `keyword_id` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $ret = array(); + while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + $ret[] = $row['keyword']; + } + $xoopsDB->freeRecordSet($res); + + return $ret; +} + +function getFile($item_id) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $sql = <<< SQL +SELECT `f`.`file_id`, `f`.`original_file_name`, `f`.`mime_type`, `f`.`file_size`, `f`.`caption`, `f`.`timestamp`, + `ft`.`name` AS `file_type_name`, `ft`.`display_name` AS `file_type_display_name` + FROM `${prefix}_xoonips_file` AS `f` + INNER JOIN `${prefix}_xoonips_file_type` AS `ft` ON `f`.`file_type_id`=`ft`.`file_type_id` + WHERE `item_id`=$item_id + AND `is_deleted`=0 + ORDER BY `ft`.`name` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $ret = array(); + while ($row = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row); + MyDumpTool::convertToInt($row, array('file_id', 'file_size')); + $ret[] = $row; + } + $xoopsDB->freeRecordSet($res); + + return $ret; +} + +function appendBinderInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpbinder_item_detail` + WHERE `binder_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('binder_id')); + MyDumpTool::dropColumn($detail, ['binder_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpbinder_binder_item_link` + WHERE `binder_id`=$item_id + ORDER BY `item_id` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['item_link'] = array(); + while ($row2 = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($row2); + $row['item_link'][] = (int) $row2['item_id']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendBookInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpbook_item_detail` + WHERE `book_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('book_id', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::convertToInt($detail, array('volume', 'number')); // for CBSN + MyDumpTool::dropColumn($detail, ['book_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpbook_author` + WHERE `book_id`=$item_id + ORDER BY `author_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['author'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['author'][] = $author['author']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendConferenceInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpconference_item_detail` + WHERE `conference_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('conference_id', 'conference_from_year', 'conference_from_month', 'conference_from_mday', 'conference_to_year', 'conference_to_month', 'conference_to_mday', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['conference_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpconference_author` + WHERE `conference_id`=$item_id + ORDER BY `author_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['author'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['author'][] = $author['author']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendDataInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpdata_item_detail` + WHERE `data_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('data_id', 'use_cc', 'cc_commercial_use', 'cc_modification', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['data_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpdata_experimenter` + WHERE `data_id`=$item_id + ORDER BY `experimenter_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['experimenter'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['experimenter'][] = $author['experimenter']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendFilesInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpfiles_item_detail` + WHERE `files_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('files_id')); + MyDumpTool::dropColumn($detail, ['files_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); +} + +function appendMemoInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpmemo_item_detail` + WHERE `memo_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('memo_id')); + MyDumpTool::dropColumn($detail, ['memo_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); +} + +function appendModelInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpmodel_item_detail` + WHERE `model_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('model_id', 'use_cc', 'cc_commercial_use', 'cc_modification', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['model_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpmodel_creator` + WHERE `model_id`=$item_id + ORDER BY `creator_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['creator'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['creator'][] = $author['creator']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendPaperInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnppaper_item_detail` + WHERE `paper_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('paper_id', 'volume', 'number')); + MyDumpTool::dropColumn($detail, ['paper_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnppaper_author` + WHERE `paper_id`=$item_id + ORDER BY `author_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['author'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['author'][] = $author['author']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendPresentationInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnppresentation_item_detail` + WHERE `presentation_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('presentation_id', 'use_cc', 'cc_commercial_use', 'cc_modification', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['presentation_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnppresentation_creator` + WHERE `presentation_id`=$item_id + ORDER BY `creator_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['creator'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['creator'][] = $author['creator']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendSimulatorInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpsimulator_item_detail` + WHERE `simulator_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('simulator_id', 'use_cc', 'cc_commercial_use', 'cc_modification', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['simulator_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpsimulator_developer` + WHERE `simulator_id`=$item_id + ORDER BY `developer_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['developer'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['developer'][] = $author['developer']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendStimulusInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpstimulus_item_detail` + WHERE `stimulus_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('stimulus_id', 'use_cc', 'cc_commercial_use', 'cc_modification', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['stimulus_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpstimulus_developer` + WHERE `stimulus_id`=$item_id + ORDER BY `developer_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['developer'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['developer'][] = $author['developer']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendToolInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnptool_item_detail` + WHERE `tool_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('tool_id', 'use_cc', 'cc_commercial_use', 'cc_modification', 'attachment_dl_limit', 'attachment_dl_notify')); + MyDumpTool::dropColumn($detail, ['tool_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnptool_developer` + WHERE `tool_id`=$item_id + ORDER BY `developer_order` ASC +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['developer'] = array(); + while ($author = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($author); + $row['developer'][] = $author['developer']; + } + $xoopsDB->freeRecordSet($res); +} + +function appendUrlInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpurl_item_detail` + WHERE `url_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + MyDumpTool::convertToInt($detail, array('url_id', 'url_count')); + MyDumpTool::dropColumn($detail, ['url_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); +} + +function appendNimgcenterInfo(&$row) +{ + global $xoopsDB; + $prefix = $xoopsDB->prefix(); + $item_id = $row['item_id']; + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpnimgcenter_item_detail` + WHERE `nimgcenter_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + while ($detail = $xoopsDB->fetchArray($res)) { + MyDumpTool::decode($detail); + $detail['coord_type_name'] = (0 === $detail['coord_type']) ? 'Talairach' : 'MNI'; + MyDumpTool::dropColumn($detail, ['nimgcenter_id']); + $row += $detail; + } + $xoopsDB->freeRecordSet($res); + $sql = <<< SQL +SELECT * + FROM `${prefix}_xnpnimgcenter_talairach_list` + WHERE `nimgcenter_id`=$item_id +SQL; + if (!($res = $xoopsDB->query($sql))) { + var_dump($xoopsDB); + exit(); + } + $row['coordinate'] = array(); + while ($t = $xoopsDB->fetchArray($res)) { + $row['coordinate'][] = $t; + } + $xoopsDB->freeRecordSet($res); +} + +function createThumbnail($inputFile, $mime_type, $outputFile) +{ + $finfo = finfo_open(FILEINFO_NONE); + $label = finfo_file($finfo, $inputFile); + finfo_close($finfo); + if (preg_match('/^([^\\/]*)\\/(.*)$/', $mime_type, $matches)) { + if ('audio' == $matches[1]) { + $img_type = 'audio'; + } elseif ('image' == $matches[1]) { + $img_type = 'image'; + } elseif ('video' == $matches[1]) { + $img_type = 'video'; + } elseif ('text' == $matches[1]) { + $img_type = 'text'; + } elseif ('application' == $matches[1]) { + $text_types = array('pdf', 'xml', 'msword', 'vnd.ms-excel'); + $image_types = array('vnd.ms-powerpoint', 'postscript'); + $audio_types = array('vnd.rn-realmedia'); + if (in_array($matches[2], $text_types)) { + $img_type = 'text'; + } elseif (in_array($matches[2], $audio_types)) { + $img_type = 'audio'; + } elseif (in_array($matches[2], $image_types)) { + $img_type = 'image'; + } else { + $img_type = 'application'; + } + } else { + $img_type = 'unknown'; + } + } else { + $img_type = 'unknown'; + } + $img_file = XOOPS_ROOT_PATH.'/modules/xoonips/images/thumbnail_'.$img_type.'.png'; + // create image resource + $w = 100; + $h = 100; + $im = imagecreatetruecolor($w, $h); + // label setting + $f = 2; + // font number + $lp = 5; + // label padding + $fw = imagefontwidth($f); + // font width + $fh = imagefontheight($f); + // font height + $fmaxlen = ($w - $lp * 2) / $fw; + // max label length + $labels = explode(',', $label); + $label = $labels[0]; + $llen = strlen($label); + if ($llen > $fmaxlen) { + $label = substr($label, 0, $fmaxlen - 3); + $label .= '...'; + $llen = strlen($label); + } + $lx = ($w - $llen * $fw) / 2; + $ly = $h - $fh - $lp; + // change alpha attributes and create transparent color + imageantialias($im, true); + imagealphablending($im, false); + imagesavealpha($im, true); + $transparent = imagecolorallocatealpha($im, 255, 255, 255, 0); + $col_white = imagecolorallocate($im, 255, 255, 255); + $col_gray = imagecolorallocate($im, 127, 127, 127); + $col_black = imagecolorallocate($im, 0, 0, 0); + // fill all area with transparent color + imagefill($im, 0, 0, $col_white); + imagealphablending($im, true); + $imicon = imagecreatefrompng($img_file); + imagecopy($im, $imicon, $w / 2 - 48 / 2, $h / 2 - 48 / 2, 0, 0, 48, 48); + imagepolygon($im, array(0, 0, $w - 1, 0, $w - 1, $h - 1, 0, $h - 1), 4, $col_gray); + if (0 != strlen($label)) { + imagestring($im, $f, $lx, $ly, $label, $col_black); + } + imagepng($im, $outputFile); + imagedestroy($imicon); + imagedestroy($im); + + return true; +} + +function parseSimPFLinkFile() +{ + global $XOONIPS_SIMPF_LINKFILE; + $xoops_url_path = parse_url(XOOPS_URL, PHP_URL_PATH); + $ret = []; + if (isset($XOONIPS_SIMPF_LINKFILE) && file_exists($XOONIPS_SIMPF_LINKFILE)) { + $lines = file($XOONIPS_SIMPF_LINKFILE); + foreach ($lines as $line) { + list($pfname, $pfurl, $simpfurl) = explode(',', $line); + if (preg_match('/^'.preg_quote(XOOPS_URL, '/').'/', $pfurl)) { + $pUrl = parse_url($pfurl); + if ($pUrl['path'] != $xoops_url_path.'/modules/xoonips/detail.php') { + echo 'not xoonips url found in simpf link file. URL:'.$pfurl.PHP_EOL; + continue; + } + if (preg_match('/(?:^|&)(id|item_id)=([^$&]+)/', $pUrl['query'], $matches)) { + $key = $matches[1]; + $value = $matches[2]; + $ret[$key][$value] = trim($simpfurl); + } + } + } + } + + return $ret; +} diff --git a/etc/fixMediaWikiDumpData.php b/etc/fixMediaWikiDumpData.php new file mode 100644 index 0000000..030eb21 --- /dev/null +++ b/etc/fixMediaWikiDumpData.php @@ -0,0 +1,180 @@ + $data['title'], + 'text' => $text, + ]; + file_put_contents(__DIR__.'/data/public/mediawiki/contents/'.$content['id'].'.json', json_encode($data2, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); +} + +class MyUtil +{ + public static function fixHtml($text, $revid) + { + $text = preg_replace('/
    .+<\/div>/Us', '', $text); + $text = preg_replace_callback('/(.+)<\/a>/Us', function ($m) { + $fpath = MyUtil::getImagePath('/mediawiki/images', $m[1]); + + return ''.$m[2].''; + }, $text); + $text = preg_replace_callback('/(?:[^/Us', function ($m) { + return ''.$m[3].''; + }, $text); + $text = preg_replace_callback('/(?:[^/Us', function ($m) { + $bpath = 'thumb/'.$m[1]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$bpath); + $bpath .= '/'.$m[2]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$bpath); + $bpath_ = $bpath.'/'.$m[3]; + $bpath .= '/'.urldecode($m[3]); + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$bpath); + $fpath_ = $bpath_.'/'.$m[4]; + $fpath = $bpath.'/'.urldecode($m[4]); + MyUtil::fileCopy(IMAGE_DIR.'/'.$fpath, DEST_IMAGE_DIR.'/'.$fpath); + $srcset = []; + foreach (explode(', ', $m[7]) as $src) { + if (preg_match('/^https?:\/\/dynamicbrain\.neuroinf\.jp\/uploads\/mediawiki\/thumb\/(.)\/(..)\/([^\/]+)\/([^ ]+) (.+)$/Us', trim($src), $sm)) { + $sfpath_ = $bpath_.'/'.$sm[4]; + $sfpath = $bpath.'/'.urldecode($sm[4]); + MyUtil::fileCopy(IMAGE_DIR.'/'.$sfpath, DEST_IMAGE_DIR.'/'.$sfpath); + $srcset[] = '/mediawiki/images/'.$sfpath_.' '.$sm[5]; + } + } + + return ''.$m[3].''; + }, $text); + $text = preg_replace_callback('/(.+)<\/a>/Us', function ($m) { + parse_str(htmlspecialchars_decode($m[2], ENT_QUOTES), $params); + $url = ''; + switch ($m[1]) { + case 'detail.php': + if (isset($params['item_id'])) { + $url = 'item/'.$params['item_id']; + } elseif (isset($params['id'])) { + $url = 'item/id/'.$params['id']; + } else { + var_dump($m); + exit('Unexpected parameter found..'); + } + break; + case 'itemselect.php': + if (!isset($params['op'])) { + var_dump($m); + exit('Unexpected url found..'); + break; + } + switch ($params['op']) { + case 'quicksearch': + if (!isset($params['keyword'])) { + var_dump($m); + exit('Unexpected url found.. parameter keyword not found'); + break; + } + if (!isset($params['search_itemtype'])) { + var_dump($m); + exit('Unexpected url found.. parameter search_itemtype not found'); + break; + } + $url = 'search?keyword='.$params['keyword'].'&type='.preg_replace('/^xnp/', '', $params['search_itemtype']); + break; + default: + var_dump($m); + exit('not impremented yet..'); + break; + } + break; + default: + var_dump($m); + exit('not impremented yet..'); + break; + } + + return ''.$m[3].''; + }, $text); + $text = preg_replace_callback('//Us', function ($m) { + $fpath = 'math/'.$m[1]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$fpath); + $fpath .= '/'.$m[2]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$fpath); + $fpath .= '/'.$m[3]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$fpath); + $fpath .= '/'.$m[4]; + MyUtil::fileCopy(IMAGE_DIR.'/'.$fpath, DEST_IMAGE_DIR.'/'.$fpath); + + return ''.$m[4].''; + }, $text); + $text = preg_replace('/

    \s*(.*)\s*<\/p>/Us', '

    \1

    ', $text); + $text = preg_replace_callback('/href="(?:https?:\/\/dynamicbrain\.neuroinf\.jp)?\/modules\/mediawiki\/(?:index.php\/)?([^"]+)"/Us', function ($m) { + return 'href="/mediawiki/'.urlencode(str_replace(' ', '_', $m[1])).'"'; + }, $text); + $text = preg_replace_callback('//Us', function ($m) { + $fpath = '/'.$m[1]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$fpath); + $fpath .= '/'.$m[2]; + MyUtil::makedir(DEST_IMAGE_DIR.'/'.$fpath); + $fpath_ = $fpath.'/'.$m[3]; + $fpath .= '/'.urldecode($m[3]); + MyUtil::fileCopy(IMAGE_DIR.'/'.$fpath, DEST_IMAGE_DIR.'/'.$fpath); + + return ''; + }, $text); + $text = preg_replace('/(.+)<\/a>/Us', '\1', $text); + $text = preg_replace('/href="https?:\/\/dynamicbrain\.neuroinf\.jp\/hetero/Us', 'href="/hetero', $text); + $text = preg_replace('/href="https?:\/\/dynamicbrain\.neuroinf\.jp\/modules\/hackathon\//Us', 'href="/hackathon/', $text); + $text = preg_replace('/href="https?:\/\/dynamicbrain\.neuroinf\.jp\/conferences\//Us', 'href="/conferences/', $text); + $text = preg_replace('/href="https?:\/\/dynamicbrain\.neuroinf\.jp\/modules\/documents\/(.*)"/Us', 'href="/documents/\1"', $text); + $text = preg_replace('/https?:\/\/dynamicbrain\.neuroinf\.jp\/modules\/hackathon\//Us', 'https://dynamicbrain.neuroinf.jp/hackathon/', $text); + $text = preg_replace('/]*)>(\s)*]*)>/Us', '\2', $text); + $text = preg_replace('/<\/tr>(\s*)<\/table>/s', '\1', $text); + $text = trim($text); + if (preg_match('/https?:\/\/dynamicbrain\.neuroinf\.jp/', $text)) { + $okids = [2614]; + if (!in_array($revid, $okids)) { + echo $text.PHP_EOL; + die('dynamicbrain internal url link still found: '.$revid.PHP_EOL); + } + } + + return $text; + } + + public static function makedir($path) + { + if (is_dir($path)) { + return true; + } + if (false === @mkdir($path)) { + exit('Failed to create directroy: '.$path.PHP_EOL); + } + + return true; + } + + public static function getImagePath($basedir, $fname) + { + $hash = md5($fname); + + return $basedir.'/'.substr($hash, 0, 1).'/'.substr($hash, 0, 2).'/'.$fname; + } + + public static function fileCopy($from, $to) + { + system('rsync -aq '.escapeshellarg($from).' '.escapeshellarg($to), $ret); + if (0 !== $ret) { + exit('Failed to copy file: '.$from.' -> '.$to.PHP_EOL); + } + + return 0 === $ret; + } +} diff --git a/etc/simpflink.csv b/etc/simpflink.csv new file mode 100644 index 0000000..86cd994 --- /dev/null +++ b/etc/simpflink.csv @@ -0,0 +1,465 @@ +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=6045,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=25 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=909,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=27 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=1648,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=28 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=913,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=29 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=1623,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=30 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=1620,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=32 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=896,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=33 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=2434,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=34 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=2441,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=35 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=5307,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=37 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?id=943,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=38 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=403,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=39 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=398,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=40 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=350,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=41 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=366,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=43 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=370,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=44 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=361,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=45 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=4449054b,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=46 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=6110,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=47 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=7252867b,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=48 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=6105,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=49 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=2861,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=50 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=16625198b,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=51 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=6422,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=52 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=19281836b,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=53 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=7941380b,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=54 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=6448,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=55 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=6106,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=56 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1027,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=57 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1030,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=58 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1031,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=59 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1033,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=61 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1034,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=62 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1035,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=63 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1036,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=64 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1037,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=65 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1038,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=66 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1041,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=67 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1042,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=68 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1043,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=69 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1044,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=70 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1045,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=71 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1046,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=72 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1047,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=73 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1048,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=74 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1051,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=76 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1052,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=77 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1054,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=78 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1056,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=79 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1057,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=80 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1059,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=81 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1060,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=82 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1061,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=83 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1062,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=84 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1064,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=85 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1065,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=86 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1066,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=87 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1067,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=114 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1068,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=116 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1069,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=117 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1071,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=119 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1073,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=121 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1076,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=124 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1077,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=125 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1078,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=126 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1079,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=127 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=296,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=128 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=5586,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=129 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=297,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=130 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1080,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=131 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1081,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=132 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1082,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=133 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1084,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=134 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1085,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=135 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1086,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=136 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1087,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=137 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1088,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=138 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1089,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=139 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1098,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=140 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1099,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=141 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1100,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=142 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1101,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=143 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1102,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=144 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1103,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=145 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1105,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=146 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1106,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=147 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1107,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=148 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1108,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=149 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1109,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=150 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1110,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=151 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1111,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=152 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1112,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=153 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1113,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=154 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1114,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=155 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1115,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=156 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1119,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=159 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1120,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=160 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1121,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=161 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1122,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=162 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1123,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=163 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1124,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=164 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1125,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=165 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1127,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=167 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1128,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=168 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1129,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=169 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1130,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=170 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1131,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=171 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1132,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=172 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1134,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=174 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1135,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=175 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1136,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=176 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1137,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=177 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1138,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=178 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1139,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=179 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1140,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=180 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1141,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=181 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1142,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=182 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1143,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=183 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1144,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=184 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1146,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=186 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1147,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=187 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1148,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=188 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1149,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=189 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1150,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=190 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1152,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=192 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1153,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=193 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1154,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=194 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1156,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=195 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1157,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=196 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1159,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=198 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1160,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=199 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1161,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=200 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1162,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=201 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1163,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=202 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1164,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=203 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1165,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=204 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1166,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=205 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1167,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=206 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1168,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=207 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1169,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=208 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1170,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=209 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1171,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=210 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1173,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=212 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1174,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=213 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1175,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=214 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1176,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=215 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1177,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=216 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1178,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=217 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1179,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=218 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1180,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=219 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1181,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=220 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1182,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=221 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1183,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=222 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1184,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=223 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1185,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=224 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1186,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=225 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1187,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=226 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1188,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=227 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1189,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=228 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1190,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=229 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1191,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=230 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1192,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=231 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1193,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=232 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=15929656d,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=233 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=376,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=234 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=298,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=235 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=1629,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=236 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=1647,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=237 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1209,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=239 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1210,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=240 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1211,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=241 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1212,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=242 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1213,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=243 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1214,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=244 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1215,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=245 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1216,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=246 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1218,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=248 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1219,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=249 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1220,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=250 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1222,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=251 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1223,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=252 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1224,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=253 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1225,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=254 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1226,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=255 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1227,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=256 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1228,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=257 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1230,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=258 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1231,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=259 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1232,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=260 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1233,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=261 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1234,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=262 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1235,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=263 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1236,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=264 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1237,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=265 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1238,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=266 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1239,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=267 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1240,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=268 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1241,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=269 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1242,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=270 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1243,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=271 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1244,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=272 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1245,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=273 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1246,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=274 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1247,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=275 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1248,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=276 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1251,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=279 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1252,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=280 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1255,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=281 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1256,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=282 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1257,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=283 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1258,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=284 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1262,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=286 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1263,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=287 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1264,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=288 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1265,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=289 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1266,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=290 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1268,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=292 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1269,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=293 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1270,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=294 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1271,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=295 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1272,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=296 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1273,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=297 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1278,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=302 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1279,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=303 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1280,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=304 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1281,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=305 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1282,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=306 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1283,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=307 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1284,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=308 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1285,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=309 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1286,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=310 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1287,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=311 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1288,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=312 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1289,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=313 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1291,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=315 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1292,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=316 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1293,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=317 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1294,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=318 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1295,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=319 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1296,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=320 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1298,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=322 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1299,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=323 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1300,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=324 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1302,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=326 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1306,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=330 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1312,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=336 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1313,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=337 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1314,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=338 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1315,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=339 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=162,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=341 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=5936,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=342 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/558/weaverWearne06.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=360 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?id=4449054c,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=367 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1039,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=416 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1040,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=417 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=7051,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=444 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1427,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=485 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1425,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=486 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1424,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=487 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1423,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=488 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1422,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=489 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1421,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=490 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1420,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=491 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1419,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=492 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1418,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=493 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1417,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=494 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1416,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=496 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1415,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=497 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1362,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=498 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1414,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=499 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1363,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=500 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1413,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=501 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1411,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=502 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1409,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=503 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1365,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=504 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1369,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=505 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1408,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=506 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1406,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=507 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1362,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=511 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1364,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=514 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1367,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=515 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1366,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=516 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1405,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=517 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1364,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=518 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1401,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=519 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1415,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=520 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1368,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=521 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1399,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=523 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1370,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=524 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1398,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=525 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1371,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=526 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1397,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=527 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1396,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=528 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1372,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=529 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1373,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=530 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1374,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=531 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1375,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=532 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1376,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=533 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1380,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=534 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1395,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=535 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1394,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=536 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1393,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=537 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1392,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=538 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1391,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=539 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1390,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=540 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1389,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=541 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1387,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=542 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1386,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=543 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1385,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=544 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1384,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=545 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1382,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=546 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1381,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=547 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1362,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=550 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1363,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=551 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1364,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=552 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1365,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=553 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1366,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=554 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1367,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=555 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1368,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=556 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1369,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=557 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1370,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=558 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1371,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=559 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1372,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=560 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1374,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=562 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1375,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=563 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1376,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=564 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1379,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=565 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1380,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=566 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1381,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=567 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1382,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=568 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1384,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=569 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1385,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=571 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1386,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=572 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1387,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=573 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1045,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=574 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1389,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=575 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1390,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=576 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1391,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=577 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1392,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=578 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1393,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=579 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1394,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=580 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1395,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=581 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1396,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=582 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1397,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=583 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1398,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=584 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1399,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=585 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1400,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=586 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1401,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=587 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1402,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=588 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1405,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=589 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1409,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=590 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1409,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=591 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1411,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=592 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1413,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=593 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1414,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=594 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1415,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=595 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1416,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=596 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1418,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=598 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1419,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=599 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1420,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=600 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1421,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=601 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1422,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=602 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1423,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=603 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1424,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=604 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1425,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=605 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1427,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=606 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1428,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=607 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1429,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=608 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1430,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=609 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1431,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=610 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1432,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=611 +visiome,https://visiome.neuroinf.jp/modules/xoonips/detail.php?item_id=7252,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=612 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1434,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=613 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1435,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=614 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1450,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=615 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1452,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=616 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1453,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=617 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1454,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=618 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1455,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=619 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1458,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=620 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1460,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=621 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1461,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=622 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1462,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=623 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1463,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=624 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1466,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=625 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1465,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=626 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1467,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=627 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1470,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=628 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1471,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=629 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1472,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=630 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1473,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=631 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1474,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=632 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1476,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=633 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1477,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=634 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1479,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=635 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1481,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=636 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1482,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=637 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1483,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=638 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1486,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=639 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1487,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=640 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1488,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=641 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1489,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=642 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1490,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=643 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1493,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=644 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1496,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=645 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1497,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=646 +cerebellum,https://cerebellum.neuroinf.jp/modules/xoonips/detail.php?item_id=1498,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=647 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/533/SundtEtAl2015.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=656 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/536/baker_etal_JCNS_2010.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=657 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/538/CS56PyModelDB.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=659 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/539/TCconvergenceModel.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=660 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/540/BahlEtAl2012.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=661 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/541/ACh_ModelDB.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=662 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/543/OLMmodel_r3.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=664 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/548/GentilettiEtAl2016.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=668 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/556/FUS_model.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=677 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/560/ShepherdBrayton1979.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=680 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/561/gc-1.1_r2.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=681 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/564/VladimirovTuTraub2012.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=683 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/565/xiaoshenli.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=684 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/566/kv72-R213QW-mutations_r2.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=685 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/567/Ih_current.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=686 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/569/Schizophr.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=687 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/570/SaudargieneEtAl2015.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=688 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/571/bpap.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=689 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/572/magical7.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=691 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/575/HyunEtAl2015.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=696 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/576/MasurkarChen2011_r1.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=697 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/577/Nakano_FICN_model_r1.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=698 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/582/AshhadNarayanan2013.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=699 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/583/DiFrancescoNoble1985.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=700 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/584/DGC.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=701 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/586/DG_BC.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=703 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/587/DRG_Devor.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=704 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/588/Kv72_ModelDB.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=705 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/589/SousaEtAl2014.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=706 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/590/MiglioreEtAl2015.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=707 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/592/Chloride_Model.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=708 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/593/MiglioreEJN2016_r2.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=709 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/595/Moore2015.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=711 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/597/FFI_CA1_r3.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=713 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/598/stadler2014_layerV_r1.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=714 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/600/2VN.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=716 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/602/Branch_Point_Tapering.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=718 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/604/MenonEtAl2009_r1.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=720 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/606/CA3Atrophy.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=722 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/607/Gorin_et_al_2016.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=723 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/608/Poleg-PolskyDiamond2011.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=724 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/613/Demo.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=728 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/614/ShortEtAl2016.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=729 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/618/Casaleggio2014.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=733 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/623/MiglioreMcTavish2013.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=736 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/624/KimEtAl2017.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=737 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/626/fig1b.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=738 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/627/cortex_r1.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=739 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/629/oltedal.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=741 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/632/ka_rgc.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=744 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/634/na_rgc.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=745 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/636/V1_PFC_ModelDB.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=747 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/640/moore83.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=751 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/642/SpaceClampDemo.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=753 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/644/anderson.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=755 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/645/VNO.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=756 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/645/VNO.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=757 +cns,https://cns.neuroinf.jp/modules/fmanager/index.php/view/647/Watanabe-et-al_2017_r1.zip,http://sim.neuroinf.jp/modules/xoonips/detail.php?item_id=758 diff --git a/package.json b/package.json index 2f245d3..5871a9a 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,41 @@ { "name": "dynamicbrain", - "version": "0.1.0", + "version": "1.0.0", "private": true, "dependencies": { - "@types/jest": "24.0.17", + "@types/async-lock": "^1.1.1", + "@types/jest": "24.0.18", + "@types/lokijs": "^1.5.2", "@types/node": "12.7.2", "@types/react": "16.9.2", - "@types/react-dom": "16.8.5", + "@types/react-dom": "16.9.0", + "@types/react-helmet": "^5.0.9", + "@types/react-html-parser": "^2.0.1", + "@types/react-overlays": "^1.1.3", + "@types/react-router-dom": "^4.3.5", + "@types/react-router-hash-link": "^1.2.1", + "@types/xregexp": "^3.0.30", + "async-lock": "^1.2.2", + "axios": "^0.19.0", + "lokijs": "^1.5.7", + "moment": "^2.24.0", + "rc-tree": "^3.0.0-alpha.15", "react": "^16.9.0", + "react-app-polyfill": "^1.0.2", + "react-cookie": "^4.0.1", "react-dom": "^16.9.0", + "react-ga": "^2.6.0", + "react-helmet": "^5.2.1", + "react-html-parser": "^2.0.2", + "react-image-lightbox": "^5.1.0", + "react-overlays": "^1.2.0", + "react-router-dom": "^5.0.1", + "react-router-hash-link": "^1.2.2", "react-scripts": "3.1.1", - "typescript": "3.5.3" + "react-spinner-material": "^1.1.3", + "react-twitter-widgets": "^1.7.1", + "typescript": "3.5.3", + "xregexp": "^4.2.4" }, "scripts": { "start": "react-scripts start", @@ -25,12 +50,17 @@ "production": [ ">0.2%", "not dead", - "not op_mini all" + "not op_mini all", + "ie 11" ], "development": [ "last 1 chrome version", "last 1 firefox version", - "last 1 safari version" + "last 1 safari version", + "ie 11" ] + }, + "devDependencies": { + "less": "^3.10.3" } } diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..c0d9bbc --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,8 @@ +RewriteEngine on +RewriteBase / + +RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&) +RewriteRule ^modules/xoonips/download.php /database/file/%2? [R=301,L] + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule . /index.html [L] diff --git a/public/favicon.ico b/public/favicon.ico index a11777cc471a4344702741ab1c8a588998b1311a..59f19c8c44c26ff26c51037e512674b030f75d07 100644 GIT binary patch literal 3638 zcmeHJX;hO}8h$KLp|uqOML=XJgnbKZNRVLI2?+^=B@x07681pYA%uP3BoRT-q5^J! zf)%ZR*4AaFtDRQ6Vyn}3YWL2J?Q}{n)OJdppEEz^oVn+`_qp$Km-Bu1d!7$ihex2T z4T74;)Bq>|Oih3G$2EaY60;^TQUVfQts?;Dx|ROnw!FLy1^qhY)XS)GT0jGH0o6{^ z$fFFR%;5;qTpCe9u)_Wz3aoq4LO%wD`v~%!ThQcj2nuH z6f4y4WTA{gL6MyuVxpr_ZcRajoi$or9MS0HfI?!8K6Lc?`=OQUfD$KrlsG$}+MSB} zuwWDlCp6{2=s&`9bVS#nH4~7!RZ4K$s84xJ(@8FmXJ}AMJs39F7jg zq=jj1tAM7Ux;gN^z0Ks;9%g@wFG9BZz`VsBgE{pHwr5 zP8L^@{ak25uIc0I8*C$DvsSkcO^q{o>o<$09eXh#8bz|X1XV5#$fXpam{JBo zgaE=VaoBB=f+DAEh*`T(<0(b94f($P@-Z6Oj8u~lq*HmQpvFV6)fK+D+s|3RQPJ?fV0U6EFD9_>mJw@!bX(tHi+!0 z=nUrLxHt>Z8}uO7HA0x7DKg#ZNMSG`p*TQnPWaj{2omkhh|$$YqLB&F3JZkk8zJB1 zDagz%kxF>J&e94J3kqa5wkWW&fy~|!*|vnY89q>K-;Ne1N0i&zBGJqYQfq6}Q>iF$ zbVQDyA5L|4qL=W0wY@FTIeU~5YsBm+}WTFV2TsF?;WrMA!jeVZZ81|;3kKllhJ5)>>dVRf!uDYYamxjJT zCXR{-$I=|Je}~(uevGobFcipu%HJFP+#n35C*df|9i0pp?D2KOfnYj%Sv0h>yfGZh z!B~nAJ<%MTCAuK9-iE_0S4U3g)vy@uG~6`J8ZED&*rrUIfZgcVR&ig!$|cEabCsv4G@Cqwze^ zr#V?Ht~O-ia$gm0G{ob2wGcOzGAwpT@!EI~I?Hk}+**mEf?TwfigCCz3loQ$(A-vm zfkP^cotr{kUpvCPq)@$e4c)WHA*roI&6RV=?`nmAasqPZPQ#nWg=1Vaa-JSW#2)gE z9XW*f!F`}t)quBu1d%1BU^I6?*wqVaP%uIoT9K?Af{kAQoRYI)P2Y*6tXzb0c(A9^ z5D*mh-_yJwetd{yejE7s`%i&4e;ZjdzIXrQw_m#c;vZgJ6aB@x^YsTGyz~6r(Nm|c z|E{2x-v`|J^q(KUb7QEmacc7NAJ-Jfm6heSuf6xzzkIOp`qiN$r_Nt_;nFXQ0s&!> z!4g$uf@zbs$KJj5{zuoIIn$E_bSQ4$d+x%uFaHtY`2CN*9Ov~L^MrRl zdgYCGKe>ITxdjNl`$hVRD|5b|e{{`*PRo~XG4uHBtM0R-9D}U%Qu=n4oM> z)-JX5*7gT}%MIrhHtv1)&h7hF29HrRjqd)vvNWTza-e5vez-^)^M%jOge>p4TOaZWqbDt#1 zT84M*YX9+X-53(Z)?YC~yG0U*j&`>vE6!PmD$_B5VS$Vt}8ENrZ z{z3`cWvk`}V_mJspU`)WI)6xYs$+`iBakZEEnu??I>R}ZhFY3hn>OiFYS`0N6LSsY zD`}##k&)3&Lo;2{AhzYECp9!|I;z8GxfPQKRL2Fa9!n6{Xc;p7<#}4Gr@U{?z2?VELNtiW4Ia za?(>%vpP9=Y2x5R+0_b$o$kik@qvGvTn+YUll%0aZAAMYwC@OhwXnRrv~hV^zJB>b zs4XuNBfk$TwnVmFd|+~dEB3p#j`-{3fZF2EwtflNNd8+)egJ$4Bamg)$nqx3%l98_ GN#G}p@{m9P literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/index.html b/public/index.html index a146b6f..4496553 100644 --- a/public/index.html +++ b/public/index.html @@ -7,37 +7,17 @@ - - + + + + - - React App + Dynamic Brain Platform - Official Site
    - diff --git a/public/logo192.png b/public/logo192.png deleted file mode 100644 index fc44b0a3796c0e0a64c3d858ca038bd4570465d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN diff --git a/public/manifest.json b/public/manifest.json index d1c1d1d..b39b2a8 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,22 +1,12 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "Dynamic Brain Platform", + "name": "Dynamic Brain Platform", "icons": [ { "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", + "sizes": "32x32 16x16", "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } + } ], "start_url": ".", "display": "standalone", diff --git a/src/App.css b/src/App.css index b41d297..1803609 100644 --- a/src/App.css +++ b/src/App.css @@ -1,33 +1,2 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 40vmin; - pointer-events: none; -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} +@import url('./common/assets/xoops.css'); +@import url('./common/assets/theme/style.css'); \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 226ee63..27c385e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,26 +1,20 @@ -import React from 'react'; -import logo from './logo.svg'; +import React, { Component } from 'react'; +import { BrowserRouter } from 'react-router-dom'; +import { CookiesProvider } from 'react-cookie'; +import AppRoot from './common/AppRoot'; import './App.css'; -const App: React.FC = () => { - return ( - - ); +class App extends Component { + + render() { + return ( + + + + + + ); + } } export default App; diff --git a/src/common/AppRoot.tsx b/src/common/AppRoot.tsx new file mode 100644 index 0000000..fc38628 --- /dev/null +++ b/src/common/AppRoot.tsx @@ -0,0 +1,85 @@ +import React, { Component } from 'react'; +import { ReactCookieProps, withCookies } from 'react-cookie'; +import ReactGA from 'react-ga'; +import Helmet from 'react-helmet'; +import { RouteComponentProps, withRouter } from 'react-router-dom'; +import Config, { MultiLang } from '../config'; +import Functions from '../functions'; +import CenterColumn from './CenterColumn'; +import Header from './Header'; +import LeftColumn from './LeftColumn'; +import Footer from './Footer'; + + +interface Props extends RouteComponentProps, ReactCookieProps { } +interface State { + lang: MultiLang; +} + +class AppRoot extends Component { + + constructor(props: Props) { + super(props); + this.state = { lang: 'en' }; + if (process.env.NODE_ENV === 'production' && Config.GOOGLE_ANALYTICS_TRACKING_ID !== '') { + ReactGA.initialize(Config.GOOGLE_ANALYTICS_TRACKING_ID); + } + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + const params = new URLSearchParams(nextProps.location.search); + const param_lang = params.get('ml_lang'); + const cookie_lang = typeof nextProps.cookies !== 'undefined' ? nextProps.cookies.get('ml_lang') : null; + let lang = param_lang || (typeof cookie_lang === 'string' ? cookie_lang : null) || prevState.lang; + if (lang !== 'en' && lang !== 'ja') { + lang = 'en'; + } + if (cookie_lang !== lang) { + if (typeof nextProps.cookies !== 'undefined') { + nextProps.cookies.set('ml_lang', lang, { path: '/' }); + } + } + if (prevState.lang !== lang) { + return { lang }; + } + return null; + } + + componentDidMount() { + const { pathname } = this.props.location; + if (process.env.NODE_ENV === 'production' && Config.GOOGLE_ANALYTICS_TRACKING_ID !== '') { + ReactGA.set({ page: pathname }); + ReactGA.pageview(pathname); + } + } + + componentDidUpdate(prevProps: Props) { + const { pathname, search } = this.props.location; + if (process.env.NODE_ENV === 'production' && Config.GOOGLE_ANALYTICS_TRACKING_ID !== '') { + ReactGA.set({ page: pathname }); + ReactGA.pageview(pathname); + } + if (pathname !== prevProps.location.pathname || search !== prevProps.location.search) { + window.scrollTo(0, 0); + } + } + + render() { + const { lang } = this.state; + return ( +
    + + {Functions.siteTitle(lang)} - {Functions.siteSlogan(lang)} + +
    +
    + + +
    +
    +
    + ); + } +} + +export default withCookies(withRouter(AppRoot)); diff --git a/src/common/CenterColumn.tsx b/src/common/CenterColumn.tsx new file mode 100644 index 0000000..243c8a7 --- /dev/null +++ b/src/common/CenterColumn.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; +import { MultiLang } from '../config'; +import Welcome from '../custom/blocks/Welcome'; +import Rankings from '../database/blocks/Rankings'; +import RecentContents from '../database/blocks/RecentContents'; +import Functions from '../functions'; +import MainContent from './MainContent'; + +interface Props { + lang: MultiLang; +} + +const CenterBlocks = (props: Props) => { + const { lang } = props; + return ( + <> +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    {Functions.mlang('[en]XooNIps Rankings[/en][ja]XooNIps ランキング[/ja]', lang)}
    +
    + +
    +
    +
    +
    +
    +
    {Functions.mlang('[en]XooNIps Update[/en][ja]XooNIps アップデート[/ja]', lang)}
    +
    + +
    +
    + +
    +
    + + ); +} + +const CenterColumn = (props: Props) => { + const { lang } = props; + + return ( +
    + + } /> + +
    + +
    + } /> +
    +
    + ); +} + +export default CenterColumn; \ No newline at end of file diff --git a/src/common/Footer.tsx b/src/common/Footer.tsx new file mode 100644 index 0000000..45dc700 --- /dev/null +++ b/src/common/Footer.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { MultiLang } from '../config'; +import LinkImage from './lib/LinkImage'; +import Functions from '../functions'; +import bannerPhysiome from './assets/theme/images/banner_physiome.png'; +import bannerCBS from './assets/theme/images/banner_riken-cbs.png'; +import bannerRIKEN from './assets/theme/images/banner_riken.png'; +import bannerXooNIps from './assets/theme/images/banner_xoonips.png'; + +interface Props { + lang: MultiLang; +} + +const Footer = (props: Props) => { + const { lang } = props; + return ( +
    +
    +
    Copyright (C) 2018 Neuroinformatics Unit, RIKEN Center for Brain Science
    +
    + + + + +
    +
    +
    + ); +} + +export default Footer; diff --git a/src/common/Header.tsx b/src/common/Header.tsx new file mode 100644 index 0000000..81cbb46 --- /dev/null +++ b/src/common/Header.tsx @@ -0,0 +1,58 @@ +import React, { ChangeEvent, Component, MouseEvent } from 'react'; +import { RouteComponentProps, withRouter, Link } from 'react-router-dom'; +import imageJapanNode from '../common/assets/theme/images/icon_jnode.png'; +import Config, { MultiLang } from '../config'; +import ItemUtil from '../database/lib/ItemUtil'; +import Functions from '../functions'; +import LinkImage from './lib/LinkImage'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +interface State { + keyword: string; +} + +class Header extends Component { + + constructor(props: Props) { + super(props); + this.handleChangeKeyword = this.handleChangeKeyword.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + this.state = { keyword: '' }; + } + + handleChangeKeyword(event: ChangeEvent) { + const keyword = event.target.value; + this.setState({ keyword }); + } + + handleSubmit(event: MouseEvent) { + event.preventDefault(); + const keyword = this.state.keyword.trim(); + if (keyword !== '') { + const url = ItemUtil.getSearchByKeywordUrl('all', this.state.keyword); + this.props.history.push(url); + } + } + + render() { + const { lang } = this.props; + const title = Functions.mlang(Config.SITE_TITLE, lang); + return ( + + ); + } +} + +export default withRouter(Header); \ No newline at end of file diff --git a/src/common/LeftColumn.tsx b/src/common/LeftColumn.tsx new file mode 100644 index 0000000..dbeb18b --- /dev/null +++ b/src/common/LeftColumn.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { Route, Switch } from 'react-router'; +import { Timeline } from 'react-twitter-widgets'; +import { MultiLang } from '../config'; +import CreditsMenu from '../credits/block/CreditsMenu'; +import IndexTree from '../database/blocks/IndexTree'; +import Functions from '../functions'; +import MainMenu from './blocks/MainMenu'; +import SelectLang from './blocks/SelectLang'; + +interface Props { + lang: MultiLang; +} + +const LeftColumn = (props: Props) => { + const { lang } = props; + return ( +
    +
    +
    + +
    +
    +
    +
    {Functions.mlang('[en]Menu[/en][ja]メニュー[/ja]', lang)}
    +
    + +
    +
    +
    +
    {Functions.mlang('[en]Site Information[/en][ja]ウェブサイト情報[/ja]', lang)}
    +
    + +
    +
    + + +
    +
    Twitter
    +
    + +
    +
    + } /> + +
    +
    {Functions.mlang('[en]Index Tree[/en][ja]インデックスツリー[/ja]', lang)}
    +
    + +
    +
    + } /> +
    +
    + ); +} + +export default LeftColumn; diff --git a/src/common/MainContent.tsx b/src/common/MainContent.tsx new file mode 100644 index 0000000..5b3d2ea --- /dev/null +++ b/src/common/MainContent.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { Redirect, Route, RouteComponentProps, Switch } from 'react-router-dom'; +import Config, { MultiLang } from '../config'; +import Credits from '../credits/Credits'; +import CreditsXoopsPathRedirect from '../credits/CreditsXoopsPathRedirect'; +import Database from '../database/Database'; +import DatabaseXoopsPathRedirect from '../database/DatabaseXoopsPathRedirect'; +import MediaWiki from '../mediawiki/MediaWiki'; +import MediaWikiXoopsPathRedirect from '../mediawiki/MediaWikiXoopsPathRedirect'; +import Pico from '../pico/Pico'; +import XoopsPathRedirect from './XoopsPathRedirect'; + +interface Props { + lang: MultiLang; +} + +const MainContent = (props: Props) => { + const { lang } = props; + return ( +
    + + } /> + } /> + {Config.PICO_MODULES.map((name) => + } /> + )} + { + const name = lang === 'en' ? 'Main_Page' : 'メインページ'; + return ; + }} /> + ) => { + const { match } = props; + const { params } = match; + const name = params.name; + return ; + }} /> + } /> + } /> + {Config.PICO_MODULES.map((name) => + } /> + )} + } /> + + + +
    + ); +} + +export default MainContent; diff --git a/src/common/XoopsPathRedirect.tsx b/src/common/XoopsPathRedirect.tsx new file mode 100644 index 0000000..aaf8a18 --- /dev/null +++ b/src/common/XoopsPathRedirect.tsx @@ -0,0 +1,40 @@ +import React, { Component } from 'react'; +import { Redirect, RouteComponentProps } from 'react-router'; +import { MultiLang } from '../config'; +import PageNotFound from './lib/PageNotFound'; + +interface Params { + module: string; + pathname: string; +} + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +class XoopsPathRedirect extends Component { + + getRedirectUrl() { + const { pathname } = this.props.location; + switch (pathname || '') { + case '/index.php': { + return '/'; + } + } + return ''; + } + + render() { + const { lang } = this.props; + if (this.props.location.pathname === '/') { + return null; + } + const url = this.getRedirectUrl(); + if (url === '') { + return ; + } + return ; + } +} + +export default XoopsPathRedirect; diff --git a/src/common/assets/images/mlang_english.gif b/src/common/assets/images/mlang_english.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ff614eb6e91a3a1bd15910b176062815e5e1fa6 GIT binary patch literal 175 zcmZ?wbhEHbPMvkT)|82+yPeNgyybHcp!flwkm& zGzJDBDu4Ix-QBx)ckkZKfEVb1WI=W@aF{SiTS!<4G&VGI@N=oWIFP{5!q2Lsl3}3e i)W)i-G-pQOVg^=GC!rM&J|-NUq!GL-=B1$mgEau6X*loz literal 0 HcmV?d00001 diff --git a/src/common/assets/images/mlang_japanese.gif b/src/common/assets/images/mlang_japanese.gif new file mode 100644 index 0000000000000000000000000000000000000000..57682060bb4f074227d132cebc5647ab3937e8bc GIT binary patch literal 126 zcmZ?wbhEHb=Ksu@|I=pvKXV2sbcVtBE>PAu?ToQ8 z0}{{yu|awnIE)z>Ib=LGEO2CC<`YwyuwWrmD+7DFy%l literal 0 HcmV?d00001 diff --git a/src/common/assets/images/no_avatar.gif b/src/common/assets/images/no_avatar.gif new file mode 100644 index 0000000000000000000000000000000000000000..62fff0fda9e71efb4049f128f71b9702f2675e28 GIT binary patch literal 985 zcmbWy=}(#m0D$pVxs;g|l?|hgFtu73I!cV0n=!y9#no=oidxfnET-$6OCc;rZgJO%o7Nf}UeiqoatWxL*`w>_Hu*#aC4A>bnO!LY|` z(N~O#xp|pNx1L{?oth&%(b$vIC$%Q&Qr>2$b!gW=LW9l1gc#G^scy2*o}R^v<_Qui z4;_k|n!duUb@Rg0BK7jRR&Irq8rit{$IfX;Kq|;VfD{hO8Ho3*rh;~NOj54$Jnz|s z_~Dei%+58i4DHhv=1*BLrN(*2JZf#l)+{mlFI@wyYg8^eAd#YiTe9sONRS99j4)kZ zWbl$!PG)zd^n+@K-UPN^ho~BV?ME%TsHqwjL7If=+cU!QR@SPs;`=w$cu5II4U@9PQdmcEZvneS9_1~@6w{g4 zWC=Ll&+SZ-`d^=_lY({m`P?rF^2AKuhPS#?z2Vyu+gu`fopuNMOq28HfW%Y~00qAK E56O(&lK=n! literal 0 HcmV?d00001 diff --git a/src/common/assets/images/pagact.gif b/src/common/assets/images/pagact.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f5b855afc641760ce695f2cdb70dcde94ec0a09 GIT binary patch literal 121 zcmZ?wbhEHb6l4%#Sj56`W$%=jV8>Y#>i<65`~Uxc1{hHM$->CMz`~#d5&)@XV7Bwv zbZ4W=D#z8l&K`-s4@4fR6qV?EBECk-i^)L1C-eF>v)v%yu4|?rc<9 z<+z&H*(34yfyg73q7r>i#Mel9F&PN>WM02!)*Jl&-0R)*{3Tc(b+{+Tply-5Ihh SYU2u#Ws#BVZ-g>2SOWkpSt^47 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/rank3dbf8e94a6f72.gif b/src/common/assets/images/rank3dbf8e94a6f72.gif new file mode 100644 index 0000000000000000000000000000000000000000..1c7c979b8af21c0d2aaa8490fbd36066cede5a74 GIT binary patch literal 905 zcmV;419tpJNk%w1VMzcD0QP?X;^N}-^YiiX@#Ev;>gww3?Cjs)-`?Kd>FMe4@bKp5 z=GxlY^78WQ>+9s?lq{^z_`^+~?=#@9*#b+ELrv+x7MJ#(+WDePo+tK9poG z;*M?q?Tx~GWazlK{@hWUdT_*~mHzOG>$*|)_V)bDALYu8h;C%%!C=gYIM|YgpLb{W z$3geRB;IITo|1^GgJ#^UTHCFo>9DNMy}Y$_SJ9qE^2J*J`^v$Wdi3acjAKlpgLu4) zS@qLQ|HvEv+EBlJV*cJx{oruJePR6VfBx@^=;-MG$r!|mNdC+>xq?vHi(IgWZuQH4 zzJ6t=eQ4vbljoz7wvL9pw6u3-ViH!{l1&xl7l8KLzl1*`6WJ@hqm71KMppp)Jetf7B zm8Yt!t*R8LdxI}s8FpG&IVUzAP(pBmx4FB$zrn+Q2Lk|o00I$y27T77e+JIb3>Vba zeb@&8&(S4(2G0-JR49o(V~y?a@re!=iG2o*4%mbGjRyD=^x%M`6>>sULWEG^LO}`w z?0fh}0Rw{+BThu561O*flBoH7V0X2+*AWVokb0(jH zE*0?UIrHYADNkf*V8KL9nJkTvDrM>vY9a&_5G***rvL&6jS%obV1cVwuvfE|?fO;H zoEc{3DE@gHm*NBh1LPvXtCw#jJW|{^p$J$oMLz^e065&>!s3UB9VaT1!pNNwUfy&# zB4!7hHi9Ty#;lpMXV8Bh6bQgN0D}k-Tr1cj2*Bz9uwUb5Fd>hit_)fWXE0lk2o)y6 z07>Fv1B^z;lP_=nJkf*!sZjY@@EFkq0Di*zDZstab@AcL52A5~2#GW}!1$=rh`oFG z^66V5AfNyQKLP+ifFt}Bpa6ga47i^F4g4p-00?6IOU(h8rdV fK_3eY_|pInG@<~BCia11BM<}znE*YdzQtV<4?nDPgPS46?+U;KG|I2 z8#EJIWuJCQtd&Wm%gY)jW1dUfmeBR99JP34L#cob%GGHaG&Z2$TGwyQtCl9#q*8;9 zBcG?sIirTP&Up@Vkqhb--AmJ~4dK%r?F#|es+ko^XGSF4Au(e_KGUa|>V{u!ZplWq za@H(+0%C)(dT8bO@Jr6*3dEZQJ2z$+YO!d8&l7Q9=+_7I@`CgibdJ^ zr3MnQCqfA}p`?$mF&VnW?y%a6DLW3m-t9MgvL|}`mb*%-t^HeuU0fZ#ev-T8JFk4M zD9JDcxrdVKc|~y>^r-%5{3u>JY+2RL-P<#CmJxWSR7XD9NRRvLxA!LoA+G?hzuJtVUKY=O66bZiSrWS2ggYKQZ%z=A;Kd8lT&Eti>H#Tzjap; bTJsN4-PDq|2WeEo1x8nU**9lxfJ^@Y9kgU9 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/rank3dbf8ea81e642.gif b/src/common/assets/images/rank3dbf8ea81e642.gif new file mode 100644 index 0000000000000000000000000000000000000000..50f3de786e3763d6643cb1cefad69d6d322aae46 GIT binary patch literal 894 zcmV-^1A+WUNk%w1VMzcD0QP?X?d|R2;^N`q;qLD4^YioLgwv>-{0Qe z-s$P-^78WV@bK&F>*nU>|JqUH(T3?T!85aM7Md=(xC#eRlQBe(kMiwRBg;fI;1WWW0-65fJk=T-k{?9tunL43^c&wC-!=_T%%EtWAJ;aGf|NF}K$*|?-cXxwXxWQg_rxUp?SJ>=q|Uv(@9*#B%8jsxZsoyXtAl3St)r)XXw|WCu3K8w zdt?6bivR79h;C%`=y?0#a{ls(jAKmv%pbOnhMQzQytK5GWG?Bjtjvfwr-C^D$Q$C0 zZRf;o|JqRg@QS{EW!ZgX=;-L%+uPXK*w@$B-QC^x_V(G?+5i9lA^8La004ggEC2ui z07(E106+)-fPaF5AYfO6h>3-ViH(bmjSdqBkcpC%kW)HGG#nc%m71KMpqZPUpOp~< ztOEcNs;pS9e1ktGcVQ`3JXs_fc1==(x4FB$zrn+Q#k#z{z`}wF1pxv93`hV80^P8G z3IWyu27Lnw))e1rWQjH*jqL95iSmf=jS=620tt-;`vg%?0BJ@K43!WWM3_*}!iIt# zFdzu=0RexBfP64g1OgohQB=SQf=DArk03>o9AvWN$B-itU8sPiK?4If2MmWq2PLCBdhIG6}> z3|TT|%a}F);T(B#<;$4`1vo%}fCUQ-EVyP+L64xX3|i}M&EUZvK}p`E84^bcl{Q2g z1s`7gc=ANci5o}Ws6qe$*Z~}vfH+Zw0@<;1N91ON2PidKm^s0wQTg-f*SAmf9=&?@ zkq{U-@Bn~;0tn=1fCCr!SHJ>@$Wa0sF8q-L7dv>-h=L3{2%&_DP}tyu5jOIG022f_ UfB*$h(8vV=_#q;R7zF|VJFmCidjJ3c literal 0 HcmV?d00001 diff --git a/src/common/assets/images/rank3dbf8eb1a72e7.gif b/src/common/assets/images/rank3dbf8eb1a72e7.gif new file mode 100644 index 0000000000000000000000000000000000000000..64d8f29673326a090371735557325997306696f3 GIT binary patch literal 856 zcmV-e1E>5)Nk%w1VMzcD0QP+V?d|RJ^Yj1OQR3p_?(Xj6(U^cW2+<-`?Kdo|1^_>gw{vTK@8hn|g4+ePXU#TIsN?{>(S~;c};fIREX9 z^~-+Pl7|2L%8z|^=fAqEgJ$B6ZRohTj(TOrfIHhJG<-uUVmwMEIUEHi%<;soz+)=}QVgJb({@zf-rc&8`WaF@t z_vED8t)u_zmHf;f#ED3hWGd2i)q7+9`s4lJaR2R)|HvD) zbXVER#=Nw&{_l$Z@QU~3)2DrC_Qyg0$QtJ6=Ire3<>lq@@bK&F>)P7d^78WF;Nb7? z@7&zn3-ViH(bmj)stlZf|RoC?*VB7-%h+nw*}Xo1LGKnWdwU zbOZ!)1OR-4FA7dvMo=C|VJBG?R)V#+xx2l;!F|KHy1c%?!nVxD&&dx10|x^JcmxjF zadUz<3yE4EjpXL&iRy^w>E-Y2hy~(^aSxCkW)zc%{QUhB6mTHHeg^xf3E-en5g;y- z2uL7+NeT@l5Iu}IvEs#ygEmT}Xc41Eh$B6k9K=Qqfi?!(zy#nxpCBF_j;LthLkEo- zjd1GZ=@V!op*ws244N}((MCe#2&wbnz#1WRAmNB|CE?bt2ETgcnlMj<0{=if=>o%` zTDESr*R~z_cJ4m_5$+5~q=d+iA!WWu*+6Cjf+jWu_5B-oaN)y=`z!`5n6P2Qiv3b{ zd^xgJH~~V74gg2Z9zio?Oi2S~36?4l8l_&{`gQC?vst@_EnBs2+l}-T06?7ho4tcB z1o5(BhlC6)#xzpS+&OgViKsV!9)0@q?bjQ*iD1AD8vq6h2tg#GM2{SO#Dt)7rcwL% i@#oi1bRWKa`u4f!pMH(7F@PNr^g+M@1vJ!0AOJfF<=RUC literal 0 HcmV?d00001 diff --git a/src/common/assets/images/rank3dbf8edf15093.gif b/src/common/assets/images/rank3dbf8edf15093.gif new file mode 100644 index 0000000000000000000000000000000000000000..704398e896f9b1406e07ec0ceb8b7f89cdef35fa GIT binary patch literal 789 zcmZ?wbhEHb^km>=_!iIb|5o6>y3~IkyZ&6T{eLUq-@SlCH7R%2ME(2J`R}~d)#~KK zwTb`Ucg>sB@$ZcJ>s^8WPe||Sj@;Q4FeOFrW_Qf72FE{Vnr2@=9j1MuT8o*&+YBn z^qaLQFLvx$*j#aU_VjIiZ3m}Ub>yYo%ZQnspK+wq-9ZSU;u?(J)v&^2j- z2(uC=pF_mt=`&}~oi=0EoOw$YE?=;$DcIJBOWH)s$&iiFGi2@hjhnY_-?@9krY+lc z?22D^c;B&uC-)rLf4nImsM9aD_v-bVowqw~+`9JQZpZ!RhrKc`8k0L-zkS#A;nU|g zU*o@Y271{WGq5m-R2VK|RjT{Pz@?H=AaJOjkzLH@2LGc&oqXC_Q*M0d?iXSYQkd9~ z*wOAL@7$+TX%y%+QN?!=3+LpgK2r^&)v6X9<+ht=_nPtV&B+-79#$1=ZUpJSytK?~ z=BZ+>tFl*JxJ@Jk6%M;iljRW*;Vg0qxVAQSf17Odx6_g9;))J-sb+_1$80UWz0X&B z`dS6C7@dg52IV6yY`qNJYB>^xN=KWy<^5zVijq%tt6GbtB%SPK*IRd`qhL|s^YaVc zr~8#iZOOQ_%yxH}tn}B{SDTDNc3gPK%_9)%VRGs0ZS#VMogLr*$=3XM_w@K&@$^0$ H0S0RT(G+NM literal 0 HcmV?d00001 diff --git a/src/common/assets/images/rank3dbf8ee8681cd.gif b/src/common/assets/images/rank3dbf8ee8681cd.gif new file mode 100644 index 0000000000000000000000000000000000000000..95428a8b96f24e07c3fc77cfe68812bf7998de9b GIT binary patch literal 779 zcmZ?wbhEHb^km>=_!i9Y_vNGicTRk}cH3%z@ir~(MW*}j6q^O*O@EWE?j(0y zNp4-ASAI8U^4BJISR&j8$8R_W3rwe!{7jlKUrAW8G;#fK+XZhi39uphTx_q7Du+`j?UKh z&ff0czP1TnlO|ZIn`oNqc}$)@bN1Y6GiJ@1w`Ae+1hv>whWQ@sNm4mq!u$n z@TmJF9tAU#OD8TWdra)~DElK(^yJu7_1I}CokoHz>{1`@o{7v~?l;H2(n-sKk)gZF zrB_L}DkSdGvUl^;Hho;k$i%|ADXw+_bC<%Zu#H)+2d=&r*$}>2?Z&OI*;ltDXPn-} zyL#H%NN&Fdk(r=}dHdMf=xqh}k5=;k Jm*rrv1^^~_L`?ty literal 0 HcmV?d00001 diff --git a/src/common/assets/images/rank3e632f95e81ca.gif b/src/common/assets/images/rank3e632f95e81ca.gif new file mode 100644 index 0000000000000000000000000000000000000000..224fbaaa5c0f968fb105353d0e15ede8c3634735 GIT binary patch literal 475 zcmV<10VMuMNk%w1VMzcD0Q4UK_V)Jm_4V}h^z-xc^78WW@$v8P@9ysI?d|RC?Ck67 z>+0(2>FMd{=;-I?=jP_-<>lq%cU3-l=!2?hupIPif75fcIuB;Wd#h)y! z>nN*~acOw({w~DA-Ne5k zW2S)oL!}>_K7QhR J+g6#u8UXBwP#gdN literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4d4e4c4f2.gif b/src/common/assets/images/smil3dbd4d4e4c4f2.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee53c7d186c7113f84aaa0c12d1a9b6d4567aa42 GIT binary patch literal 204 zcmZ?wbhEHbFp<&)wLfCdgn70NsH>R{#J2 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4d6422f04.gif b/src/common/assets/images/smil3dbd4d6422f04.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a75a92b33fc6aeb42ce95b0dc293089925d2681 GIT binary patch literal 174 zcmZ?wbhEHbk^W_CtmW{!ey zW_oFAj*dcvzkfimf^%t7s)AEdVsT~;gW^vXRt5%k1|5(lkbw@&eif^(?e%F%>e|Z0 zlhijeL^My(oS4DpgY&^ Zev$gu%th963>Qx8O0E9lJduIH8UTjBLEr!Y literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4d75edb5e.gif b/src/common/assets/images/smil3dbd4d75edb5e.gif new file mode 100644 index 0000000000000000000000000000000000000000..b1baee2b73b59b56adeb7bfc88660a8de77e94b1 GIT binary patch literal 204 zcmZ?wbhEHbTqjKs_w1>el{($pLsg$RHDfM5mZ(xg-cr=rB-%p3;ApDe5l3_J`v zAZ;Lv99TjocuHo?6=^(cZOAAr<8++U*@Kt);V$QeLEcRn(QEoDcK)0nknllR!n;MJ xEor8%_SVCSPkB^4)Ta2P{GMyZa`QwA7vD)4*N79Jaz$=s9dI!3P#0vd1^`?kNjCrh literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4d8676346.gif b/src/common/assets/images/smil3dbd4d8676346.gif new file mode 100644 index 0000000000000000000000000000000000000000..5777f687dd2a7c9c97ae4e8f973770c0ba509053 GIT binary patch literal 176 zcmZ?wbhEHbY42nNlSQ!}D8FWBeKn6N62UM)Ow%3Q@QHF5hjN}H* zgb0aSPHY)gQ=VOkcztYVQbx*c%{PDKP6!-lPBIcuW8$6Qyr98OS?03kDz~Y=D@v#2 X@Gvzko1uP{Q^roLc}o|gFoQJ!@8~}@ literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4d99c6eaa.gif b/src/common/assets/images/smil3dbd4d99c6eaa.gif new file mode 100644 index 0000000000000000000000000000000000000000..87a792e89feed8fc48b155565ad06d33e12b61ae GIT binary patch literal 207 zcmZ?wbhEHbTqjKs_w1>el{($pLsg$RHDfM5mZ(xg-cr=rB-%p3;ApDe5l3_J`v zAZ;Lv99Y69cuHo?6=^(cZOAAr6Lp+d(UiyKHlM4PE@u!^fz>po>&){55*U7nvNADo zId42ML-f|ehAK88_9gxkgs++%lUFn|n%U%R>~1KwPUM8#ZtIm2@7O-6FfmvI03ESJ Ak^lez literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4daabd491.gif b/src/common/assets/images/smil3dbd4daabd491.gif new file mode 100644 index 0000000000000000000000000000000000000000..95a63f2d6ae0b68ec902399c3dd2089ce07db543 GIT binary patch literal 170 zcmZ?wbhEHb;Wd#h)y!3=HfHIv_nD109&XDppD8a`~Zt<8 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4dbc14f3f.gif b/src/common/assets/images/smil3dbd4dbc14f3f.gif new file mode 100644 index 0000000000000000000000000000000000000000..77c71c07be59af34beca0c77f39fa48450c37fb4 GIT binary patch literal 210 zcmZ?wbhEHbgxLc6$23b2ZD19|4%af-@@>3F2nzSlmGt}{{R2@|NpQ5 zKLsg(0L6cbzM0t>iJ3VHzM1KzsX00d5&r%G!3xf$NvR4>MTy0kISh(FSy&kuco}p+ zdO#LAutaU}gxLc6$23bKgaNIF2n!7!vD80{0DM@;NRr`CxMLP|FjsU zO`B$HZ2T{m`TzgdAk{Y z42nNlSQ!`u8FWC#f*j_+ny0|vvLs{D#7LG#g$-|4OE@sA9Od4AFkm|Kd~XH`0k@Ux z3pZ%2iEupR+#)O!v+;FKh)h+ioyaK_q2&^4CzK|B=)BON`e3KF9OGFDp4B_lquALE i8kwS98TqUY_-bPunK&j+WODORWni1hR<5DQU=09d9aH20 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4ddd6835f.gif b/src/common/assets/images/smil3dbd4ddd6835f.gif new file mode 100644 index 0000000000000000000000000000000000000000..01b5a602484a21464d341220b76478fc7f9ddfb4 GIT binary patch literal 202 zcmZ?wbhEHbY42nNlSQ!{N7<52dK^8f%1PORnX3Y&@ zNw$_a(kLTcE}^CobmYN4myU^UnGK&Z7VlA9v3Od7hJ^@M`@yVh2Mx0KT`0QpdS{Ay h9Bb%L&z+$mfm&}QCmv{?5aIJo<5k2PrA`J0YXCI9L-YUu literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4df1944ee.gif b/src/common/assets/images/smil3dbd4df1944ee.gif new file mode 100644 index 0000000000000000000000000000000000000000..49697c5836b663192aeb9625e1586f6c02fb26be GIT binary patch literal 678 zcmZ?wbhEHb*M`@asCm_c;uIPci)3%;4(k%D}+z{}sdUjEw)=xBr_lEGr{}g>QvojJia}<0t(@RrxbQB`| z{R4s(oJ*5Z6`YC^i!*Z=6o0a?iU1YsfD8e-)qyotL7^)+vM)v1)BkDMxm|t-js)cU zxtd7+Js`it-AP8OH$257Nk!8_e2dV;3u==*xV;K(6l_FJx`<5g;bB{EV|k}&s_f>u zJ^L4(7CQX8p?bBdc0#QlzmPyjxP6NrpHohRk+X{;*k&#U9tIso21W*6AY@?io#46c zf@Si#sIDK(hLLB|jTV+nc{WpV-hopJg%y_~`3@%XG)#LS&cVUKx%gy*iij|mQ#ONd z2M0^D4-G#6m>0b_;>)%Af23QQ*s z8eFuP<{P|M&}7zuZ03z8u6&y-w~ou7quC&4QM9g7qK#5t+|!e59Bd}td(1V_!$!_S ipQ-JH%7pfSCl1~&f*I!pryqR$W0%*HueV$k8LR<8EC4|O literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4e02c5440.gif b/src/common/assets/images/smil3dbd4e02c5440.gif new file mode 100644 index 0000000000000000000000000000000000000000..004261bd7ff563a35837e8009b80ef0d9a2029b4 GIT binary patch literal 263 zcmZ?wbhEHbd~CZ#Gk6(tsD<}fJ!WMO4z5Mj^(nFw;218cm3YF9vH-xG&5r(OwpFa=InV5a|2 z!Z`DfP)ot47ZVv88?#b1CgrU5&=Z>N$kP($mmxFLPeY$YQ{cm{2@MLzOO}NOeOnw+ geDv+r*Ifq_l<(NHHVL*k`6Y37a+a_wDKc0C08ds}VgLXD literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4e1748cc9.gif b/src/common/assets/images/smil3dbd4e1748cc9.gif new file mode 100644 index 0000000000000000000000000000000000000000..50f9984accfae423e00821df1debc9bbfc79aba0 GIT binary patch literal 209 zcmZ?wbhEHb3F2nzSlmGt}{tp7j|Nnpe z|0z%&3Kah-`etTlBxdF)_-3Y;rsn7d~CZ#Gk6(tsD<}fJ!WMO4s;APMO zX#!c~z!JH^Q!;C=NaI;+O-EswSqEkw5C}T#u;+cknk$PGZmF$L?qp)RtS%zKAndWE zVZosQ9h3BBz_d(VUkEmTJ8JaPph?Np-m?PgEat8 C@lb65 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4e29bbcc7.gif b/src/common/assets/images/smil3dbd4e29bbcc7.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a96ea1baa5a12561f5e74249bf8a56e512f93ee GIT binary patch literal 492 zcmZ?wbhEHbUIrbI z7LY{_Eb$vWBeUj~a4;TtCbv<ZNFNG`%&x~-ghN1jI!qx8vO+NrF0VTVs}xtQ<<3~Rm0OB~N#Xj;I3@;b047&}1^@s6 literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4e398ff7b.gif b/src/common/assets/images/smil3dbd4e398ff7b.gif new file mode 100644 index 0000000000000000000000000000000000000000..15402e7b7c22082d75c6497226300f918e910ae8 GIT binary patch literal 205 zcmZ?wbhEHbTqjKs_w1>el{($pLsg$RHDfM5mZ(xg-cr=rB-%p3;ApDe5l3_J`v zAZ;Lv99TjpcuHo?6=^)XouNh0;NZv7I|f0A9rnBrSaW5P!Y#G+sdZ%w0}~j2h&pQV y9CZo~%V}?3CFwCEph5QKvxgjZEs>nuBD^PET_bJ;)$GrDyCi9a^pVLN4AuaK4ow*V literal 0 HcmV?d00001 diff --git a/src/common/assets/images/smil3dbd4e4c2e742.gif b/src/common/assets/images/smil3dbd4e4c2e742.gif new file mode 100644 index 0000000000000000000000000000000000000000..99368ba26abf66bbf3cad6436aa012f1dadebc6f GIT binary patch literal 4959 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 literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/banner_physiome.png b/src/common/assets/theme/images/banner_physiome.png new file mode 100644 index 0000000000000000000000000000000000000000..c53915aa7c231ce47a755a68c7d1e447e389ba6e GIT binary patch literal 1274 zcmV+GVUqs+|BlarO>OcSh z00DGTPE!Ct=GbNc00crwL_t(|0b&>)U=)mkQ7{Td!6;xv2FQE>>*b=IED{9agQ6v@ z4Rj-!+_U@sFS#;Pr*R}C$VvZ~xz+T1l&!!+oBsx3y>cE8UFqNW^}BSp+n3{?!x7_# z({5Mp_tiSuT)Y*wj#;pZ_8*V)QHr98-J@W|UKel0rC%|NU^OkH1rk6fSSkAsZRj%E3(Yl&{?vL* z%ON>`;qfeTxn!L;E@KcU z^Y$Uyx38dbM{C5dpb-R^BrKAIfwy~Wsz7#}9q zG~-SEjX(F>>XyG~ige-zZ-a8{%-hKSmfZ!q!0|S3L+5on1|Ij8YZ)!4tJotgR|nE= zs#~Xx4|ag>`UBdep#O>dBdylz7(IXX6WtOmD<|EF-z*IU<-_+fr#;ST%ZWCrFU&W2 zTk&y)<&6c}kYwj5BdrOK%Aaa3w$a-Ie~*KJ{TN?1(W1<5F-x>~y^*o5OmlB9WFE_U z>AlSEXtnfd^u8a3{Ohn`dQJesGpFAwlO9z8(}-EvxD2Xl93d|I0~L6VD%W#b;>F;a zkG kO#tb`o1E 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 literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/banner_xoonips.png b/src/common/assets/theme/images/banner_xoonips.png new file mode 100644 index 0000000000000000000000000000000000000000..6fa26de00b4e3e7aced0c5895797590e625cad48 GIT binary patch literal 2154 zcmV-w2$lDVP)C~ z|E!At_459MW&e9t|FN3?i(UUj0RKGz|7$S+oofAGKL7Xj{r&y_!?piX2KBY8@+bl5 zX;%N}-~VYy|3Lu${{H&<`swNE``+2^G#T_U5dYoP|H7&NQxg9=0RKJ!^YinKjg4ev zWRQ@M>gwv;+}wVCe$UU(dwYB6R6pho0QQ-N|B!J1Oc(z)0RLeu$H&K9TwGaMS&E8^ z)6>&mUthq$z*}2e!^6Ye5di2V1pL|5|Ly7jL=XQj0k*cbW@ct!U|`hL)Yec%(+vRP zJ0t$*;{Qz_|0@9hJp{9}vz3*V$0HWb5&-}9^#3vdaBy&ig@tc#Z^jP*&J_UG9|-x{ z*7@!0`ziqE=jX7nu(-Im+S=O0#Kg3;wD$J)b8~aLySuKguD!jz@9*!?(b44O{nM;eSLl2-rj6%Z1wf^ot>SI zj*iyW*1AbY!3O}#3jonmv?t}gM)*gpPzMgb@B1>lfNjjo%&V)bd3kw>iHY&l(z+7|&2n$vMKJl+(V?NC`}Os&Dk-Z10JIAL+cF#M z&CR0-2D}^)zz+t;4FJ;=0raPN&i87{5Ir)EhV| z7iJq|DLv9IYg z&-=qS7PlrcTll|_EMKv56|nl{HS?D(n?LVGt*az+^1_tVP;kQ2(ihI0m?0!IGfN@a zgC(ZutcA%r(Z+$?Jabk~PEJ<-z)lKg7ow=RWX+8E^Iw|=l$P0vqnxUdPUvLWh^yRX zaeIWs>s-WbQ3EADzr-C5Dg|-@1g$EiF6t`JL4Ve+TfgChIU7IxaMR|e0K8klS!IR4 zN~Kl0C7TheTph3Q8jq0Frb;AxfW#Nj4^+ev9$$+LH}OWw8u1C}PhEXOV^i~#DJ5@< z)TS`9C`12MdE~puQ<>k{8yz7N4(Ng7jkLy%-AlTby}Eqn4Yg#8D0G%Q&> z7XneNAS{vk6C|x_g9@5xNRUF*gy>$$9_r17alq|Lh9}NKseMrb263={yJk6b7&t5`ho8ja_vaNFJ3x+uC!cPaDDyG z=F2yp0k%@svQMsId`m5WJ%mV!?Ry!wiOXmgl4wO0J7G*nCNNv1oXPlJC!Fm8S(e+k zsPqW>bMw~KiwA+*ht{8Oo_yy5O0#N+!$s{~VrpSMdzs7SQe-`r$>oZWAf32uwJ=jU zNtZ-NV2;bwD^zLV10N!kH%IeZh$lXOxsh|i8)J$(flpMTLb`OA{8Mo+^(K&0z$ zaOLZ($G$P{W!S=@BaY2Y5*o`J?K zTi+w=cye#edI)?B-ct^HYu9JgWjL@82spPubzVV*jJwN?MHm}n20wjJaJEi!r@t;*Fzw%wxJJII>$hu`&OIl1Qz+$HWl@ux?7lA^4tBxwTl^6h`<8>iNhy* zcg*8N3`BAKKjV#W1J@uL8a^6GeE%M@SYaPNzTxw$JEUhcF1 zrDf2B<@0%4x0tY|d=)>SOWW4^Hg@*75`ZEMLn%odtb-*PNJ!=`FMzv;3ioKNjgcXd>z3TL8jHJXta&8taXue-IC5a zbpv;_tu+9YneP7cSUUS$1GkFPoUra?i;-ZZm^aCNc{nZm<6a0 zM`p2KkuU@9I<555$!ktn^LbcP?z^Q(Ei8+dLVkSz;mfDb=kvMNYE}RpMh1#6>$=uj zF-J)z3bOHkn`RG7Jj=ziH0rD>xaB3ZQc7kj^XZ&P67Z0@odeV9YdU;q?=QeCOS9`h zbnpGc!OOvskz9<;-D(n}Wy!WITjm*i#%vFoVc5((9y42Hv89&O>TWe-aaD3gW^i1- zhkn{md84|=Gf$rH^?UY=q*p7?ck*U@Q5AG!-M!add;N_JK&(t)wdSk^umD5|a@pls zZ&R&8aCKND1lr|OkSlTVL%;vG%q0BxfBzqU>|g}xCYT6a9fR{=7$O;^m31KWQj0P| zB6{yI01^-a1PBg-Cj=rQYnMuWFu^k^@B|PIwyz8u9Y-o}#dBLirj?L!(M;~#4Q`6T zNH7vS0(#IElm|huSbm)X5d$CqFwpX=7GF}?dYl6VlC?)v7;I&lD%+4#NDo^nL z48(sJTLa5qe7>zWTEaKrZ4E$xbk;B|ZAiM1ucbRzpLo|-#3T^H!Y))RiZx}%P4C_R z$?yIr5WKfd6AUncj6fwIBL8{`W*|857J`M~Avh)3ImZBqN~?&GtTEsmkVKLJ0B|ii}~@vZ~m&U`r3!y`~#o;!r%SKM{Z1J4Rt_uDx9Js zVvlAnfe}d6!h)8Ff#Hiy9RfOLHR!AKK zFo(R?%|-O|cm9^DT+GL#*<|WHCuzIgTglrU<6>v4P|j^JY$hk=_@JJg!eVND1!txV z_QupgC@qzss9}SMfCPawCKLBtRopbDKns0adrj@B+c+Df}V0VN~i?igvU-pkgnPVU`OdFP>(-f#QH z_eXjB_kQYU?-Ve1B&gl(2aQsZR9b;xQYy|`{eHXEm22maMB47j zB)1?f$j0MQ>D^@NYafGH>BW+Zv_-3VhjnX6tra1Wsjlm)GS>LOA^=wv$BH_U$R!I` zRFjkG>EU8F+Q0TWXbe;}m(Z6Zm4}jzbF$M@ zS>CO!5Q<6EE|kUxCY7XdlrFq7#*{X=sjI4a2my)9vWO*0&{2{nWMfgEUt3!lboP#B z){vJvc%Ch2J`c_WU?2dQMU`oavK|6Qnv(QfcKKY3X#Jr#fj4$Bn(W;j-o0L(+-Fls z2tGIfmQqS0<^aKmB^)KcxRX&a{37&iy+K%SAcQZj(9p7UaKIiQ#Kn>4j>R5m1v1KX z2fOFzosCP6Jl5&=lulg;q!K34SXTqp9xEs2&II9*n-ct%3H9lO2d(|nxzuhmZ4DSY z5cKwz_+{VtCx7VsOk;Q6{gqeW{WS|t=ZgS_n!@h;#xIq$z-XCWU{@F$sz~R~xzKoo z;G0T-i6c_3GEzoqLOENSc3XaRr#%hs`QuYJt5xI!M5Yd=V%G!=7JR6iIpUIaM@Cs!UWj~7-cPvihhW$Jq2LRkJE zfZ1DLqhP|Igxiqz99P2<@}#qpO39|I=SaMsif`Cnd+i(FbI%EW=-Elqy?1|6998+8 z~K^b99L;X?bR#i)-H7Cqxp0^x&Crf zEJCq>Y68W~2V)6$5`Jt9{7j|!L z?w$#WD>kn@{b|>xptnB>o{V|v*>JBP94I#vg-a~LcG&Ld%glNfzQAPl=Dji_3h(IdQ z60es2{%RD&=(rHLV*ClP@`!;PllNe~x4|^1(-0V3gNTw)lF$N)sGJu8 zfl<$Fn9e;ZDbr1CpL=ZeQe8|S^tv!h)zJLYO($~oBPjbzj}d|1B#fd8Rhsoeh~ z8Wtk{AFS}qutdW1hVmeC01v(t!LXo!I+Eaw@xg&ipnopD_-yx~ceHmNij||%*qVpP zC70Wyd+)mO(zCm_K6v@Dd!4P_-i49SY^#18wMDC$gt|TE1}}#}W$n%Na2=Ls00a--2=J1q0sRZ?2~Gc(FP#6*o$r%5FfA!5fw>qPPY~SZ=<6i6YKHQA5!TPr6UfYgsYt+u<*Jo+O zF1WgxRJb*89-U*uLCBy$FhdA%EXSV1nwRgK!Ilz_x8(Di>bj(`*DW^?ifY@}JMApb z^IB$x^1zL?PExe2lWe`L>{5!HTRIEvD?)}>WN z;|&3O3_%Nx$N_;#Fk-O&-~A49U|7P{o_%PLfqkMx62~j68{KYi@YqB3VtVh^wWGT? zeKBc%?wU^*OFtI}6GA{{A%q~|IXLG?>VOOw5byzn_z#@>6 zNOZ>ayaWP#@t@@VgU7)KZ-e(il3>rrvQ0WmcJj@^6%DRgOopfXO;x(rKEloby#Bwk zu3~loff(_BPpZIW5F#&c(Pi|jr}|o3R%x9K^!CH&yDGbX=g=PAuT1TmV4QP}ujVxcA8X7tWe@Hl)#lu0 zJ8QLGy*D4u5g=-c!&qr1X?;NBnx=^p$P!QB$B=t(T@Btb5QV_383h9a0>0jvBQm{S z`iMY^gbdiyd2r_XIq#wU}LgL-u07b9>BB$;Vl z8!r)nfPDx7JTjvK6u-zcR;K?mXT3pKzxc)S|M>WFH7sV2Qb_HC0fYbuAfb2e{F}dW z{pt66rg_;6C%aAK1(DE6?RDbPnv6vwv1y5$T$)bj1Sh50ubTey<)tWEYLT(n0sf7rhDUP z;5EjtN%Hl>TQ9tcLpI=v|q!RpTbp@|Z^GT`Pf9_-?Kh6|1YQ-ulY%#N4_w zuNUCU2E8RM&$9g*>lQ^BY1eL3zb$7CBUfjv58;c=;60WI|_dhp=&pws|g z3Nj7LJCP*9RB0k$@GgW!-2em>kxH`UsjpMjqPrM{+0o+Y*67}i`s7|w%>jfb(&U9e zTuvtanNp7a7umD@-{q`d{CK0n`UR$8odFSo@s0o)yl=b**_Y>^=sxnUBJ^hC(_(Uh z-p0hD>qAWm-nK6r?b}XZFIXUoh;1+qTG|u-29o_<6GA^mM%(#jD+tdlhNt%>1i3uc?7`*XQT># zr{azax5Dsa;}>3)Nhj)`8+1Yx1aolUt0p)vi3ypo)&ehWx6VIwzDeS1ub!OjResDx zF>d8b3SJV53=CD%)RpbGbw7`qn6+oHSQ0m-cgB(N-eWA)lBWm=0SN&Cmk9QC(qI1N zyvGm_k->n#Ge2qY!Fx+Y3~-~enM!(t^DCR@SI=MSZC%{I`O5g{01o%SS0-2lucbIs z_5lgl|DtLJ&p7Li3hRv}(*Ho<5dK}c9f@EG_5>jarF^i!TAqKnfA!5L&@ZpwaNbIS zIEs9zf^T9iS}obx6l?wV`K``ibw$MO+VZR{CgXYS0$+Yy7j|*-|sT zA~-GhN?h+WM=5ee{z|?!GvmrMi+R=JNb6VbK5b+rw5-}l!22e;TNhpoz z`Sp(5`Py>`K1ihHTZl+X(rs`MLb(VIU7~ch{pcf`SAw^9KJnATy*vKsE^`q)0|5Xp zXCSb|FH+9>|M7YL24TGc_5cX*I$Plv5yjfL5GAn@vnj$cLv5akd1 z!`*h)Gwsbvaok+wx&=n*AbPzBB4!Mpn1MYw8>IBBYD$}W=lqpOr1i8p7!L1LvqP?o z&65PrTa%V{;(1?`_l?UcY20Z8Dnz;Jbd(ZWQ>UYM&Tp&_(wFZXe)PHf^Klx6W$x`@ zyS*Sw!ZQZ|Vk89jfRY*)Y}oF{NfL1c9D9mwDN2KLzX;xW@PL6>5X1jYSegPeI2XePYv+w%@{)T=hC?&~NwJ?W6Jf z_0z+<^ZC*7xI8WF!W$b@tJCTn|K3sbwFlF-Z={S~8y#JnA9dSVkK(bTw(fMO{)u}Z z`lQ%@_R=#?PuKH^bbqaT62xXJY2&~{5l5GCrC2-Eaiq1h!3OZluhV%5i;+0KZ~M_E z)Tejn*FP)l_u0{!JILmm~@>I19YQnQkZ^KoL`6ojh`@ou>!rC5+dy-{KPl7NsYEcIR>Bq9R#)-}Nj1ORV=EJ~mlvRJoMrRnk$PqusOs~Z>Fy-k*J z!yE{OBKCrvrvMBd1<5qxSn0v~d0PPoEh$aoIL+(8&rRmTI|uXQ8%IY+#biO#x*wuW z+~PPAqG}y4IXW$%JtZNc$}PH(T30uw66lf)S61Z8x@-@E_e(X;G@9bg zl`KzazJQ|ew$rWaxUOqsjQ8xlXJ!NupwcQRLL~)B0U#fctZSrv{dCwbiH5wK|H()L z1V%oa`7;6nBT}Lz0IYAHfBda)fAxdYae1tXgjT+G;5;J|ky6q#J6|~CgcgC8LxvkF1ii)&>P87vL zrc)1fZHuNhwl>b9RiZi)3Wl5)9L(l^2hIu?>Dmp zUQ9!iYPFuWTS8{zXg6&?Ayj)1A1az?C=F^CtpUb)oFya@(n_RjkIjPp)WNIbf}|>< zqOpl!HwzHddb%ErfuWs(ij)ut?CZLQ#zcxpfR09pZMLD`ii6!qPv@?{!kaDGDuS(} zdft+{ZBrT0X)&%h^VV3oBoUqU4LcuKwL=U^x8+SqMBPkvJNfozy0Z~)t?Pb2sp^)^ zf`Ga8PLfe=*-ptAe>@EBmT)#{8W}vDwSm_7<+`FGk$_BmKpz4VLj$(^Vg zGB61MK`4-cSOg643m9(@)*CQ^8BuDK#NZ$_p@F6X$mQnMooC;&{_qp&>LxCa1uW~@ zx$b0IE*7( z-IYO>QV~u}7VB8~3Rj|yL%RCQH(V;749@2wzCVx1}=;3(H={D5SZvop!y12YGAb`r!-J^sjZN3)lA zCvQ5Yhi1A})$EN0rz(*pSuSKQdfm{>F&Gxsfw2WrUfCKeH)yqEAw9Ab;bb-=;y6m8 zxLZwdJ&BW!>YI3Paby<5B276J>yKZA)p-AtM?!P2KVWe6WT9e}wOdA*Mmf}wixnk% zRXD0mlTx~!@H6eOxgMJa8yVd=ERPnUt@Cl|#r~0xs%OvHhc+o~xA%@6Iik>+j{TjJ z;zAw-U0Z&+AF=;SA97WX3?Rc>{*x9;rdS@>RdLfE3gS6Xu^|fo$lQPkHuG%|~Kh%BK`=0;!kALW= zKl7&km2+vGL`p$dIyydVW{Dd-x-+=6C4Ty|*XO(2Pd%~y^h2|2FF$rX`vWUmRlL?o zPHxQXkJ{54R?2oi6V-((?CgzO*7XC?+Jl8%D4~*=f=B0qX~_G4APQVN81GHSMO|BOUO(~B zJ4Y&lrSgOr5aEor5WNPF0<|EbGb1Vs0YuzQGN-w=#oB7;{5O5wlTSYBg@h=nL?nPU z2W+ZpczS$qcmLLn)8peXnSgKD)xZIX5fBA>X847SHwfzu=eoBMfP&su@5&=9mmXWY z^hn%UpBQ)lb5ZmSL>WDN)XCRWB-6ItXBuij>Y0 zQc?yW!CH@1?0Pz?BFU649`6+vb}c;m>AZbXCAWv2X_Ey%^7WX_ILxJsUN|`rE!klm zs^Snrk(dPVJ^$rbW&Lx4|gxFcWz#2|C=wAm0Qf~?zs(!;AemK zb6>c3a?YHKR!2R~+A3-)GljB!`SRxb-V6QolmFZI7Ax(q{+f5dcK@?K{R95?@x|Vi zHq@=&$tq@VySOSkJNJt4`J=-*OKz2t{YiB))&;v(FB#*BbWnDU3rZEd8 zg;X5HUdh5M9};av*}$T(C&S4~FIidTjSYz61Y#(Qy0lHKIB92b9Dno{98R0E^yFml zUIk_!2t^2h$N;aW0ZIj8S!bo_g#aO#&;tZPAf*(7C1bf5tAy8AS_#DstG$Uis+fBMw#(IbsOm7xpym4Z?Z@LHD*UKk=Tg zTz&jabCDkxeCu9$d_2kYX-u-4$#bh~=eJkl)EiiUXcVlomt{3A=5r~fk}-H~oz$vZ zTiF;J<~*L3U}n{H?yG7PHe=)je2gy6lxRh@#?t%h$tT)}MMoZPO>DomD@A#(s;!^j z==p2=*M`UQ?PSn3@jX%3EjJ;2WUI*9FbT!(?N{Ia&i7vYj%OE=HXdHP`@KJrt*@Tn z*tq)khwHld)$UDcr-)?Qc^-)+&fBd5#__1rB{0+bSzksW2H$MBR z4}a!U7dh?5tCuhCd@fnNbARu2ehd{ncT|3SZ&vhn79=miw2`j8xwvY38*SQ=s(XmW06YkhrP{Twthvrld4BqYWGmKhCz!7nGYqzRi>gx4`;R2{|%Z~6aYax07gP7oUH&Fp<)jK*rKx$B9f{+0<=Vb!@uu+n~yz; zs&)JRq8Z!yqINhuKY(63ICs9+UzI{NIx5)8#SxB%R<~awsUn@l`5IE(7??j$x9ajl zdhd;KW{I;@Pi9K#*n96d0Hc&rD1Fw<+(l@;kANrgB@TXq7`vhE} zdG@1K^GTY2`tI?lmQhreRzPcG1yyf;GV3OS;&L8ed&Q1=`mrk;D_eDCUWqPT+3Y-a z`}x=EYOmAj#oX5{DH_{GyI>KO4bB#ItTBy5QQLb*tK(^1OomT9wAyXujWtYaGOaA) z0|qfcmJ4Mq3N#ozfwLltDc15qB^!A`tOQFT5?m-HvMh;{vyEz(w`8~5BBC_ijN_!K z%d{_^c(T*fHNf6U4s{JxL3NPRLRO`7f;klj(X4az=NjX!*S_%a)6aaYKG~PSt$;WN z0pcuL%OSXBx9AZuaXNrt6imXQ_YfdBX3wbq@7w6W0Iwtbe73CR9m6jsf7TlnmH|S^ z48X1e8z_zlVrME0T1SZ^RT~4Gq?aDK@bI(!^&PSPP}PJRyQhc82SV7DT<>&STfLRb z?;?VzoMyuzPA6qmkK>kEy_7a?-TP46FrWC^%*w(n7G+&EP^0(WeGwr9SfXaf%mJ1r zFQJ4GL=*sL9UmWrd>5@$!vwEI*zc;I($@lQr>Zlbz+%CnQ5vJr*>K`4k!5q|+*f|h zSL-zSnGgQdqt9MyttG?A98`;Md-6PI(a(PFvyGth&ph#4|HL1KX>s!({hQFxB373k zx(Xz}_n-dL=RWt`ANb3ED$0AG{_&sw#Bcq1t z=O(wzb>pN0AX8VtVk?2m+uh5T9z8jzCW~@qy*)gcjEZJ0;+951!3gEO3(hlp_Wmr< zi6AJlq6xcu$KcD0+k>s`Rg!YCSgd3UGGYMdrE`H0Kqw?k^(>EdE7Msfl2~MkPNG;T zC1ghkkt9hJMc(_muASrQRMoZ!eip*yb%PhTPzXenYL-ip#Ii_0#eT7{^Z8;tofHH` zRSpK(Ti*5lH+N{up)luB- z4yudi<#DPW=;aoda zZ9xhcuRQVSul`NnC3E@XKk*ZnpZIMgb-b3$=2ichD;2mGKK8kdY_-!~g)}pJ$1mNx zwAG`YaH~sQo;Q)W&U;Xgjt;3b}U|p~DT6tEFME14b~l zW@DHfpu@xztQAU7s6<&b_wJpHD@)wY8XAmGCM<&%t}R6^y4Ed%vEFm= z0Ro)4sT3F?A};any-9E^lwKL+{Z9JOD#=2O16HUS7LJ2J8`$>rqStN@R-c z0ue$mteV1}jHe-BUAbaWH;rXRFT8Wkdru^_en4#qf|+$vM^S|61BWD2Q4$O3t*ZrP zv!bruY;&c3?$I~*x+~W|_t|@|zETfg1qe!}Qpl>QA3PRG6elH20SEvgeDNX*%SQ4S zO1i@Xgf|H57aNoSZ^2ZIKq1H=&@qCnL(m&nF2Chn+fTgJCH>*l-PxUvM+<4|&=lP` zdF0aCl_xGHeKl^(CvV>$-j1WxrX3x(I8L22(eMPvL$jESOkG#ASye7v-GH;pI)a6( z0pLrkBt&#}XMFuF90U`AkY`)d?J3TcC{jTd(+MR)$W*&lmitodRiMD1pt z7ru102NHvGo86VQ`DFgdPksD%)9+wV3H$Y})ig~HUcOsCznh$z$*seG`WOGkE3drd zUb%OEZS%<|e?1WV==cA~XFl?&|MtKAZ=)#w+)w=MOCS7ujT?#AXiOOO-e#8!RRugpyJdMvJ1_-8&_sx4tGd&{I)XftuP{>i`Hr00==!O4$$#p{10>)HJ}gKZ~o8V=J@=G=XgtCu!0aN~c-N zltOE1ZFy&Z)a#_{E9W15@9M^*&z^k#19z^yW)}p12QZN z=Qq+F{(r+8gjE?LiQWM?1reiaJT7BDFFf?#ufFo;cP~P+d;etr-bphnRY0NJk3E@O zy((5$lvHpy^t(r4VfEU%d%f;j60Oa~VfR`w9?lnYR~8LSZ#iR4Rr;o8=O}oB<+E3b zFR>LM@{+C?k(B!4YNZc=C@g{?qEVLAj=64HjyhWCSo;-Cq0BJKv&YeE$pAX<}ok-~0aeq!+es?Clz@ zqxF^ip-YYD5B%VdWh!~!*MA*&_}~x!L~%54r-K9{t<}l=fMZTWkxE%o%+?c;;KsUo z+1Kh|R09n&Cb^PA7PT8rD!cGIo9$^+j!PNq4m4ApaFk?jfu`}MZe$2crxQBs15zY$ zKC7*cD32AZlj&3*jM|;fPQN`_iN{4_E3i!70V1j(K(ACGaWm00O}$(tFioiHpd>L% zL`8(~0D;I021{NtEE&Xy5SDKzA%r!p2lVEhW2SjM(*&%XgTO$HQl|`RTAIqtJ9*l@ z^yK#XYIgCZgWI=e2lw3Jy+yN#ff67~Eo6(u>0skMjG}15TbcZ(xD|iYl zK}ng^fnAW0tZYB}#Ne&(%(`oLj?2BH!|8YiO|h2Ct(DG&o&3_{o2nn*J)G{|s1~Cz zXhm^amQC6GQ>3sj@{fFNE zNFWZtw{P9FRef~-@bR}it~S@6e&2h%hoAbu2M=eHi(mQPulUX1Mr*w$#vgq3Z(n-s zYLMa9ojWgl;!~F|oIm%()gv?g^k+Wfg-H7=7V#A3r{-vmP8@w<{mRoP(3=<5k@j4f zYLQSNfdV|Rx7LaVAZ8atVcnfOqsO0J+gu4JCvyiZ5|Ku#f@nUO&&QKyHqNyWQWByI zA|NoHiP%sYFEj;AjwepsI(_@oYHc;$m{<0+4jx4Y(rW<Q z5lIjR24){PfOq6c#S#19m$OB2W{O7yb|FNJ0x%Y!eF#+<0vJT0$UEVIpFg~HyN5}y*Beh~yGQpXc33uL*ZB~(>h5;cM0V!ASpYGI zMsh6JkwjD&5InO3FxHQzWUbrkrN_y9v?x10ZBY(KyqL|4>D13>X%W-o#y1_-up)Xza8y9R(Fr2>$(=3rQ8 z!TnaWdhyYB@9Z4ieap+weR_QDHRxP{V(8~b-i!gfU?$Q52!j6wz*$TDqU5YMri66` zk{}TH0NY!Sf91EVKJu1{SEJWnYNzwu!I{^8z1o-*3&@I0Ad%v58r{nPufM0#(r7Y4( z5*dJ_8@J-Z?6kHYJ9qI=9`5en+*s+>AV>4VlgWL({-(jsxzU~v^F<^X=OvPN&MIdq ziil7ssgxomMbulAX04yCWZG0^tCfvv99EXCbH=hY=miE5z`Fnjki9k`h?oL1D3xLA zSri8L5BFEMcGd>%qvH{I53vePHI?h62UY@{>z_P+T~eEBPm7PNQkhMq5!PCC8LS|>bq z#cW^Z%5$+h*_)RoC>FhzJSk`6mycig*%u!DwzoDAlEENVorBlzz>J{{ z9QcR6|N98|p@*&z5r7%)9@g{2{)N`{;q9*$K5nPU%w5qdV`~%2f=t`cc~YK7V`s9M z+65_*W;US_=!3#E($95BXSIV?s{<g)_fMLxUT%o^n zL*CzCNe+I3rc=jMaMZW}fe}K)-XKcSw%{a-W2ZuCNIPPGG0NM$#-4c zdHDJZpS$zw=Xi7g^#tk#03|XqP(^;vfRm|B?M!0)Bot_<4c!;dB zx*6N~!9YH@ef1(!QW!e8JHLD9@Z|8s6^4+D=_o91Rp8xOQ^6n*1N(4h!htg^MHKKM z0E6@Fka4N#vO@t(h!~AKB_yuxY`bbNlI|?&2ARBf|J6Zgwz<60U4MAv@xf}Iw48HQ(ttz5=ROTw5ozC`NxUv22hhF~N z7p{H&g^hMk)J`%cp!)rlKlQi&&iDSs|23^8j?L3=dFPL8biZ)@`mdhjv+sCz>*4M4 z(A*vE+2Hf2RTQ<3+VOPi_OF?1N7@=6NUfYZNj4X>k<&2B+n5SgHr6^(kOhtl==9^x z%1HNOmaU_s)xA6J-py;{!_U;?kuzQ;Sws>5UGTwK4laOXKvX8MVjw*8r3sjgi_t0X zZ1q>yTdB{djR}o6mQmM8ptOg`CP4@x0HWai?wzS+teh;2uu8iq@geh`r{g))!CG9l z-UJw|htN0yLDnuxbSIA_iRq#$s>%hckeQJgg7Yke1VBYZaz&@5F-@Rl+pp?6OxP0p z@!}*+lQ_~B-}I)3pMI>F9PYmM{GDqrhl63|Evf_*L151Y0!oYm{C|TtAb+Xu3|c!@ zGDnVrA%V1P8s?2@05{a5@7Z|IuL!FTAMWi{rzhPgvH93TKyUZa_rlWi7>ygF_JP zEc?I+fPujyAc0VbwN<1vOFh+4M|Bz|y?OcmW_m7z^PQ}>zM;3apo2gsOuN}i_i%Rq z@UR%o_KJ$5G>M`lLR>ek7k=t9|Lo8GgDF=Z{^6hO>6Z5D2mkpGUY$Pk@gMu(?C#NK zdo6WX-9AdLuFI_R!i{^Med&ga<{$m1|Mnff^H=_^Kl`UX^mqUD|MrLf-0%GB|MegF zAO6G-{k?TeS*`rh47ed79y&++&Kf&d64C8HNII1g{& zjSB1Eg+LSn9DrjK762dunWWEt?cm{eRr${7WaQ=tT{Yg>UcL0lL+8#{!-AgMtw)Du zz12MYsIqGP`mQ{9ad&z;A05t`X^Hh5?NFFg@>32PQLsQj3QOJ!jKDy_11yOQU`b65 zf`#A^0$YpT00tyR1ZEK+FhRG78|=(iGm*iwws@O4J`YX2rO$7!UG4WZOVdnoD$-mh z(fVsA{*#~j)XDzw&g#{?pVkxKX?JGx>5A@H13&f;e&EjVUbQH;JL? z;p)!e8fI%rZzCIg|KIuNN3ghaaQ}yY{KL7Yt81(O;D7m>|Lh|lu}YlW*qz=!`5nLd zcRX|Ti7&kLYOyzY;v$P6+F7qIs-hi5QNNR}u`f={p~b4xjQgQ_Rh)zdLIW8g878M< z)gjhLH>Zmtx(V}FO1e2IPEJlD?{jF^3PqGEAt8jofQ%9)kT-nBPz-31mIW&iGsik& zHkQS~aQ6JQ!@Z#?CME+6QY|agAkivmve>6d6DxWCg6wy@S1xt8*6PEP$;qUgl#9UF z>vfx&ii(RxRoBkBz(_=rK~EMn_$DIXU+u39vKqJ=PF=~s3lC$B%E~)eD#MjTP$k_J`Rk zuO6HF@Ue&Om91<#Uird}{N)2{4~~PWu%0V7vgK(rACYgAAe4;A0Kmw&Y;6D#zI1kR z2mtQvF)X3kI&OTZX(??jZPvtr8V!vGk&0EoHy8LdK|h@&t+uS9%|UA*ls0y1v2d;K zoqY8^$D^5-k$lNuo%wvT|*;z4KJ<@|RZIhWgv_i7dxYVFXEZql6cp-3B*yB+%DYXd^ zgPoV?*b<-;C@Gc#>yqYDMN00D54Ts{#jXBkKfQE*b7QqQolHlw>A|Fu`u%0e}EfDgU-ofob=eE;PaKKtRHE_Yw^{QqWue*4*qI@60u?= zK#3@T6jIC*MdBZ$>dhr@>FBhR{&e1rw7%GiZ-7Jy$x589wukM(Pfwzsyj#BiSg&Q5 zuJrKe{?JXim-owNp*5gG+qli{TFOafroq^Rv<~{6n{R5jO-@)x@Yxq$i<;=!!DElD zJf6piX+>A_m3LivTz~Rs$CF9aK_9EN!P?1E6py4zbfhEn%2lCeJREyCacU;rOluU5 zz&Ud|g-elYEmV?hwz8`$>Y1mDb8otN#Gn1-{^9Pea_?0rj{s^Ax=FCXI-{J0U_3k2 zO9bYyH?Q6!^CC`Ez<0aoQO&bpOxvjtR*s!HoBVNi1PUw=#%2$?A2uYvaRG{Q^)(62-lP zJqFApwe#egtaqQ74ejJe3GEqvap4WZ;{T|pj5wYttr5D;GIX|9o_zPp!*6ZUwXVMt zXYQe$wF_4-7ZyMM>h9seskiRJM*PI%ai^bu;pOyWpRLBTQuCpo?N_s7Ta3AxfU6+{ z>!g%Plw|YDoe6Qso`Zwnkys)cDFGNzk^m40AUHVih*9Jo6e#BjP#_b5)TlID10b}Dk~oV} zk>)bZw2p+32mwL}I`N%;R#bMr@Xn}mHjBN9xCYxWbMVfC2GE{>nGi%;DMVO!dFRL- zjt>W!yl`%HYh!TrLa6Fw*wQDb^U=hpIw+(hN@gW5MSsyWa$4BRmRg749C!!>7(#Hs zEa>$y8Z$(bi7Bm}k4sy#x9n}utQN>YA_}6w-aGcLvCdoWcH6U}tejM9E0^E=wv)rX zn;-lM4*Y*SarzCsp<&6&HV$N4bhdgIo?5^7H1#)5jeXxn`q-6oMDX0r+t2UWlSybp za=F*~%7+f-_~d7IyPvpo?ez3!R3Up;&K(xleN{u_1Zf0~2sRjNW}sq#0Nw`A5FB_b z1E4rFXAmF&5efmw><|J3ZWt;6%d8j@B4QzdR6?pE{qa`j`z_F|Rm}1zt^4t|r+#F2 zdM%l)zHscHdu4pQTY`auq&yzqYlgSJW$nC(#AG&3^VqYi*yt>&OqHwF!qg`xM_Zkw z-(Ek@eO2+aF?S9QADquc>1MnZC)r6f#-iCyGAe8@&Nf@U)U#}7VP4%kyq#v-?W8Aa zh=l~ght5BIZz4OYlDv>~Qut~Vw~MVurqRysm25rVX+ujraaCPfyM1&2qo2OJ_tHF{ ze4<_)Nr4gsTO*-XPUtwVI|7J6DpHc92q2`QEK3uW>V%R+XpK@L066D@3+FHPJN?$~ z!EiXLgY7tLrSJ?DxWop}9+@Z*FcC{Y3CdQD_g2I3hN7d13F`YJ5W#cqi6lL9bplIRdi_(gP4bGBInPE973}0O3Q2;O;n`v=yIx6O+ zM~Z_5fg+NskzlPgZrM8$=;fdXg0B{Jd!-+@+lQ0sYN{_j{OH}!e?Cl3-yp32y9f*U z%g^fx|HsMT*W!2A_nizW^)g&;1lo`N=GFK1(1snk*@`mSy&lC#;xu3ul$wW;cPF;#jXHc- ziO(MYZ zCmE4Ys3?(A5{ZyZI-9vb172rx8!F?>VXqI*Jazf*iGB5cx>xXMHj~VzTu7*Eh?g%3 zK#a(!nAmYJZVrTJ(e6!&h@N1`Jgyf9v$)qaTkF%!^?cA%>nnOOn@+~3_h;*I2Gc@f z8H*@2MdPXxOl_&gz|zT7#|q-cYNHe-ay)~jMA;4yoH@(Maf`;q+K3<&OGd?Kz7|D5 zqOB#^N;E1FQGj%H=V28Q>fTzmd=*Z1!1j}AuE1nFupb?{`Z)|7!D@HIfdz~S|SooP9ehoxS@ zK={AgiireCCzoCaz$D4jcB{1Dt6czsFDlFc1cV4^0t-!2Yg+1BsHM`8PLeuLy~vO5 z9bLON9PiIzK5mA)ZgkJ`45sBXs~667HYbA8bA$Ev&NfFUyib5+Jq6Y>BBIJVSC|B_ znvMHPWjhzrG+T^LNvmGoGRAk~fh~ixRVzsk4v$09?{o&~Xz~@SSI2d+SIv$wRB@*( zS2tw;A8*v&@QJ`Xi712^1l^MwJqOx;`z5#buz$^rf9S>f=Eo-bm1`UP+6e^U*I(c8 z!G%jVEwJ|}c-nsS?5YS|@AhLY8JK22&m>rs}rgUHd3^aful0@FQ04%i(1m2ooDv73V5Ejw@K6JweIQ!cMuVu>{ z0j$%N3%a{mN$C}AJluNgJKwc=?oz;X_h5eW*5P^P3H#)-*fo>p}dCz(v< z-dA;#qV7aF8aOAHT_Ih%< z7_dxQaa;P12m|d2rw?zQJAbMDTyy%u7p@(D;S}!gCFSmEv(J7fS?0B#@jp z+H3aA2FP=&DbJBX0JSBsa#px$D|g!$)_d!lwZ#{1j_%!?>>tfdErcgu8_yh~nCNW8 z5#axbWfQj~NoFMEK;A(>M${p|QsZZ1++;dCI)Zj5edJ=fGl*m8{-``4wVD2p20r&6Cwauw)#xSOd#+9c-b&6AAvxxBu5&gqJ;7!QjMvIl+tq1 zln#kWN=SfNI*v(s@U>}z2%rTt@CJT~XjuQdQ4^7uSXNu}fC{n=-M`em@EFE%7W2w_ z_ibOXll0ErABI25FW4f=V1D?5KNjRyJcJ^$kK6Ekgu@e-Zn z649x+rB$!AfQwNm7g!F#oB$UPDqs%?$il;N97F;HAt@$_L>>`H37HxOQmVbS-X5Hz zlcjMK#p}OdD1ZdQgG=g&PzK~kQJThiyCtM*8h>x%r+X*O@hKM-%ul&K#`=`Y!+uF$ zbM>ibdzb2|5v17Byc(CGI(V%fbmOh{PP>%_S8Gj;LE~MlB&E74?dj>zSm?C6lq5w_ zg+)`<^SDhQ-Gz(mA+5^-Z{EANCVE!d(?wxj*x`&-c1-nt0?#zor&1`CqR6;fjm7%8 zPQKdTZYQ_*kB@GjeBC&Hi=w|1UK{%%L@Q*fFTJQNwP?9~Ko4$G2oZ4*by=1R-)iY@ zM-+9Vf~3Z_QgQX6)!x?X-NX9DS59snh3UweDo93RHq0D^=Lpd(i3#{i00sbO8w5cQ zAdrzgc@F?A6AB0*1PdyRE9!bYvvFKZhvV(d{`vDO7tak^tvb113TbqKg>4t}(iF~t zFb=6<_JM>05h1?5whq98&QgNF0w@w%Q6xcAP{Kz_NP#v~#>^UH(#~2{Rk!XPafRS> z7fEQEC6}5AltQq;!B_wRzZCEWVSTZ-f+g7dFSb`RS4+6`O#kusl}dXzd+f^K%}-q> z(f#}mCRY4iMM zzk@Lw6+Usl*t&W9TTf5EmM;Eq4dsHsQLLOn6_%_4QnAoXik649$~X~HOQlFC&rMYq zwh3CcW!u!#dAk)~y}Xlk)U{hj&t04EAJL=&2s(;bcpn-o2?7ZhkdeRWR|oKCCJ9^? z;z$IquQ><&lEce!?VYy{BBg{NL4t*3A#d+>j>l&IXn$v?wYjzO*rhBI!yC8vqy7q^ zpZMS#sGSF3&0aB`@d-kJ*AKxDNFb4f04X_EUdbTQ3HIRG`5<#239*u`rk(BG`%{sw ztUvqJxv%SZ;TFa0;HWw{sLevLj6gE`8s5M!ttsKz%FF9)MFO%uxRrF{3U*dzv*CrU z)kmMWq9gu^j~(payjPzb<^nKqgR)85tb3i_Bw5w@YTW5VWyDK2rgyI&>vBrAy?vYEQ^KHC`z&*R~m7w^CN_OIK1 zGY2`G%u&irYGqLAcv8(p-WwI;`p)6WELvGfH#gHLNs|Ge%!_GRpU&n#ch{-19A>Be=qnQO^Xkae|V;|VyR3r2unw&VeEsUs~x zL{hR?4rjb)YeEQq*^dhAECLX|E+Yo;#<45C7CVJ2?;ehZ)1!G|E?wBTxR$5TyEP&K zGB`C2!5R)OFp&_*J^(E{K|(~3gi;|9MLGajDV(IB6-G*G5eXr()kFZqDl$M`N1In3 zedxkNsc(w7wpC$flkxrCyDvOHdi7=NO)3HWYO24NxMm#QrkGKwO6{3}VWw0jrr zbkx`G%Fep+@*|&m?bR1YQE2iw7N!WuQQpE%2hvum<@tfy8Yl<)?mc^Y^8|+X6fdwD z1>iu!kwOuH6f)v03n_MNS(4HL9fyX%5-_o_%qS2^GRi;*B!tkUlvR-siNZ)x({9Ci zLZ$VZ2&91Je*nC^mQ!yI43-&OFt(h}y!YO4IV;LV6*Z-;PJ$bgvTWQyr|)m?{K|8W zG>b4VrzUXHYL}8D6CRz3^CCw%y1^^Z3fjxk%2ldDEeY*E@%Pan~-6n(DMEf2!KQ=zEV;0}hMl`PDm{ zu3MIm%Vt1dCnN#|A|aIa4y^%iEPD)Vn1$gmvBQZd4==3u zQt&UodjI)XMya{aLCyjNOw)E(XIjVD?qZf*d3e?L+u{rN_~qAz<=y*HwO8>%*M&y` zQ66MUq)-qE|A2q;mWUMy00;~g!O<7zmH5THV?^;q-9$19&m>SNA@f*gv2Z@5T2x55 z#J_v&5;F=0$LyV1OlRZCjB5uL0c3C^(~N{DLsLQJp4@rtt5z=ekBV#5L^{snxCT4% zg_1g{32dnA;|KH@bxqOCj*VTENfumyI1f=Ct+iL^L5Am~wibL)f?Va3EY3LTtM${H z!#JSgbiVNG27->7NC>ZYIA24t+Y~qE!%*5+%<)*%=V#@{O>7silF4)EeA5KUCj}f_ ztL_~&_w&36CT8bVj1ox-77~O;sX=NGk&Ly}0<{DIL9kR>$P6(mX2tr}3P?Vk%}OUg zX3iNA`97*3n1w=_1tin>a$bwFHgf|@e5vU>BP<4|G-g?}Oi5l?YnKP-c!DfWl+@C* z3&A1?A&?n^xm$T9qfA9l8v>Lq^gXZmts+s&YH#t>514epulDSkEE2; znv|3YmPxL=y)5sfB*naFj!urIlcEkAu9^Va2FPMm+eO(d5@ORpRpVAG;#T*@_4~(rhsk6ixy8g%q0Cg=<|r2`Nn|A7^R@#io_PKR z_|&IfolovE-fgPmIEY%3CPZJ6&?J(g0#}%oK|5%>2pitMCjF@lvKH$O)0m~wl94ZlK%4(^brbJyl z_15j<)8W0Fqi%ZX?#W^b3rMKW0!8HOrddqNY7zTQo))eSAH8v}9l|5MP7{u=Pwxe< zmDWOQ5h!Na;dm>E^SWma09CP26D+HT{ zX1Pk^X}cXNj!(-~kExj*&WnSUxu3IlSu6+>_K~X_@qmaGBI%X!Af4Q92iGDP zslql@U6)>H8O4Hutc4H)M_N*3YaiI9X<{whKP-fpJ^gSZTecq5O`s;k>{%1BU8s~0 zQ79n*@{P7_d4ZWgBfVsY z8uQ_Cvy%57dB@it6@2tl|ALlg+u$AWk{ekf$UqjpJkWoj^c4CJ^Zxux_NaOR2usdl z;Irtc01yn}&5%ZV{k zSf1DkyRxSSF;Tf2HYV9YRqSFT3`p{z|=*5E@b;~X_v z4rN1RTM!A9P=xWFBa8ET3nRTY>)T6@Tv|JS>FT$?X~MEf+eao$j48sXnegd-{+SQI z_L0xuuDPW;ee|-(Qf{MlNN%>4!IfT1>olv&ELoFLdp2Lhdax4uqj{6YQ<=?sy=>6B z^q|R|U@XXIvVdC98V^usM**MfTU3K#)JUDgZGX1UH~gi@+{!NEThFZ2=voB z^z-EDx4-Sx!yET*U4v?>V#U^Y?}Sj!2Y3U&KncsA4UFBg2_!+Uvw~E<;TE98xGpLN zx!zxU3C9!wV>yZPM8<+rW0)+e(AB`PmgPEMMW11q(jHbc)fa_UuZ zzMdA-)A6xX;_~H-Z+qwZN^5|iXQ%bz72Q3itQKw62{K5YLDST=Ykc8Ftw;%?L4JeRwvth^jE(X+9^a70jvT5`->bwC7`+Z{kxy~^o<)YOpi-#I!T_VT)OIR zEP|b#tD1M7lV7{l@u~QpvMf^CkwOquO{u((#?t}&b31X`YG7mS-m8nFdwloyem%?CA9T+JYC$suQo1i=9x~Sc`F5UWGam@p{|vZiQ+_CElrw;jjeva zpPZbS{rj`iqY_n?M_I|Xu}-iszQBM!05EDHr9i^K&I=+~zA!e<3xU2ifw;4>`sCMr z%kbZZ^3~5{;8=;$SI#3y4FP^Z;tj%5(b;MqvKQbXfCmB~B^Rbn0{hCB)ZU2K-s+OA z$-Gzv9V|s!_wzVXsDLRo&jeACDyzr0wbKcpiMkj8xC`X)e#rYn;zVrJMFP^_3?d+T83s z{^*rzHrDJBUAET3CgXB$k1a~@gD94L)$SPfMO9Ac^Qtinuqw%e!$1xx5cPYjQM=Uy z>C+9NfB_n=31u++>7V`Nzx*fv`eU!$c>cN9LK8<9pOD*EMoBtMz#zUan|HJNNrbO{ zxb^HHd~$eDjvCIgR*H?86wQKQ+D~X@Wu>*&8yoq`wfZw3{Mh>*ee>nV+dqDHe>@v8 zMol1@^t@3_6s2*)o?RU!jrXO>9wkv`X=rD9(#(XMF_ol4E6IbCK1kSnZ<6txgCR!V50SrA}oT8Zejll9Hc=62Wl`tF^> z$+Qe!Dyfi3E{k<3#h}-+b*L*FY~T>Q^?*PGz(EM9r7Y{p0dXWxi?Z^5{oIvHZ~cl_ zikZ3h3IJ=ZD~~_{0>Ljtyg^t2fI&$q7?{}s1|R_0m=G8NB(zqpyzM>R^Iv8!+^mL969RRYBFrAzum2?gA1iH)_^`f3Xx?CtN@ew^eg%{7P0 z+J#USyax=z=M0=h3Ztm0U0K?ItfgK~hK){A&mvf_<0zo7Y`8m~Z$0v4WS(%ev z3JSGgXWQKgBfu#<#~Z8C)I2|DeI;&g|-v)O}!ZVdWImEL=#CJJHln9LxBMS zm=L9qQu;6L(2!U@z-6y0@Qkg95hWlpDnt>0hy!B?2q=~H))=RC=ymX<*M;^rjPCjB z1gs%pk!&zCDG47yV8A6?abWM5p_gKT04;8{!20-fDnsRC2(~s+4JrWe96g6HtENA` z`_fbA-*UwAq&CNs;$mkeO*xz$ceA+LZjMfmM65flUNeT*K65-iIW6b2^|VNdw2%Pv zin8_sqbRFH6&Xaq4TPFq13t;3L9d<15f4YbxNREnB(0Pw>9T0DOt*R>iUB6mzwzh) z)L;9D|I9>d(A|Pw8yJhthsyM76mLGBx4%A1zO6-1hH1Y(EyvUdSp{%j3!i0aH_uv? z9|Oo%yPpqw(dyv#OnmUuw~zL~+Jt4tM|Kp-Sg)ff{c=bm`8 z65_cJ|5Uwu1Dpk|et~BGy+K$gwFD3BtY?M*Du;X(vTl0iT`Q|un&~v@wpP0vqiSfN68@KQo16c7$u@*W=23EeIVz2 zs^v;Ay0ev~Cl}3Z-=5xMH->-^oDU@l%}9Xg&+P9=e6~t06}R)Gy`6P7z*(mc&Eh`S zC+J3AGx!=@VCexV)#)^bpO~NCwSFYDD@8%YRWMiAFJ9Q*ys)`_xOcx?m>A-sbQr}w zJh!=$?42A)8E0`uE<_Z?-V^%5PEwnSRHH_NuJUz+q)=*hZV**A>>VE`oqn&Ex!^4F zxr-N)3;~)(lyClur~k`-SM@G_^5y-HKYw#Ecu$sO7nAneTlrUH;vIdy&|6f+{llm` zMI)O;m#M94rNzc}zHuqv40a{YXnSP}-GBUJpLzbZqvGh~d?dg6S6uj&@4HB$frh{F zmwj!t`KVLt_m8Gu`|h{C_Z@@RUQT^+;F}ZRXeG7peB%7$7auxzF>Me(|LXX(4skNO zypq(@nU0;(-N_tp?M=sv5VyNg*6yT9$tPJWic6do&RBE?fDu4=@Bo1w2*5$79lCLC z8m3UyI@7WxFp=C!;#kFnO4j7;f<^ZM3aeeKS0JnWS7 zqFzieR7$wel+C=tz)>(&Qy~Koc@!iBlB=32=!|*kM)VBchY-$o;5aOKX-QSIyr0n& z@Y(nh0s;{VS}N{BFgpHX^XM5u2ufp1>wKec54Nl0&1%s$#aytk-UBZf^Kdo{mI`$Q zQh*>p&_dGoxqS1n47$$M&AH6(mHg7}*w?jSXs0@?g^vB};D(XSr!$hyx z;%cOxJpbs0!MSPaGr7^rqFCv2Q78#XB-~;yJ6SzTBqiH>7#h^P`4kxFikt9ncg zDk0+}khiw68}aeM=reoQR{6p+mmWq7a}Sp;pQ`~7Sa;jM>Oc7n-z7U$1%K;r|LDEv z?{nv=cccGhEA)=Hue9E=+Ir+1O!)8vpWA)yXM2xazHsgti^c4wZRzCUb84$se8cwR zS!@94=6>|2K6bq&+kg7M`A@#>J&6)^8W?N@@%CHawSE4n>eUx+fBIvGfAi1((|_`J z>60&frj~ip*;`xh{pw%&uJ8P+tE(QYfFJnC7k=pbKHA9ioo`)#_xrwa@DNt&>lbbYYiAFQSO#qERHs9=L$ zfbiv9C|Okvltu_402LDkAJ|yJ!|}`yRxUpM7VX`OKV_zew}D`ZHwX*AOkW0v{~$r3 zQHUC9Kv`&v0vTbvfB-7Q4vZ8Ya_Fw5kG!pS>CG-$J!nLC`~p%EQyycbl`%Fg&EVoA zmoWQy5Uqo9JZak3Zu|Rp7xNQ8Kb1|m4z|(0gr;Cqb7OG8DZ$osGvf&s5x>g8+dO3S+buY%BQG zYoTJJMf=z+kly^*V}0nhXCifO9?#)%^57zfKlqa$dhrv_zxugX?!0z)crbZ*ZSyVe z)wgtd=O5bM`mJAaf{T_@5c|`o^SxpEmA~qnL=++Gm$Sh?_|bp+2qnMfo!=12%76%7 zU)X^svQN(zi(mEbU#$dafC5oQ@Ufrx&|m(`|L_a9Cc8)b2;<-I8~@XG8h_-|3)fjU z<@`6k_r3qwyRIh7@p6gf<4<3@@zOsi=J22Y^51YiLtSGmQW>g?9r3l#q<{M_{Y>ZL zd+yvT!&qE0aB1BsFIsG=ii(DfICK zX7|GAbbPWuTuc|!*(stBq?J-}94DzRI1H=d%ll@vcW`mDb*`86Q+aoPcKf(O%S{{` z69On9Gzs8PI#@_FGVQIY#4O5UI27xHmAAe5id%f{U*CmLC=s1)NCII9fnN^-Ao%h? z|6$HvK>RZK;mh!6{X(p;Jk$^Zax5gFvyLkO0@bd}0^${Y?&03U&vbVl@gbVc7P@XK z&H;)%_F2B7puHHI#cZ^)VpcXDJDxQs!?1gFa`(<~cvP9WtrrDS1HR#=#HIpUd)EYO z!Fx|0mjFVB2X~UVthNZ26&3&pC8d-|4BpYQ*ApT_&@#kMWWY(_E-6No4B~ZJiy<%o zgIEq2rIcbR;ydRSi?V5wtqbc1z9~G5C!elvN3)|_`Q`qf{FA@)xBQy-QKY{8+rc@w zbL%(%FMs);{_}tP;$Y>m!A3975KhIQI~47K#RSB`cH($6CfV2p3e7AVw0H8iYK{qBJqi$w-xr^U5=N z0+b{o6e=Jxy5RFHLrQ6ii^alvQ!9XWHv?^F#lQMr|G`gu-@gSPa>%#4n;SaX8CHYU zwWr?w=E{di#Sjccx;!0z+pqprGSS7N$P#Vm)1Ug`@Bg)b`>!Pd2;zV9Z+^H~m|yo@ zzv`>L^6P%@@BQ8Heb3i^!#95IpZXKOR}tK}d+?wAuHV0VcVVMdaOHpcJAU0?|I2@< zF!22D?N8r6eb2K`eb=|XNh{An{G~tt55Da;z5o2?<;$C$Pu_k0$*boHykq(w{=2{M zpZ({*<>G~Nw{G1jim51us@>B%xxITrb<>OV#?}^P?fucb5#Y+|Tt5>^8l)f)O{JiT zvP4m@fOGr%r#Elx?(L1|lctg#WjIg$J+MDHp6pCzSw$P|KAQTIE3146EXJ!Gw7&C+*B`BdHwRB=Ji9iqlD6pbs_Kc#)i&k)L zvfh$Xp2a^&NjCWTtTc`8tVEmVWW|*>8)(vbJy?XhE04c3R%%+*aVCYV9(g$b3xEFi z&B9-Q?&cASNVJ0L<-vFA#iW|thT^WX3rNs$h_Y5WsX(bD?^G6|yi;2V1a(t*Dblsx z$4`!?!StQ|x{}vdR!`@%rfGs{B1<{xtt@loAlA-S^SX+p_JCzwfdVfn(6Uwlj!;FY zVlP5~0Kyv|83v0Cv@m933`hkI>dAcX#%=U=r?ru?zPi5Img;SBTdt(==sGG8;HS-^ zllR~8%(JaQuQKy2Pr<Fscyr}z-uzJF;pBM!d;as^_fP)mzmN#qo9C?cpa0zF ze${vUN(g}nKJw8|+`M@|TYu7WcJ=Z@f9SvZeahQJDeoLLv)}gZ@7s(G0RQE`_b>m& zzx+qP`wx6a9jd3VuFekfE8AV>=KA&B&wTdPKhWI(fRBFkqs@F`O_4{usK!2|_YX?x z_PgEA*4ml}UpBs~`N~F1DkxcaMY1U(#gWeECVl=jckPw^d)Mz&(ZuRe* z1AZ?2gbUBEVLK0I;a$byY|#M#6rvQQh-6s)`z)#{$W#i_QOrpy<48wRMV|N1}lKm4^ky^ytqmo%H;q6mbC$|o3MbStzxwELr9{s);`ErRl3s6fA!tHRxEEHow5YdscffKRE|ws zucVO%@VSufI95W$GHN7=h=f1^0=yG|no%;b3ocTom{H}UkbqF7v6Thz3J8N%wZd$z z_toF<4Ue6F_|14lsVCm?_P1CED6L9JMe#e{^-f?yfDin{2SK+Br_=SFU-RpK z<@xQt0Qm4ve(GaC^1*j}^S6H0vsb}YljFr-{_Fqz5C8VxBtYb(M)zL1x|I&Hh}r+6 zfBcV$sMC>kZm%Or7-!>d#|Qvv zh>!z%8$5epQbGn|KoN;3LW?exT-S{ULnn7ndmC%i%m2*(`q$U{E30`oN@B3^(SP{^ zpPjw>U623jO2h2V{h#^nAA0-YZWt*-I_Kk?H)YO8tF+BkpZ3XonbnipSu8G=k!&qe*stqWI#0C4chPkdB$vR0xJ z0Z>*4M~C0_8-LSx{ia`z7@0bJ>SG`IbASHN62Qr%_!r;(-A}&hT>;?a^!}aOH)OPt z=nT9bbhk}FQZ0|_{^9)mG+*C|p>9;Fxh{~irC?;TD3YRkuwQ-hQ!fu+dzHsSur)=> zLxf78qB@{(j!}wb*z8hIkc{9tFxDmrLZRXey`C1v9W16(dtuwO+i~7a%Gyt6Raq3l z2Iq05mo;&mkDIat+u)@11{Mp9R@;MT-}ANi2Wu~W_ygf&-)SibjVpoPAgup;&@hk` zRG9`L?yIfK-Tt=BR*KOvG$mBC7@SHH)R7ZeE&P?Vd;aoDvJQ=~H}2JUZo9+%aylt; zuGv_!6*sjvb88mh%iwA-W~q@`V2g-M0%b%}frtc2l8R9~?ZM+g{0Obt6<4z)ip|UN?@a7-a-HBCUBTWCeV1(<+imp~N%ayC4}n7>lXY z8p_oy>PQ^PSsc5^);bTbX?E5!U3&B_uiiTOp&$9kfBXBtgM>W4mfiaNtLl-fHm1dF zznSdnW?p-Xi2$#GX>qy_7%n|>@h$Io=X4Gq__2?G?mzXWOF#5|e{%N_-u=zLuPA2T zai^30G|I}(%3N*K(DF)INp;8|oa$p^YN@={ZHT2UZPWOILWmk8z41+Bn-ZW=!D&H6 zzP1qw$!=kqB6uNWm=_=WH$U_BPyLEKjUIdAQACV{xcl<8fBg^t$D+7j8mH?KI!LaqEQ_u7At7eZvp_tM9*m>wcnJANZ*czvb;uf=d7RfA=RF zXFb4A|LjNq$-n$=keP^Aj)&o)zRGg=o`3bP|C>Mh=YITWZm5lDb?dwdkWlr_-~4X1 z(*4M1UYI)WruxDoJAd%aPo)6kx&KRl;cwkNIDP7EZ?^zH{(+C~?H=|w4;Y}=?*KSA z8Q~_^^CpN&b_ghLC_0=jMziX&?u1~x!8zA}K&^>X@ZbtpGzMUlw>#~=%Gz1lN=;?z zqBK>VW%+iV?@XF%))=oE%w1!{bgnTUv{oK}+j{}zi$DFNetamj0Am338-(?L3%pj^ zGFJdG^e%5+eZNJ#bF>SSn^Ck}*#flA=?Xi}|U;x{2yp zFcw_}W*(Xen=)8~?1{Mj~{+s{mKmTq2*{@&UTD^0}e9N`paAV&cpC13@2Vc3lw?CimI(NFUw(|Bz z*FSu3a$28u;$r9YB#l>4BUeshd#_t=UD;UAy2E?NSaDl-OXEsr;L=23f~`$6hcJ(t zC|HRRG%ko>8{>lYOo@uKy8iS}f96Bi{_Rt5ee>nVu3Gdjzx2Y#e(GoTuHWco`N?D$ z_D3R)Kk?%q`qali@t6MS|1j8C{mjQc@h!jZ*Fyy#_~D<5DR*x1Ge7&;?>cQRti;X( zN%b$j=STj)AN`Z#BLm6KtZ4s>@BY|R|Mj;d8eVzn#m|1~li9|TI%)sZM?Ur~Z+X9i zhUw}&75`19|5*VAA1RbTbJ-~Z|0YvRhedF03wH7I8;+}%ICaxw08TV^q@D2kb4 zUn_|Pt5@%pue^E$qdAu&m9zvBPy#XumO^MqdTOOAPSUia<3vUhC7(qnlamC1#Kt#g zW*03bNp&<#hI1E>CP`lQI$1BzTKx>H2ZVF0t+KA>v+@Ab%4$;{<8T;x9~!^XA3XNf z_bnESJ0JWJ@5V|6>))ub{_lZIteGllRc|9(ztmv&WI7CsvcI_fAPP9@>%lon+bp4# z;+1px+U08Mnip@twY#z|YhR7@Vj(JPP0d`f8GAbiSAk>a5ds0#fe2rZ&J|3{+)EJy zH;lvx4_j{eSk||KeYNe|dTm=e_C3{Lw%BKmE4f`m3_61?Z}J z8reBC66d74d7O6<{Jn$S+c#+aZEwnTKH>_QB6doMkr8+HX9ov!0E$$+JdZv?N`%OO z1$xM}s#>XzQ#6qXnKeasZv&=#g;wM)c@L z7uUANrv1$?K7ak*?lH_P%obFa!4;JqW4#ErWK)7I1UmtNm>mZe2p|G2`xsIrkiY^! z5;}~Mk(>}gN=jpy=TQ>7BmxOuQz!F@n1U|@$$JZE7b{O*wBy6W-Niaw?JwjjetZY* z(1t{79h3CVaque2A#Pz5QzvJgHilYhHt0m)PSSRhcX3XI^s?1N^BOt{f^B4gT1yXb z^Tw^?*RH+iJ@0<+TfRo1{>hJj==SNJ%-6o<-CN)MO_xuPj@BrlI2@nsL8&b5KJn(K ze#LjZ55fKL5B%F-_g%l$`$WhbCU<_{ANtnc^E-a+U;4}6_c#9bkLQAa?YF%>5yjU( zmNj~_YBpz&o%=oC@C}#O*MH~l_?-`b(^tQ^`@%}EKb)NW(Dje3R%vWk>msbAo6f}K zT}woU>M5HORkwwSYd>$S5UTWIw5Xyep8EN0K6~@#<*TiggZ{}2_g;3&3qcBm=D6GK ze$zv5x_)^76SrUL`_5{-vD4oYg{#FZ&8tsee_>Rahtn18ZbKFC?l&jTeYEnoKxH61 zAah9iCe1>W&e8tFCx!q+APFlQnzD_gXDR<1A9z*W`Nv&d_bxud`NM~&F#W>rCx7}g zjvHW#I{DU0+TOZaWnX=8T8Zc;j&JL3|C3)BfBd)qIlvm?4tg)^N@Iu97Wy)jb)NT} z-+A$tU)da;+roOLMRU5|A}jlMZi~v~qM7)U=Nm3H!~&Ro2#z6=L5W2oG6iX@qErSH zApkoIEIBx$x%3gC0ElJqF<_#-B4#nw8CD*vYA~G6r=kRI@?_=Se%L$NedO`ZqnGnw z@8vcg$>h#nCwC6&5Y@$OaoApqE$5R9(Vg~RG5c=NjiH=_Yrs|zYCr}eBvecW6p#iP zgNT?SN0CsPL}b$r3IZiikc=YrK(|VD94C}YNwI=RNQDfjBomw1*Na?5t9><@yGF-S zTxuri>~vq6+5!ef6biIfSxe>}(3+GN!liMV#b}#Fgl47F8FbpBo-C?D#htvhH7WVv z_Pr|`-UA@O3t#wbuap1J|Koq(Yiq~wqd)qi*4jV$-~4A^`;~7!KG;7xI$B>{`SBn5 zv48zN->aj@m}qvoDCbQl%kSRa_kkEBlKRT8ed{0nL;p>$rQZIwxBQ*I|HE&4*He!_ zdC4@z_x;#U{q?`_H@@<1@7}%r>Tosx^Z(>8Km7PJKlp<`{?t!SXj{-^)x(`tHSl_Q8+sAM`k1iF(robXprzvk)P~ zA@MAj5>OfHJV1(^#8Qd1*usdk)#*yyxd^Qlp=?iGUTeQ|b2T&Z;NUbP3o((9xUd!I zxVP5bI={Jo;qpYRx^6QQ+Sr2q1RgCGvqcG^0k8ne_wx>)>YLQqQZ8Gr%d49rXr zq*M|GDJ`T1YJ#z@F@ftFcdF5Bcz$QFwY{oR!$(ett%KeBjSoc~#^YvlqqB4Ip?mqK z7UM%W3-(qKDe0W!#&`ro!SEjn0e*hqFVU7zMIL~_#{v|P@xn163qX~edr!9h?pblq z4_^?|o8X;MD#EsiTco;Lt?5`Ny+z#FD5}ogJJZwSvYt0oS6q%mc>-nx^%Uv~f`MQk zT!<_Mk_0J1bVz9#XCUGrVpNIHF-ctuts|x5NJdg>A*9riBuQP3N{L9Jk|;$$1zItO zrk*TXz4*e0X7&f;FiTo$(6+rbJiPCX6+-eX-e3E}vU# zCu%xtT3LJI>H59Nox66iH-GOlF2I6(w!N|X{onJi9)0*BAK;Jt;s5U6{NRuL_TT>7 zf8Do!qljW~t<9~i@A=-J_(T8opRjctC0VNFy*u~*>Rz_FBuNq>Ye6kYBN-xyeZz~|wlSa&O2{DO zcrlyW8b$lwV!BcKG|4x+*>G`^rD}69hy$**x|5>r%e=GNx|pn0i&`xQ6PD`ni-+aC z)2I3m?c}RBeX1yeIAe;FaISXFBTVl-YR4wVx6?ME?-U` zdg!5R2W34zrUVd|xy!DSNn5UWyO%aEJa$X^8g+4{~d;25RQq6}&u>3+wjw#^*LW?KKEBkrYjUNm0(K!uv{a5dgqh6b`*-@4O>oilvC6NGSzG z%Yj7`tPzA#ATxc5u$F)`2=bAR>zbYS)&~(d*kGJVd)O55@Ki|IoVzFG2|=<2i_BsAYpv~WcUvP#Q#6jutomB)4H+SptN!`pH)|Si+n^P>0 zgBgQcNCswy-~u=X!EkoQfxxI2C7Dh$)G6o~qfEsqDvgm{=5T8rNwrMAI`erd7@pNz zT8mgyq(u}fttroXk%Y}2#X3&o#jdC;nowUha55dwI|+B8nE)Qkf1s2yv{G$R+S z)L%NkvbGjkH#R7XO1^Thx;e7*Ik=(@rV-Fc%>Kw9_;0jUhr`AH{J;E}zx}uWZq{4* zj_>>}T1LP$I$8YFzws~r#^3qJ^BJXUkCn%#07HQA*Z$gHL8||!|K(5pj^Fd!|NcM! z*JT6mf8UerYg4=L|DNxLsCoB$o&bP<^)G&SHk?AM?V{G#zxAuX<-P9#53Q{C;~)Ic z-~OZj{l`E51s`NbwMC@o^`hJB`LY?;^R`q`h;yBRR)QouUerAF4v{$584Of<&7f3<@U|=8*Y}ug#-6E|)cUeXac+ECaqQAb{+j*=y-YtqF>DYMT zu!SA=V|#96Nw4MVVk493AS_(JHMWX7@uBJmV6qh})<8w3XDP17K#5X8|*b#zj9 z`;pQTglG&npzz>5O34*)#KDK)>XQ#KZ(ut@jROafc99PERXzn#8daz;l_l>Iq5Mf~N z8Jxyc2yI;h$Zv@5OJIO63yl#(5~XDuKtR@ycP_WqHs!-_p_8P%^_oAu4!-bSfDejm zNZS;(Sf^2v4A%Afxi-bENKp_P)7qO>ceR7xx(us~^{ltSdPNg5xL1kbPK zolJIPaXhktc%imv2-zcey5c zuy?I_?c>F9KjrgG7*PH2kA3h@{`Y_SmFu_T_O=ab@3@AC?DNk*|7ZT{-+A%cu8gr4 z_a1rpX$0|}r_a6j-EZv=qKB?*GdY!tjqSn7sK~RNfM?_3h4VY@&DQzz>lpZxAN>qW zik;2vXLlZbGTVj;fcF3NpZ~+Z@K^up^yaRTdbPj$6_34R`trfO@vg2#ztb;$r6F!u zNK!&e@FI9ef{fwuyudVZlG0XOnPzwYrp{C?HaFTGF6*-4@vIT?tSurHf&*|(W4%#~ zB7hVEm1eDPPwNJ$MXV606*=QTr#kqO3r~)N_f-LeKrs`zfFeXvNG%gZN=OjWX<-xO zK`uRt$;?5~L||RDFijIl)zYyg#m=s#VO&}Q4$cspz)c8o078rdCP*3)37MS-XM;5+ zKoUz5$-FEM4$Jd9Nk2(|UDGsYCtQFvXWbklygq9dB9OpkdfJx=>kMc4+TL>r6hc5I z{@`F7@6gQP#@jpr^ZS6)7B~suRc7@Nwy83z{yhah6CB68MILO{vKp z$`poWT{rQkZx8oxalMF&#Zhzn`IT<`^h1w>kN?&8{NVrg5C8E;Kk>OHXy(L1vc7Zq z2Y&n$-~Rqz`S>%>{BM8nZ{9sTIvmbfcMeV#Y2JTib-p4|EHr#|<|PkiFlS8sjf z!ymtV^)Va7e74xRxc#sH^}qhT|LuQqZe=GWJifczap9X==YHcu@1L6a^FQ_3r@r$o zzv?&t#$WfH-!(g#+}hpkr2S9+@P~fl#qWP;``k*}@y;5o4PzAqI3XHj3_5U5VpO}J zW1)0ePrB=!)z0?3*gZYnYqGd@uCH?R(eAaqgZoEMT-X5+Ax@-9k+`WV+camt;Ze6$ z&+Oj(_*|aKs+v!HJ6oLrvXD}Eu*NkD_7;T_Q9!9YN#zz2I~oNooxYk}LYyM5_S9)v z%?g(wx44=4ia11qlz_9Bj;`jloFd_^SwuXqya8&w_b3Ac5`zGwfaopy;B4hX2yu== zT2F_g#mOY=#yt(}n@TVd5uij70Z1mrLI+YpXrUve6OhsW=?EWw{Y(JL!5{-lS)DeR$|Nu2+9X+ELV+hYGbXp1vgE@K+IfQ8v-Dr3+!N? zW-^XJqG_eLxz^iWAFQnOTX0&LZ2xd}bXs@^5+I60JB_n0wsW=8YbQx$EFX>B(J4;~ z*xQ9>YRq_lc<(tV$DQuZM?U=g_x{75{g?mhpUlQn(OTuXr}d4ryK%apANaA4fBW92 zzxf-#y4#M5#dP=Z=(W2iFWx#H6;>{q#pHN$dImH{LlZJ@BiWd^7s7C82Y>C4{ZAX8eCmm}KHV4b!NI}j zKmYvRYrFNW)Ayf$(?cugGL_fPzr1%>>XuRzNTB0jP2xGy+F>ly$WidYV9K3?c#nYDb06;`2B?1#NGygnng&;)$^o_OF2jhdS zn#foWnwyc*Nr1TaEHbYmVNG;;B+oz8WNp@KdR+TyXc`t2r5leto5u0umH`9&2Lk?kT1)0%q8e7+%pvYTdw|``t&J;5d&~M{IGMVG`>;3wQ3Mv+HiF7V ztW;t(lY&&-?X_0cM4aixOdcOkZBzPYds=V1me-b>CHRSlUZ~! zjrWe~*#vlUz|(7qJJwO>_N&K#d-r=!Z~Zv9Mc&_BOpRVYZ@gR#%Xn>PQPYon;O-B9 z|DOe(r4f{-?wq@tu3i<{hQSj{P24`$fX=n97B*}3ILJTy=l||M{)c~Uc6w(z4oSZD z8-LAjjcw^i^DCFP;+6Eo&mSB-QC|A7@A=7p^>_c?xGGB5to7H|WczKKkDlJ&+nZw| zvda5OeX4RwMZR?Jv-OsnCJhcnYKxN4bvmt9qFp`R=%gFn3mFkFMmon?`w9_>k0 ztjFo`?L9l_M(qrhAgM(N&R8GJ`*$uMwCkU}{po~@b;LP{djw;usjNd$Wz3ycuA*!l zRN(~&;Us$!EMriqBVy+h7D~0eu*b7Vj3K;ESb}g#SpMIosxLjrvVUFK569VayY%v%_;lJaRbfWs`goX( zUNO#2=LLk=LnTE~l%;4t?(J#e1htf_5da8%I6BlqnsmUr21-hsL>sL}EmEpFvZXJs zPm9H@SWs2eixT3wsZAW%=JR_a3HA!~j1#ot^G8Ehi}EpkW>s{Wbq}F=Wc#sT(hKpu zd(}~Gs}0I`(!q*cE!NCo!0m3{W%ZqK37jPgQPSFdCv=_rp-yV**Vb!?i> z7jacpCiZSMQB9+*(Pf^TQ^mZKmkVy@QJ=hp+JbR5Odv3Z4tfc!8PSqK@<9>?C9S3s z04s{6N4fB_U$0!dw^-Ru(kw)B8j{>50~QxmIKmJCAPFF1sZm8_!T6A&L4d$#KmsHt z5~P|?DzpMfiBt(eT=%=`{Fc}qYj0K|fOMx(WMfkH0X42+2*H$L=F(WlDz-!gRy=Ga zEq8v$UB0UI(cbBF?(}*Yy3f6K^Xhu*>XTnlot)nL)K61j2`DJ4*a0x0c)c7#4;&zP z6axPJVCJ8{h(i4N9a~=pzWki5|F{(vf*|P_pm89?SvVd;2(BmA&Uf=H*g9$Tqa?5A z<9f2kcHv!##tI~mkz3BoiBvnuR@U_T`CO;nu+t#~rbNao zD(Yn|f~=zkYf_}0NcUS3b*0r2WwZ9mmdI9yb2{0p=0iI^d72 zt!8T*vxw_FcHM26T8bBPH1_7irBS8Jifi4-Jn6ff=c@FP?aiLr9`vpbHU_G- zIGu@-FZZ`QYn{O;pVf5>B2oEyRe{ivR02pTRj`tPkq`mnEa|W1l(Ncv!$Q1#+a+Sx&22vR=(BL!f|?2n7%@kc@Qe;jKqH#lgaj z-~5EgpGt1dhUbd!nqAw4-BUk0l~8KI9rBHLZ=QW_9ROozq_s+B~%*J-Svvp-<0C%I{-K=b~S8nV^m)9>m z_O_FQ!}{JegN=j*upprVdjKLq!8v5sIyOGMv6}M$0iBRBG#(&GmV$x_)+53CJ3IYL z3Yn(+422}KVA6a)8^z< z=mQRcn296-E}vV1h#D@@D+~-81tJNBz{}Vy1ppy<0Q3$l1|;tT`mR2i)w_G6EbF$~ zYFZSN1sxm}&!5O@x|r?{r}uA`N3X)<9yFB-!p1vM-j*^(p}eV_G0UN6Lpnx4U_c;- zfb4wm0cb?X%^YC1wytJ}r5~-!s1-S&@o_|wy|;yPHT$3d1UNFi_DH6{4!ns)d_nae zqwYnFH_j<-vAlPT4Xvs+WN}}VY|0T=QtH!sIGiuE3JLMF9D5PFmXij0Nv39{15QLs z*Iqdhv|_}qtya{Bc|G+Fjf^<!*a*v!Z`3W6fkjd?T9Cslbo7DI3@vI}L? zezbb|d`a2djzhfwEJ1|^2}P{4L`wqV;5m4(!3WO(0Yl&*fDo90J-+@5j==K&=)&(4Psh=>7~AA$r3 z3{Ec7NF@bD7;B|t88CzpOl8=y(wL^Y)k!k8RSm^L)_~TsYb=08KnuA8e}Au8%% zwDR%I+iq`fVVlz^OoH>C5J*!Tw>zy?r>)}_Vhj|io?wtk97obfoOD~N+gTAZ9haMT z?%cU{?bYGoK1`2cHiTj#z2RCCA_@&802PA(0xy`+5C$YfFF*){a5hZzo|dJ(Mj{kQ zD7@pqe%3$+crvaxXRg(6RjxUng}W!NbnD~M?)d(m-MbFcYp~cy&nRL_w~>QXN~f*5 zBsU)gX4DFU0$?D-Wyi9VReV5z#z14=a;fvXe%)hkx488)x3kfem8S30;e_yxGcV0f zZ_iIl*F>69o$Lne1VM&0M{mj3-;!=zw3J&LycHfXfYOlxJzA6o>ptaq+^QukQl~t0 zqg=p{swfL2 z>cY8(i9w)eZ$qe1KnUT%zcdC^f_!~SGWSIsLHuy<>7)C%4}Nki`(f{6x96s;Ol;GE z4RzhrQXnc%rf5Tzx!uirT-A4H-EP{sydLOKxH&EBBNHo;1VKh(DN$kICEbJojk6p8 z0wV-q{Gyr>mKQ9`Ac6R$w-dY$Vg}2uc08Wc$kc1;SQlxYP@KC036KE+F#!1h?AS{$ zmBJ;y=8b7F8!0$(X41@*Y%8f%+)CT)EB%#DlEr7{mkBhf)44Z^ znDo|NcWZ54Z@h9d+#g92e&B)Gx>1`Ny?5Mg-_z|5(KnYjJp{_(3X{@!2tj_RDL zU$NId_4)O2HdpFU>nB?I9qAA2v4=`W?pKKOT}mSr2~qOYx3kub#c19%bz`OEwJ7gKspHVO05L_~boG_%yZf^tTW3i%D0`i)q#b1m zxq6BulnP#+iq2_Mh}zCj_auS0P6(w^Y1py@PhdE3z-6uBfJ6Y8kEiKCv#+g(SZ;^$ z`n~(d94kF*9Ft*XMC=)sm9JvqWR#1h$%MeBEcT}5NXhclobJxQ_MLj+;wXkhI!_1~ zL)B`E(2f8j&&Uj>a^4B#K$RwyvnXb8MQ1 zjC0B~C4p?#Q)tDKWE#MEuB`=&J(*(Eb?*= zr$w`M{>pp5`Bzw@=0u_WQZyg^tGpoBh4x*!pPw*V2YUTI(X zit&83mc!Qh0cCXZ+Reqi7pWQokY|UWgHRqcum+uUx~}E6WvAepfC8-nQV;@ruM-i%vcm|00+S#-a~ulNDgmx% z<9S(@Rc$A8S2n5Hf0c(PqAn=}f~Cz`wo$M0*?9pfO*$(a!gMk+_1x5r#D>|2CE)`B z0xk9M>VdT;M6en8Ae6;8^FtTtsdijyNZo0@5#l2vT4 z#4GJMRmPy1ssYAVR%7TTZRLHHb)p8cQ(Hrorrc_gwA16t8bL77@w(Cqp@6WqnWxlZ zF9VsHovmgC;#!`yvqjd=Ihg7Gj3U)ukDs`_^VAbNA9`(%uFp?qdp_-gmc|)tJ!6PK zpT#r=X3xPdiNFGj&?=@))Sb3Fv7 zD28U8LpnUPhu6jaoKiaKe@Bo0ywNOIBHaBYoi{!EHIKjPiJ$)QpT70Vi|)>~#uflb z%ip+VVfaRcwFI#MK8x9O9t`L1`gB;Slyf95QfBg*)6TIq<*W##8v}VuyOz!}^~g>?T`k%z zzp}Y=FcHsv;ib=h=yUUHH*x$~@&z_?<7*~GDksdq32?QC0Lu;xP+%}iw+sduGuZ$P zAP@yDXNAOowpos*JuW2>0EI+IAuv}})dDiLHFe!IO;K`DgP%^Ru4Uk5%Na2cK-+OH zBMmyGDB~!XQs(`QX)*Ej97V|?Aag)KmJF{8EIr??r_&fzZZB1nwWL3txV@E~%k-a~ zlQ)L;x#8^A%uEA1pM=PU{0{7oV0vP!p6qYx6ud>=$hx+kR!!ZLan+2F z7vyIN(j2PeYGl|Z0u&37ShDjPlu!(kX{p4>2o*5|Tf5GuUcS^?X?5DeRNaZv8}VwD zc8ri30|`M=5lU;VGXUNPZxIyWmjFxV5(p9=+!4M6Mpz;sAPHl!m@PW}ypt;xA*F4p zA|H@(c@YAD3m^hG*L-PwcE(w9iCFtA5jye$3y3?Wmf>)&=Zn%9XPSz@1?Q~+ zZ1i+un2W9my|yH&1A?8Pv$3lu6qE7RRuhG()ZKYW*KW?9ct~7X>$hXmPK#EQ#TrFV z^atB-`Q~4_^Vn0*edxzepZ^rt5{2+K02>ta24OvbU-sJ|1fvfSKt)036PG@|lAPP> z9@pjV+t=Y_SGzg+06-9H6pC2^Y8@x-cDvVZwexs96Z?lHBVRn z5n1wLsbU5Qz#zC`$KHDv1}HqDL}-9C2`7YMBwH>Jmq~v@FT=A45tzLYWUZB1qDTbi zov}q>rZdT9{eZ$6OBRqN31n0ROIcQ_K*9k<59<1XF9y?Uf{XhIA$Sjf%u5c%2M@+h zh;^as=EI-+@aq41alLFBbL9DV#)VQD0~u6YIt` z`^Bieww0e>b7Jv@*Is-VP3%oD3b=Q`=7X%ZlS?+!ZS zwnv|wjE-kBll0evsnPk>&Zg?zwx)6hazUw7AOsTDgsN&ZVxC4a3Q}p3!ddhjg!jU;4J^F(gw9#~BF;X# zTq2G!O{7p9xFOpGMJoS0!<#;s_&i736kCl_-(_62=a2^DK z03o8_?Jrrv`m%Cu0(MbNIn-3q1|l3bGtoYu9Nk{g@kie)U+0bU&C1%V z<0!i}TifX!oaE2FP|S~x;N*k4IpsL9>`^PBGv_sMszeJxLBzhQ1anN1jq`wk6f+4w z4=k9g5Mtm3a0VD7L>ha5lD!5N%p8!HfssnqELZa>EV?l?HklMzZKr;Igk}!@nEA-t zlDLDi1yRhgkUG+FsuPvQwle^sx|7*?D7rq(e0`v(AZN&BmQyE!Xr~#k&+IFexCpLW zh6JRVp4fJ~llYyYtkYz_`)IOqp*7p>z4jSpr z7ztVu34$KRI-sC#L1Mv;;>FskzI-vs66rm*_%^h+PoNRF7rWBy_QK1gsb(}>P1j~q<~xf^59d!@ z$b_HVyLWo3x@1R+eIiiU5WHhygREZN>+UVe3zt=^FVa{@|MK@5;pfHwyFCkku}=xP1WyP;K;r;`+e+j~ss*K^)9LVF52^`s zMc|iW4iQrzDP&H%rK7ap?G0K{sAmw(RyU=B>}0Q)3{PD%0XKnW3P{0wYl8<1E;y+; zNrDtn)GZeE@zG>FmQC5%x&ewvBo1=`Ak~&h2RUX;h%x{nWaWeKP3gS%-T?rh2L|wj zi~$^w1#3J>5F#*H(I5p9B80&I4q(|1oOw$ZMY$-HH6DC$reWui0}7x(fOvM^YU2^C zkC-KREufXf?OwMoi0X5`w3bPt4??5L0NHzA%=aPkNHZjviabF|QdfTpK>HgE_SIT);{lI+pHXQ8wpla@w6qj?W=cm}q0uqZPa!#D=oxXDY;B;7b_4+)< z@wkvA`@L3YWdOl&5<~<_Ok4psO7rUKx%HJCNzN8k5=Chi=dnz*aVVS<Bi3bg>yY)Obwwff^)hF=-3ili7bLJ;Af@1b+<~6LvN5?xUj;+id;KR zZCwVEE8CmnySL`m5P(ze%)!3V5-yBZ0cvInIs_Gg2vU;_irMoLAp|7C;N^05IG)#&g>}ZWX{@Qet2sDgAVfYJKLG=2 z&jJ}_@RCiGr7LTLx|U(F-ONf18bf8v3eclQ_Ri}JqYWYos=Rr7_`)lDZ+SdHZp{s_ zl*nipoSUQfoUjt`ZNKK(JFiY(`P}gM-lDGSgV88U`p`=nM>^3c_+&hNX>b3=trO9- zdp&go))TD7X*ZRev5|l(EYBYnuU@-#>-POL-vkJanS-c|n_fzzsGAKVc>u+9dT6?7 z-%?NNayF@hZL|)kaus!hBj3!~C?*0)#Aj~ONC_c1&2$}wlUd!2PxlIJFVYR~nh>0b z;w4Rm5Q4SHq=eQAJ@DBOj~RkB7+8d$SV)u-fN|M&fM9R!e>ouSaGheo3%GK|mM)h>*?z2!X@0>t_zm+wl7Qo8maG2!VaDCRDTKPahpd z7J?+l0VKFYW0pysNUhLe)5B5H&O3uatKY4BbFzEdisjXd7m_6I=Ge=y*4o>c9g;IF zp|M$2dw~z&c#&lB>c-%a%dIk)LkHC?HbMY5gpCSHI^oDCLHNQg%F26ar?Xx!yR@@; zavO>T>(1)x`K#AI|8Xd%38h>!&>N!r8PEd65+Wrk;}Jxs)9IhvY`dmjOe-)I$cC(O z=vin4=}1LMkE4#xyIH#hY{7+Iwx%~O?q9!g_to8#y*)6e5+=YbMc1Q4T#m2NJ6~~4 zelfOMo2qVVm`q(&c~=y$m=S4^8ubcEMQKmwE3(xkouE{R$aTkiVVq~*pf8XcA`jpx zEa@d6gX3V993wb*hM1U{B!mDM`1KPAm%l~93iKpIQTx(L=Yp?_;2Q552p-r1M!Xbo z9zbPCiU8R@Xyr79h$mygd5J58v6o{IryL zBMR@m3Y4g}4nj`7G8~fxoIUnr_VC62-VOiCi}U^CV&+ehE>!N}T;zpmuHQMmwtHZl zUd>y^+etIc7jm)n2#PYPXSdn1$K?Y&dqaajj~v z+bnyr%qmi8J`Z79mL1t;&{JqQS2-mph3Bw5PG7SRbyFA<+XQtcOcPN+(&@>`)cDYE ztx)5b(EDYk7Y9UU1m|2}24D)Wnfhe$0e8UTC)y@*6V4I5oC zYiC7M0ypHWvm7XrLp2v07AB zY->D+s{e`UXq|b>)op9ET7GPi#u47sQ03jmh%-!6e2w)_JP3j3S|wEQc*oHCQg# z%(+1f0oVZ>h7^GioM3Wb!6VuRnL%4*L9i6NmZ~ix0xg>e_QXNTXlBT<3ce0?4X$}` z`6dLvq(WHQxWw6zI|MMs)pZ?n9w$+^mz=n5Z>>K>upVM`Pz6^-LbhDJs9oA>I=wU# zX$mXtcx^PEb%gXwr+zLX1pqdP#tXK!tO7g4w$h}cz@n;LX=^vcl9im7v%7bPv#A}d zuI5oDdX!x3_tyKlO`#+yAc)#|h`NJ~-b%Hoj1TptE00{bm?F(;KaZpI;?~O7 zz2_afcbaS04i1_ovASPmk;?#8Oi3r}MWIHX*_^1h0sPs3!h0)-BB=)}J%f$XDN-$i zh`eSW(4kT)hzEB>v{7uW_1-p3Q#T=K1^^*6EWHTC;jG><=n(*yF0bVcSdd4ItLXlt z4_|uX?Mk<;mY5FK^Gs%Wkg^f%T3W6QI_-A5lcA^N;BKw;?_5fL^v zun$=jA@X=Ulxo!Jv@UMZ^aMvIvu?ie&@*58;=yh?y_ZQ1;SIt%1IB>9@D89QFFg9l zJKucqu~iA<8a5hd!PU+gU;^C*h=O2A1`Gk%vNhnW^EHPUP_ql6DZp0%z%qr1KuM5-B`sr%P^Xxr zR5!UO+L)wJN?;Do0NcO~fMqyaLvz3Yywsr}(Amo`GJ!kO9s{1eNQGtmc_1PO%7S(- zfT=M!TpEua+|Pgjgy;>**auNts4OSeMzI_8)CsI44295v5N07%jWVL2w;ze^T+HJH z+ER6tz8bgId?NJW%3_67)NlcI!N?E=R8UuDt$lufx4!w(@b;b4;b_!=mr+|Zy@O^l zoX?8~tJaX{PQprABiKLOU3qfn;^pmiho(RmwexCLUAueN@0a6owI~|T;IR?XWf_NH zBa%9zC~fEIx^aiE-QTT6W0PhP>SlVFalYN&Ac+BeBqTa7gb2Y)DXn+L7($FlN-4Wc z0&Af=WnC?1^H!D&veY``0tgp`5D^K~f?0VLxj1cH-B`=al{Epp7vwmQMB^PI6TLq9 zvj|2=C$P@eM{Acabk5_c=c8II96EI15f!2UQfK}KUiO1T7$A^1JN$^GA}L8rAq5fz zA1nz>l1OU}(7f)_iaM&@P@;t(Qe742ltg(%x+7v8k~nm7Ip}69{a&Z@pw_x~bUGZ5 zcMqmjgGrKVl#9mw+&|aW2JI+p4dD7}ba*Vo!lQ9cBtm$@g_N=q0EO&jS!4Ou?W3oA z>*v=}Z@oL1+ZhI@0<+}c8mF}Kfg5%hOBDHR;cwg>KK*$6q08$pn|bZ3?W<25KmD%b zPc8~yz!}~kEX0(<1R#meJ$2=+?|bT9&+c68psTNaYGy(M0tuo3U638XD2YYWUhnk> z{nhr`TGU;Oqqg3gHZQ(>dh?|lu0GXKErSQKqT*g)VInJR?&@WtcJLv1V6hZ7n1gjL zc!zaaxq1O;5ICT=XZbKFF$iKQ7-E22(zMf#%9fvH^*r)IfNLBQaV;Y$J*GX+E?g%klvS`UpwYyI-wEU<%Riy;vFnJ~sozL7`_(y%ftYSSqF zU>LYs&##`p#fNhe9 zo)q%)9~>SWRQK+e^CEaogb3iIo%^9$aP7fy61SF4XCHIe9&{hOdVc-fS{dpWZrnJW zjianRKApev{Hu>{KFp|VW79m7Bmf&BlSn}pwMS-Qd#F}7o_+R-H~%NUBGwAH`t;|& zFnsmk;4{1PdneUws3J+iV-qkR)KwKFXPOZZl5?Rf>OSe7ZYSMzhUFNiQi70xM6!15 ztq4v^k|an<5l50lUDst(TL{x?K6i~}Hm+f&io7J00K{ZDGzeBGuf->yd{gMPop9sh z+8xfL=`Q*cwAv#9N<_hg0EF;G2qGnQ97S=gw3bpX#dkvT%prBMOok+`-=D z!gjjSjn_7^{lmPPj-gpHWY9r2A$67-2AQN$!Z@1Ghxhi|tDEP}slo|k<7%PVmn2*; zL1a?KS6|3v5{ps|xFW|1rAb=SHyq+KFAcV7r03?Kv=$CC7 z8t0u20?@L9u>9PXIAbed7T}~nAQ4b|(2aGetyH4d%DeX9KAaX=IqcAMyTv{0qiVDl zBI75hTM6_d?G6vCn|G?mzh+}RDgk^z79lMU!@;YS8&0`OUU@lGuBx#@ou%@e43a`A zL@{NHh>=uDk}-QO=6NJ8tgpUyw0rkt_xAko#>xFfT}zQLB(B??&&#dt4U~3K&OMY# z8nxQ7X~rcv+GzLR`=slw*DgzC8Z+=>{@$m)67Chx|I3d&_kl0OQF~>5B?gxg-a4{n z(>Ujy_rQ$ERau{$oLkKp$z+=_Mk>WLKOe*p7WQw zd$Bx9L~AXTI`i3`t(cL3D2mcF1ps5rvQb4DWl@qvDMwKxm!XhxWRloDv?5x0l4jaE zcRC&&PTaxNP8NPrEekl1U>$j@q!w{(+3oM0tatj!s{XlKyW4^^a*cI?*lJ2J_W&3Ol*ly?O8PZhO${_hxE3m#((X)`WqOys?1{DdAX9pb*#wxO-z!IZ|Ae|BSFC4<%e=NE+G$o&vX|P=IrEw{7oz;@q28FTeG*J$JBo?TKIU zLTfywsA@U7@7g9*4a)>f3qb_^VPD;@mp6=QCZ4f1jj-uRYLK&$f60u~3 z5DAQA9o*CH;d5Pa|7bw+f)-=1Ms6_)ai&BJOu?fE1|*Fd)#8c7fOlDG42Nz*_kbio_;8j&ZmL&pqF-CY|PB zb5zF*R622KR**Vy4M{hFM!;&Gq%lfUa~h>5ub3bEvo^_SHm;z-c9NhKCr4&7IYz{x z^>G}x)IfkhW0tOR1fOmM4?;RA8|M~vW!Tr)?2dL{8{XGW7KK^pmdlkEQRdps6h9$f zc)FaQQ zg{c~9C6pv!j6yWlMZMH5#uw1XiFx|l-gWHC;jMf3Z;mH>^WYG$&`?()zutXl`1n^` znT5fQ9|aiCGnn4*6q9K+f!qe8NG`+nWQNpcIP3jgrdrDl8zkYS@)V3_(TQ@00}Ln3 zqmAwLh1YkEEJxJo75#jXM%1qFoH!TkRdVYxVQO@(Z9h;+18_~2Xs%<`*m7n|== zqJ8WB{dwiiJ=Cp(e&w~pX4ea`8n3j#PJ=gtypy*3X{)<_RjjV}NL|y_QNGXL74;}@Nh#)mB)fYzmKb>yEgh&stoSQ>f;!7tsEd^Q$0B17rmp&pa z|49JLw}vwn%X{vPok{9RGR@2S{Lx|W#{H%|O4e2|ZDA^cMd3qi0tcvx+aXs<#h}SE zq5_Ne?;Y>mJz6x=;5d<4FC8Q@@dkngA`}Q>SqS3tQ$6c{SfD_VTFa$~?3{B=V;eJ@ zj1x^Q5K=@I4A5dR0$>**yi&6@Tlx(H#ayUs6xeN1m{jOgdzw5Dw zTFEQ_@<$feet2hNB~|(H;%IkvP~>v76TjRoR&@04!SU5KP6m`JyDlA=%mq!ei_bxe_BL9o&5Btn&ibyeUB26_KdL}@2W+7U=F-Z>kF zML3=`wlt%8b2K!Q5{wmy7zvgHGLo<~csO>9yzCDIu*{NpbkY>7Jm|yP01n3k)|<20 z9dDdPgA#$jNoNEK?@DL2;3&xZyQfzlY7P2&@3;sLq9Sc$Lg0Xik_3VR01g~H+Qw@s zPEKdGDf3pE=lQJUbLTdr_kGRhKJXK^7)Ltsref~TCxu>&eedF@9j`xlyQ4^dYrxKM%S5QrnfWd>q28@wSTVMFChwHd37? zja9_V)_bX>(7JZc)J@|s)~SfH2H3k0$w)~J0o&3@DHV#P_!iC>8v|=4F@Up{q==YU z=vJEUO{a5ca%_u3qSBZKlu2$%YXT6{vH5*QM5KEE=!(Cat0>l zt#{4n>EHG3@vnGuLvZtBU-+|s_iyYR7tgLgeyP)4%h%Ud;`O}cSG$L1oJO(j^>0>_ z$^C^o7>fnVsJ{p$q6Sn*lJRWRD^N%xhDeE63mJz1!2?Pl;T%>})twc&wYeEWdT_iL z&tbgaq!Ta3r7@IR|nycmvV!34FMkdnYa~ zsVQO(7}z2TYXBLE$OVj4Ynf40os3FUNs>gtPX+L$XWubgGB9PI`)EPKsS>k~HZE||=$jy%+OqGza-ZC-*&^82As@L!5?XHwD zpa1y(2yOAb|LnW}+28-imy*>b2Pk9`f!4FmbWw!>Eh(p`L)mLzeAlCO4xjj*fBSQ$! z0mLXkNGT*@8k1HeWh`Z!P^_#{mXwpiZ(g|2U0XYu7Pk+_vxY6gVm`u}!aVr>x~`jY zI|z@^AOb503N!ac@gc- zTGSZ!fDnLiDWrR2F*J1)lag5s?ft#uc3)h+(3up&Zm#A{$265So=reD!3il)DONgK z6ipn-IL^yDL@5pW?cwlrA@ir+{WV#u_wvU+1V_68f|L}T4fsoxu(Z()WU#U^c=XK= zzw2!mp4^$v*oa&2p{d(%wEb*xP<&qz2fVm z@pE68j1Q~n@q+Cb)C^q>v?}$s)APXKtc_ZowXH3wa6GvKlLN37f+r#XVw9vKoun#C zRHPB2YBs8-LvXc8v^(7$9&69>IgN0=;OOsSSllt88Z| zww_+>rnbo(QY3s^dl154yCJWe%9a*wNVsz5WOC||`+2XUTZZTC8uS4jMKVN5mdS*g zfXKvvOZ&AHN(!-5iz_KaqN6lUfQ-Iw3@L%}bljpCkwc8Q4TS*s%o_TA@rIo!Z#7^8Q zU~lKv@DZEqd;pt3WWVDR=i`4oHv99EoCAmhNFoV@Ac&+OrInT<%Y_h9xL8pvfbQn%5z5o1I4)pxALn-g-37*JSOWn?;w;H_L6YjnSRL8Bfj=dM08)XDehy zWn%$JoXv~r;oM=w8gex)f+ZQTlNd_ZD;y@g;5E_m65;ETo!9nTiE*0ghO1$^P}~Mz2_yL%nOYi#pz%*I=4#axAVbzK5fDauTGzTWxqadOl`TIgIfSuo#jGy zEM+2R$qsyI^;>zKFQ%vE_z3DDHVsOFB-}CsUPOtE6RA}IC}z#%WDLa&f|IC&hz*7W z#RDiQq(re~6NIIbWr-f#za-`n5dyie?A`v|=^o+h%2x;w0xv=TPI<-bhzJ?KR9-Dv zjDZ;ZlDq&tGlNG47pj#7CPI%BS~LJhX4sBTTJgrl#a2;=YOcNY96(~EM8vX|p$V1< zWunjG zugJ5f++q$IR0L5wQ=RX+VISX*^Tl+rGMwR}HnAiQ<=vB^1p!h582dH9{F_)(0q*Y2 zyZ`W?{L{nT{qxD%(>o7c=&v~rr>>T3nd+zQG&9F#aWE;-Klbcn5aS2_#rHh_@lPlH z_9s93k@?=~&)#~jE{-3{B7wYnde^0puB98>t0~f}pMNC|2{dwC-1@Hn=D(^|$N_xx zdw%eH{?^}D28^>$iM0zp>&tj5VVH`A!Uz{gro-d@2&UGJ)a)y>;+vm&-`I#R%x1s; z#rw3(+WKiN?zp&&E|Gz&|k^67FDR+V((~j zpZZM+<;YC6A9-AuCcvEh+!YnL0+&L*aZNBawR*bMR>A`k2$Td8gC>q8CL*l#;+4&I zE#+inwUFzby4YY_#?7L)7#F@Y-Ue9C6oPngYgpFWF37gh*1^%F)0tnrcy+ROG_Iks z5TQ`=?8`g*v3n#FCrMRRjb|BfJe{rd<5r@b)~98u+wIFwztuPOXMXaB>*0M=^h;O6 zdi_fJBUd0G`8{ z^ezxVkR-u~Ap~0XhTy#lOn~Bx>(Gewe>y}H5CNH%25dTGy1?K~U}?GZ6hP=;y`Oms z*>m}$gScL;hV9v5z8L4qfL1mNdFUz?FYT%x?5r!hARuZaIKfUbF(C*g(x{Wlwsa9v zc%7#L20{RK-Z}53LeGqH8G>@=wnvP!)RlWp zP@7Rl((&k?X)+sXBq?J8?+`@r=8=al{jGock3aoWAN}Y5%ikHK9rkcAowVPyv;Ou+ z)*reA6y5oekGyo_UUF_Nd*-UE>wo>X{$4lD1E>#t_xJsTgZnSe`=?`efWdF^`{b_pqG!l|B3!PA8RBgVE13U{;qHRTBXxVR~~xiF1C&e zy(prHjFc9Y2N#@eR$GHf7DlEzc62b;XAZ(fnMTjZ0rhT|qZ*=EZwz4}W3aor%BQ2MNmctM%19&ZE(yxOZ~8-O8^#`KDrW`pQrJ2%`hwUz&uKzvpdnc4gTa zlr5yus65?04#fljSVfjPweB@CGeAiaU2Nq~Jyd6d_T3@Acw>Cy_GEfoMgWm-BJI;S z%hR?}nHQ0Z81f)8Mi*&tv68{d{k@aX@lhxy!qoyJLg_&ONFc!gF8E+;y9j0;%;^Zc zk7B`$%e{Jm&eOjGCInza%=649u~Y(Z*|a$a=p0L-hyi&C_+kx3LZFlm@byuk_ZR~6 zmn>l6|KPVedki1|!`WNDB-JA$<0y3?3qk`JI|%) z{C3^TlLxN}WmB*ZiA+#Z)6~{#!l0s9ASN6SI_r7V=Q%fSDq*Smpg1GVrDlf~0xX4C zb`F+s&XE+Q2z4T)S8QNTyoYAbm(w!++ZW;Krnx$z$GYd!O4{;HgZ@;7ephp%D==+f zK$y*j!^ylU>T{PLd*8QweRF;Isek!zqpOcxdfO9&U-j;>oE>Rc*ZA>QUVQHJpZ%Jr zzq8ixna_Ui=+tFu|e`WjGO9y;1i;Fw{ z?(J~zcmMj|_1?F?U!HIKUMv9Qy!@Si;15{zsG`xm<2!%vd+%I(b#NS#_DVF1SvWqY>%g-fV!#xf#Yb-Vc6>W^Ya^NFYE3M`a5eYn`_bFl1oQ>_sb;w!*aebreJ0; zO;9NcREeTAkECj)iPAw6wNqXjB!f;`mdCg5>BEH-*i@$@SzO$?wDs&0P{wQCcsDo3 z7Ork^$v%NuX4=^%02ao#qkg%l?_9t6wr4ln+`89thrN8~U>u(9+qXY!$tyPEd|oVrM{_(;nDHk*N$&p^T&J8R4m#) z4okDLS|-6OVQQESSo z7Ys;UgK#b=NwKpISQ4@H1So(dqheAa2!WCq$r+MbF)tgvAevew?1AeLN_Ig=WCy-B zNvh@=D^bUS5dkDIk$_-{79h1kA+Z5QVhYDlB%@cNMY7j#?+?zOOFGXS9-N;Yv~?L$ zCa`W|<2dTIHfOU%Udz6SCvtk|c+R|NjFeJ?woAiLlPc-3#gY(8-z>m^!X%65#>efn zNE4~UDc)mKfJ-bqr^OJScBrFy+M`~*; zzoG*L#{F0C{q6tdufP2K_4{{jeZ`xe`mg@=U(W~Y`+oSL^2S$x{eL?6-@Nasx3!bCzxI3n^yqN$=={t!()~IR2lxkwQIYzg_RAG5l6Z{dsWejm13<_ zD<3H8MyF3b(%aa`Z|&Qc@A5&JEm+2*h4<*31r9{Eaex?&k9nBn?U~MAp0{rwTzPoq z{cn9_b0z)BpSga&{X>maM|%`+OY62RYASS|w3FQNy0-TTh9~ns z=Wb8$O_137IRx75Zfy29*9Lw*KN(+tZ9bdWsw56^q+=bOEM#4k<%2^6$576|)hN6G za43O^mt_%H!^~(c5!G(todpme6D=bl1R()YoFyI^0F+WXl3FY9zyOh^urMJwK=i?} zGr+=o0#LXF;qs#(hBLukDEK1y-+>FS+q)#fS%&x7Mzr-tKo9~zF%W>Y9s*d8Q9?rS zvWyGhd_eZdU=fx>>5;Rn7P0Yt5~_Wn5FQz|WDd*nN+l}Wh|{g4H*4}0J3ApW3^QT4 znHNTr6!9R*wdDvAm2@g7TbDnF#V}@R(|Bxr7HB)^8xNlx9(`l4JNy6QyZ_~TzTy4v`j+>DfGdwZ1m6GPzxe*Y``7>G=Ki_bnhE2f|Q>}PK7-@dqd?)UwP|5~oK!f^a;-~2188@qq}*Zr2;pL%X*u=;2I zli&aFqmTTmKlfkkY@NIInJ@gCfA-xke(JL~U%Up5ZD;wWPR>beSE^NNkZ5uXE1cvx5D;Lh4`=)QW^n>R1sCvk7yC@yUoUC0K zthL%JS-V{g2A$Qd6^i6^QSRQWM^iJI*wOgbVo?!Ft&~$NJe-^qx00j5diVTRIxJ?> zj+mEGIV)n+E*NMUTh;=ikjTJDgthYrqtTTMd8eD{vZ;#7TjSAVB1sD0P?ofmPP?si z#Pg7**L@p-};xt@w%dmA!Hyf90}%n*&kUyr zC7CIZ(^_qAT)42YgT~zX==bg2yFWZU1Y;n0@E(XjN0jUYXTUaq3<8A|OD_SV%)Z33 zz&;oUP(qff7L|2)Z_Q?ZZ6#UeHf+ZNkX7qrb&tko7!7TkY!n%%YIDqE{Ibl>RTb{n}6fx z{X2j7TmDB*p|)8nkwdi0%7f(o&U|H;4p zM@QA^`=0%pCzvHW8Fp;sU<8~dT3{Fxv4Xa9;v zkJpd94se~k@{nE&Qqy%Xq zNl42>1#rF3Ya46FRe1H*>HdMM7bMV@vqM<;umliFDM3qAYAMxsDsKoxEc>Hb@zRTX z&nW-&qbsBN)=!mhov0JwaT@FM=hp_S>FP>$`C`X-$kIUEkRx8%y8 z-I+}0hmEbVaU85qVkRjg6{EmTJ0jnh1@(G~x5ipNgK@Sop(f%pfp>XYU}K?euwO&rz48P*JROjw13PK#))p6i1QPT86+x zBpBG+K|5);T=0gOrH(90L?MtQ2z%yzK;$n1em?LQVVONJ2Ct(?D?;>0#6p1-L2xi0 ztcBpWWwH}zQg{PGK7b;rg-}F9OR*`J-4SwB;JcdmD#WZJy|PN(jr*f}iB3j~#k{Jl zcCi;4NeGwe)C8d--OD;18Apz+We2cMGLGY*m9b&caH>>4&ig8zqH*J~BpTJlhj(xP z*qxi#L-6f3G(sm`&)S<%<_Ks++4NQXRU+P~y{yaHS|5v$#ZV=HUZMnssy5emcYpiu z{oQ};fBc`~1nSxBul(Wv@q54L`|3q`baLzgUU>DzfB4t_>dPPhq>#Bp^`8u_W0(`xf`GU{6o(?+PG@kOx8BmEFd^uPW6@?_eN;wLUY z@xDt>*}KQ77;LBnQQo|Hb2^zn)>?bh%Ec8*yKyVmZIL8a$f6~a4ptG*V_pdVk-;OM zxO@NQlMy&p)D~P6M9`<0C7?h&t9t>7wZt^W?TsjIWiRfIUfZ*#5UTW4kIR#N2~k+i zTS*8Xya$AUMC3831S(&kZbfPTy?;vH|ga_h$9U%-QQKHgMnGYearw7S*u zX>|YY!QQ>ebZm=xC<|N6%VsubfjYDwSwe`1*J>&R5T^bdvGN7qzNt2*K2~5orqOglHlW`Yqi(cW!;9 zwSTZ%))Al(S`v|WxLDK?&C^tFUw!Q8&P|w~q5yCXgaiNv`o$xFn9=&Y#pM#P>L?~M-N`i<`pdu-xwA>RaLZuy`;lM&+q*WACWjQ$SEu!ThkexsU z5HM{KN>p(W%cK<~skMsZWF-S8ARxj>%U~8V)GPfcj>vlF0YPdY&7=T9unc@&a?fJ8tNOXh0>J)*O>bXQvf`yi#1TE|N2NJdgh zr6M9)5x93cG_F~Vxrxn5WO^#v4)N;NW!2617qk7@WKq}ix~>I`G%J8fHQ~xWBsMOr z_Z}2nCe+Tg0A)n1Xg$lcOlsgzo1&P`omqfAToj)@xp)pXFl~SzvDaK{^YZ7`^$eFoj=$cI_qzJ;rb8!!+-HZKk#F3`ueZ= zwZHbec3*mJczC+Kv$mG?|NB4u$JfN_-~8);=fgkt!S{XBdw=Wi|J}d!_x$eTJ9{{( zTT_4i$3M1zI9uyqEYD(TwBjsN-9cm+PZzYPH5Rr$I>PcK)J2Gp zh=kGtfsoEhZqIDzO_WH-<#4{}B&)G*%_fT%K0E%pjiaX@zA~yCgvE-a^&Bs44=7PT zd$ZcV-<<9@&8+ri9c+cZ)}o3y^@wWuDh5DR!wA$^d3XOPT}#hh7)+;bbi}S!NBa{F zDp=<|Xvfa_sxgUE32A13GAvsIUg@ZlOxRji2xV!!Z6Xu_bQHm4IEhrcv9S@ydbTL5 zQd;YnePb=MSK!jfcY1o`^3`l@qnMB30o;-q1cKyWJcLES0H6VdwM_tqcHY@oZ6)%g z#Bt3v*O7`ZJ#^{9m7Ph2`P`&3?Zhr?TZog_ZWo99GpI*l{*tKXt}LL@bDkGw0*hS; zGt`%a(j>HDVvj(YWTv9XLFSfwf-D3H8At(=Wz@(_XR+%9LIE-pk^odmKq+L5Iwc`d z$taDYG?Gd&p^oE3DDMkHh)=knlJJ#@WwenvtIr(FTH$o|K+=vlJ(j&-~D&~*?0cNU;Vp(%YXK-|HePv_yfPE zyPE%R|LZ^a{(t+}gmVr6*IFa$Gk1`Rd8~)f@f(z31fOaDlT~n+(ReiE|(!ECnS5 z3Iw%O9Z3*JTC@@&;_PTto*b8<;;1V8?AVqgp=kMvs3qaj$0t}2ATdHLpeag-JxZ?X znTYa;+J~op|Hi>X+gA>b?dkD+z27>wy_)2MS8olky|P%0%X;oZ?L*T@FsWjdC{squ zC$dBVo&p3Yj8R2%!fJKoHnwrSrM6a`cT`l_Lay?-4iMb(<F*PRTy zZJaJZL{VdfXQ)gQ#c@lfrXG$?$J6-&WV`ZMH?DCWh=~b61~062&Y5(u)>+>w?p}B7 z&YtK?Prd;D#X?xDfB}RCKo6D(sgrgFZ6#-oZB6W~gz0LWZm#u>b3gUrTTkvp$-2C} z)eMq0C;fXzwGRdsV>{Z@j$&Ik#gSReK?Vp?aL=pAEq}Lx6sQPf$~q1zB9#CDN+n5& zrQq$Hx7OhUh(JUTF#!+;L5wK15*P`c>7*^Am=uXbXiWj#SvH840lC=P>^%9%#_E7Z zQv#_e&M<33-t+#Lt@A;ixfu{)NmBn;;3Z55jkQ%(CBZ2rl?JV2kV<006tRketBcT7 zp($J;tqI+h5W>pH$VdyVgg)yJUn%EvU#_IF1JfzPMVXgU%vaOHy~84=tlh~$Qi$5| zz~@n;1dv1#h|Q%zx7SIWHw|$mc{Wfj3%T{RsrP4-S56M@oE}dWi-Sq^T2sEdD1alK zcF}mS6+mc|j6;Oblo+mx_&3t(d!g-lmN2r4f{K)+74$Bc&~O#1#qRufe#dVeCDUR$ zy?*D~PJaH%>P~gIx3lroxz^xKS09_#<)>eHf9KrKPfjPzG`#ctn^wl^6My#yzu^9k0F@@W_OO%oyV&~ah1$ZqGrUtVwC{|fU^Ug0|W3`a3hh9 zOjTP6t)vxsu8L~zqC|`I&Rz4a3-hOT;6V1aFSKQxytL;&`^sW+`<`oz5Gq!LG6zgJ zn1!vR)F1$r1a&6VqHFAEGPD@yd*y29L2ldTDwdWP^*|`?&7Nx-<7`n^Op&RKiF8^uGQT;_vfKHp7iYD@Eu`zlJu{PvQjxS+#vmhFHh|0wfr$eJ zOCTaaAarH?(w2$gjQ9lwfdC*h5hYQQr+G)EDM|$CQF5jdDKrXbn!1(p)rZbM`pCwj zIAkG2q@$ED$wk^SO=im?Foh77YT4`NPhQg2&)W~e5}v_1XKfQg5Cmtg`Uf}Cp0t+= z0F4q&ENm)_6N!r@D-BX}q=QyLYt~ALb?$5$8l;0gve%>ff|Bi;1|wQ@vl_gp>lI8p z5X(5$?ao4kh9Ag;D4I^H5&YCnt4#V<+-#?`uwiWGi`l)&{!0fpUq0G9DHbm_CKx56 zHIN-+JW!CD#JpgU*Qo(6JCJ{6Z~Mulr`TBObR9LQ8Vf4ufl`U`M%5?Qt+qE`9d@tZ ze$89+Q0q#ZW-Fc5D-S)okw3XkX|k|u`6gXbs++$&y*u-z7*0H^fok_m`ljti=)rz+ zx_9@6%eyl(o=i=S>E>#GMYY#aJ@dr72h$tYJ7aw>>-1F?&0R}I2}Rk=fG@|kYW3q` zTOMi`z%HCWu-E#v#40-KWH(x?i;W$Ky7T)7#lg=)vF{-+46|g+CCjYl6c7MOE{pfG zv<@LqNns(XnmGi-s%%DwI6w7>9H+$W!4r7T48Vx5pH$d1!!+7v->oN3WHzX>WY0<* z4P(N^qZd0{{efKZU$}Mj$(QZDQ_(6X3Q$UxGWMXDQp@1kpe>}<6e*CXV=1MY*=f0` z8Wp97^UXXw_0+kwjyjl>gOzU6L}4*C!8gW)k`aTcr8luog!hrD8l_~KqS7E^B0@j_ z8BFlAS-n0;gV&Q;d5#HXq;({O1HtTJIc=1Pj=>uaQI-RVWo<>T54V2dxk=@}_j3wF zn5$4*ng;Cg%3Ciz^R?C-Cg51+DC?E57xwQRqnq;_+{~5D=RehEiWS=u{4>x*eL*D!~nrU0OT{V41O!qN zm0&?h9H}@0Nb@wyvV=q+utK1gf&{uK*iP%p)@()j}DZbr2vHh|ZZNF6vemcdYA>EM#6I8^Lx_ z96EnKSxG}wFDj1^w==6k5I7Z!Vli3M$y{-0r5&?!bob=L@dTe)ZPuS@UfjEEKDm46 zqc@MopC9rFRpwS|@7aUUPNc$FaFx|smv!Cp@w$<}{Nh7j)x9F7#jy;PPNz{li1fBl zi*j;jIC5;(JKam2!OTp)a_b4Se0M%1z(+glUw`iDbE*Z_LLL|E`H3r)%-)(l{mjZE z#dLmG+@H-&FI(-B=qR}+RHt|TLbMtd{?N_#x*J6`?|{14-fFAXeA+y6q1&nbxjDisn19;#N9z67CQ?f7BGRybFrTSP1p@fn|0!akMfCx-p z31%jtRHTK9gpyI5#&IlK86f}xDMoMseUL#Y(U!++E8UIta~tcuekVaRbps%EjV;zv zXpPF~EOEVq$_+#1q^zB{kwRd@P@!rR2vo6$mB!YOn7-DJ*x;%LqN;HplirS8VuRFF9LcMB@`=0?<<3q$pd95H3~X%d7fec?^Z%i&r&>1Dk@RLQ$l`P{7953ti&8y4#NQ7v$7oL#!Rn2st# zNm|4fqD*+{O+z5G79oqudeN8a-IvZkD%%h17Q(`)%G$czp9gkz*3Qx_QDTrr0c0iw z7&FKQvFer#8}n1=%({#<3dTU)l(b3&_GOZI9SAwke5V&@;>MjL3?P=LOK2hcc{^{d z#C_`9X}fMu=M&ZVwup2<&5WmIp0%ix0X_&I%Jj-Dx%cAf;lV%qfzN&6`P0|-FX!v3 z^w1dZZK`xx%|*?b0ns>ldl>ERU!-K<^~I=OwEf-w;3XeMwN7hSCv&GN6jy?hbsRwy z3#sQ0Q|Sg>e`wOiRO~DVYwL=e8l-}z@#+X=PEiXr0cl1O%TY;XZKOIBRg3x%y>3M@ zX>y@+G94TYMTM)zH~X{2#JPe?N`;ggL8yvzFBu6zmmsZDO|T+K(_Pzl01)QYvu}R$)r%{qC)1Pt`sNp2uI@aqL3&>ck|@vz zU?AY&oIeX9`GwUIW?UB#I}&jS7Ja;Z$)>$}vLB+>)pO0woAsTLa+XB(MAftiGcWpf zzBoQO-50HMy)`X^&>^I;fGDsMftJi?&m!gmDJc*I!qQ9NnIYhE8Yu!9MqGNoB%=Tn zf)pScsg?(S$7z~IQ7om@QvDn-tq=jhA^9Ytyp_a>l!TX--k-9ruD^QIdRLjo*&vkM z+CFagHXeSMf;CmG+np=YmQ!1X(t|^wBm`+4V(6f16QogEARBK1pmB92xF+cVp>(ng zdTwM{`-|?|{pCoz1~uHSPFd5~Z{j zAVo*Ey_6A2mda5qBU;a`sa)aa$aq*xo7{CI#e^C~n=uFS0HCx?RaIo;Bn_B!k|>U2 ziOcK)(wS6|Qk^WF#+`b+kPRx9S)x`jE1a1(O~@$myutCb)%on?{-^)$_r7}L=Bm%G zbkAi*cUoCl6m?Z@%*3SewG>y1d&85Hk~nvy>cJN+lX+TvdjWJ@B%IjN7IYJ1~gEuwt~*>HTxvp0g@S zX1aCn1n39@#%UIwZLK}kTD!d%fA;iXq~**Sn3tE=Ha7aJ?^c5+Iqi2MNOD8$l}M5V zLU2p3$b!)_I3z&1H0=l>NdP(&%*#R;`JOLF0oE6Gz14jnj)#E3GlMrZdqY*-(viw~ zxt7a0Et3mP*?3a}ai&l~%Vja@AUz2Xt)ft7RyK>7zymi@t_K9C_2OL8qt+$4st0M8 zt57uNv{_WnA89U}19r-h^M=VXa_Jk(6Pz2hfI*-PT!8(4T|9m4ShVg7dw;OGIIrC5 z8c2 z4ydIoL*?svJUlgb<3-jj*4Lv)cedRJN>IH2?FoDbe=(uq=nPzZ9Q zmS#f?4*)_b?<#A3uiuJQ6>D@cq*5|V=b40HKnS*2Q~_WzcSXp~J@KZtf;%~#eBn9g z?H8A29I`;6g7?1wo$df40Fn&~x~tTRK=4{;MdZ>q^6@L(S&Efq3i94EI|?BHBF0)(LN6DI8+33ksTo?2CJw|;l6hqL}a)QQOIX4@Da+vlD?J)=`G|4Ck!2$w? zz)kKn*hr|sc-qWIi)z8fU`nL@(i9e zDkeZ|xN6MI1g%t(s#KtN!ttW?owN-`?N*b$P$fwcwA2l(V>ch4bn_qyW5sh$5tVUNSJ+e}<6hiOf^4b> zLrDk?l6O&A%@TESV)^FF zta>>q3u1)P+?!)h=e%e3!2t=(9Kh7iTs^*;T}iuXJMQ$my3km}DRsoodtU<* z2m!(U!XhjKISS8#0b1?zk92!clG7G#@1BhAUVCM8M?JE0d34adGut#&Q_+fruUy$U zuB@_+Ux}!nDV-$T-?8?7a7V$}B@GHdDL`8Ee0Dl1Q4nXj2ucW9Su3@QRHEZZC>14X zk|j~3Q8sZBC5ejSL}^f(hysH@E#>jNFlJuPn%T50=f>IqOd&Gb>ZO4bq?7_s5Gfhy z^YUcj_yGHYD1p|wtXynQPTC2*RM`sV_qr?5`AdCZ8~j+S=9T6`HTS+~AQGSmA_Z6MJPwZy-Sz3R|e6onOD7@pH;k=L6HGS!4`rQLglT_icD8ju0fcTK>0GSggIfs4H^ zjug1aj?>scrlKTvmTg()rMw?c-P~T5=~HVDZ>GK2V=v3lyC@ZN4ORxrK#nLV(85O8 zs$~$uO9DW20U!K9FNE@iW+A-KC9xr4MI@5Cv`MN&kc-BY)gqO0C2OZrX@)3`=EYt; zDYNwr)oXiK5sHAKAx}z?gK1G0W#u5mf^x0%ev1uvYq^-)gJycaSrEy~{q^bbw7t2y zXc~qGTAuSJ@_JD()@ac|-DR&aqck^|HFjdz>{jA{n**3#v6k<#vsVySerizq4 z4=ftl>|CY6g~Ciev#B9YLVy((f+=YlZN~zn2*E2-zE%`xQ(w!z@F@;YM=O_hb{^X9 zwGm_!PAa*y=&_7_V|=lYNitu=dj~T`jpWXiwe=%e23L6RJckfOu)zdml*|CZOM#ID zWY3JwVz zzU^Zl{J{K`=bSMl1q1;01S0%GtFUU-#V`RNkemJU5BEEi3Tqei*_+PH_OA@x`+L2I z&LyYCU=dMP%%jdj`+K*W!WT7iPzk?Z5@F17ZP0sF4Vl`rz3q zOCYomf>DrsP*ufw5~s0>q>5D>D;3F1)JdY_Od}~DsGPg9YU&f6n8r#D8i)cl=w?k*HM6$Py^@Q<-7jV{ zJC6wmS+dgZoH|~Y@mi~kk=S=tJ+D@>_Py!pbUr^lJ<)_R%iA2HDAjenYs?`za1BPX zm2SpfMOJn~hIDuRsb?@#9@AJMx#?4}?niN0OG!3327-udrKJW8h=G|Eq9lUA!L#@5 zIMis8Nb>_gK(fnoA(L1s=>>WvSZI3HgNpVfNW%H4@{Ahn9pG|Cg7 zq~LV`O&DAd0DT$vC?2_TT$Ldv)k=B`uo@c_QE<{0DnvR0>&NF!W5Xg_nru4#j&9|PT43A(>UB@|HhLRRUVbc#x+n7r zv`0ye_e~0JUa^5Dk~2vLSXszD9TQgIYH|WXia~*Qo@>LZVHGE}4-N6qmBLa+XadAu z)TJ9%#X&jCWg1mc%#@-GlHxp-LMS06AW7+o>dMYs!ysIPRR}=~3$kn$<#;g}kD^uv z?bWr4Q=lx1YgffGTG`sTcf1!u*jn4%$=g_!r09IRTOLHv%|`9kz1G@+=-jz`*o-G# zUj^NnYH|Zc+8{YJFu95nPMmy1e|TW3mt{c z##j)Lb>;SjtkX}dn>A+f8=v^GZ~d)%o&Gp*RyPpaZ(46XdE@va-*9Q|iSpu zD$#LE)p176f~>KoGV?h^QPqgkp?&T1pWAu(@s0Iuh;vp8DI&873N+#rn2!zQOC;>5Gepr-zf#-J@b}*o;oi{KVBm z8LDa12%w0lE@#Y~=G_2jZC$rc92j9{=!7fVo>Li>Z+hljQ{VfJue|XazwY{m+UHVX znt3rnEKqFE?SV)d)!Dv3E~P#n)M)?q$?Dd8uyPKXcR0QkMbd<)#^E)gA6i)Vb(cT; zmhYM;JJk!X(Bddh@^@5=*}OZ?d{$(>($B4gW}<@hH=u}|2VvT_)hi2`sRj;(uJuwMo9?=)FNrw2D7&J z-dexa0FeX)k3Pj#710E|S3b|BVBbI!BFdHP)?G1^duIIUFgfx1=y?9yq;2?Z;ISF_X6Tc3LNp|x#4np=RGa(i~H42sHTUJWqv-~;NKVgiq((a_$> zXuO;uYA;tIAr^Tx>1_{`_U(JiU= zCvik-fS}Q^Oe0b;S3(G<)G!JiYYgdDQ)ASb4>rvH-t8No*R5;M&C6?`bd7Cjx)={w z+zI&pg-s$U-gfE!lMmhhEx-EBGRdmsB#e_;F7mw)_Ue9sg2qt@~4iBG@O zrhN95Z#}=A;^rWnJ*|``iD7w~Xqip7)t*DBJ*L`a?ym-Fz6%S{3?u=i) zJLh;4%QS!kg*BFiF}3R!-dDU(7GouxSz4R5B4%5&tzeK>S^$DX?-TDb#JQ5ClN{>l z)SjQyMk7k!OcW1^7c!DFbC0I0Pe1dFlAr#*A2i2@Is$HvB*l!{+ZaFzS$I4FmI8W! z%T--aLPXv%fEN-7ob~YU0sRN6u)GZb0b-r^Nu|ffCx>_M7vrOxLphu!Np)}UWM!?h z*6j>e<}AICE6$bPnqVty=0%xL7f~E_I;}~FR5)lTJmiU*2z0xgzvvlOZ0L#o{iA={bGDW=}jZ_8!8GCdie z{Nzu*<4Wt6iuMm$P5*H^E>*Ocxw_`2AGLO-x>JG`87BFr!i?20V_{B*!Cpz$>c-x+ zi#NyFT1fAN@ph72KRvuTJ)BG6v}cDW2gBLD(tIN3m0llLyG5J}CJ3HFvl7vQO3%|) z*T!qrp*h8!=54Fz-~Y(=Wn2LzDr*6q6iOh2_XN;@BM=}E=`1N2LI4k;YQ__W2eple zl<^4)Dbk5?9BAy!$PQl_-+py+2L!B^y^@k%uRg!og}isVm`)eAleD0djxkizB2Tk4 zO}+QV7z(Tdt%;3JPD6ntS~B9kV! ztvk&ISKs+|M{9?7i_!g?Zt{w#jy(y`eMAKD#bZa7A4o_kl$=$CNIccjhE7yp2;+Qs zFg&__hy3TQ8A2t5LMg2`6P9g1ir@0~-M78<{(thHPPR7h<*iD%^S!hOHfq2*5FQUb zf})}FwXx;Y94+L?_>jpH)jl=j7k6L0UKc_o552nb!8mKVuo}YsPE@v_eCxyZ;_qvy zd-(h{{GlIbO6M?nQ|2D)M60*m?fCLGHycpAOtu#xFyHly)g}s6WIgfXu(4)-WxKb% zwL?+;!mUFoa_<}F#CZrT5HVQC)-elah9v?p2Vh3)L-2qo5W^Q^-{{P!<%2KFx^7&g z6RlYVinOeZ4S>!$WANg|i}Sa?8!Ju zpR#SxI$utTd2)K%N#c#wK`GaAzqnw?Lpq0rggTFC$Hzc2=4D=jOjDWawEcjtRN6&5 z+E@t>Um4_aG@8ikcdA?av--xZa&cm2yHFm0nS!e!1kVWA2VvqiH70g;DhH_4s;Rc! z=^;c9wKDmYZ~xraKK0}8f7f*5>eUcdqYKAPbGxZ$It{c;)T-vvjaR4UQg!4`?>-0_ zIhgywdF-wALa^O_E#*v3D>)fRf!t<{@r?0Lj zW$8mblg@=LvM z)%~yPCc{bE?sHJSDxeZ-lhZZy&I^S?AxRPvr64IuDuuCwVeq3&Y`*UWv z2crpyQb_i*GN$z_7qYMU=3G+o>woKq&u#9nuL&p@;NA(L2Z10x;D&4?Oa)a1!Dj4W zT;D%!UeY5eQZ4c_?UuvCy~T90y7JI!XY;`B(s<|eu0#XUN8q>6+tuzA=AEy4*uL%I zlZkzK@9r1Iv-j!jB2QW$nVpB|5y);;<0+y`qL#GX#r(AitVOEL29J*`sLd0Pr03Rq zhllrF1KiZ8v$Ce5M&}v4k;`&s>4U-7`3TVmu-1DAh$ti?fRG?OB8BDbOBYo=nKzwY z9BZkKPZQmgwsL{2Tg*&uP1>kP3S@soCQpQBLD>;fCI2&Foa$T zVceN*{XaTk*%}e@HEeAy7GZXDicJABcyGIL?#jwy|8#=QV*2>oE*!ohPF^*$*$IV; zY+y0BRX!Z*D6$v&b*Gz^TTvmlLvHPKAZJdwoOM8{7X{@}PbY1`F|NKi?rI|z zk6t{zFo=&GPd~a?v#==_ErWB-kxo({lnu3lIL7rj9jbQHTD!I=2CMB=twwyp@7rV_ z4nA|d?~40^UvSNx(k_&Oc8B9!3Oz?GJog)3Xc*h3+#6lIGkpxH8}8*Ko({AR8q;hu zvh{rAphHAio)8fL_}UO73C?8dob%qplC3z9SoY;(sACJc4N_5PB^D`ER@Qc2`@QL{ z1KM>o>16DfT~w*_k=wMUyU3M%gf{1U^=x;}NAs+c3@Gil^OV(OF<;JBWUyXY(1ZY7 zd%G}oZ5j*K1=l$12*5e!uWG5$=?S(}UOU#GTN4b-2Es_6Ki8x!ciK0G=0ct>;~m4+mF&_T6su za5OylFuWQT3wtH+6-u6tCyNw@-L#rErk7EK31WPFI#S}^6OZm(-E3XIYm%JucDiVA zJPmbSvuh&8fPvWq$NN+?`R%A{}P~W zD$rXg%K7Nd{_JG?^dOlYEZnTIwOas89Sn=i;=S=HOv{I1_MW@PNwJv4_3bbPz-*iVx1N#(--`^24C|lzw$$W<{$18f1#Xx zrX1a1tYr=&Xw$GS`b0-D?)O5Z+zO@_ZSO7f=&`w5pr6;Hxo?zE+bYGzmsIbYMK4J} z2~^}fdk#V=j06LO(jc=$IxDjn86SZ9p$mzxai)YxRd=f`Fq=FYZ+Mk%H7wlO3{g#m&i?=(XlT;**OoDH6X z_v|eMsx2XFQVEjqEIcP55U7ceZJ1S4fx^Vu@ccP`{E11_eeEOr_g{Mf#xH<7mLW#5 z#WDslCD{g{f{;jpNdyuOaOqhZkvE~9)x(>0Qz?p|o>5HHV$KHuc9IyL`tM_fr+M{JCUMwmSFYH#=YO($=f{5F%H3NrtY#|FGM-n%l-AK2&(5@3t)RNc!|~Q=bbh^cYxlS} z(5-%Zc+|{FEb8S6V>Up9j9)zS>+A;{ps~(03`~dt*pVP1fe45QoCs3SDxZ}m%c52s zs>UddK1zU$l6t-Hm1lom(((l`-99ek9utmdfK736z;OnO@{UH3O$Jt+?ELv^2x2{roA zU^x+-)pU5g*It)Nr!Rb83YXR_IhGWr*a$=CG4l_7;dE?w z_i%AZjL$o7~YXnMFl`HdzlG?Qj8_8~9U6<2(a*tt_@DxJin{7+& zMPt3wG8-)xjzfd44vr<{?UvTk8Jl7pMUhejd?q)%o?+j$H0sc`P!@-WoxA>MGXI31 z-Caq#Z`yh0(Wj``yYcatnqiWJ0ndlWyZg`mbkiG5nPTe%LFNs6AJnY5lBCkfmXr)+ z8EVsL$0?Isc7ly}jsRZ|I9tBvJ6`%uRlKx0s-?8afh)F+Hg#DknT|GA7gw(~x^w%v z-M!~;!qMlUxC7QUZXk76rUXfYAVFv$Rge;;5=-N{3qjMOnopsef?GgSy0U>#M~eT` z-#UBySL}TAuWq$6p`omuH&xVb#lFbrhwjm3{H3UPe9iiTz~J7|ZM__dA0c|&+3vmc%h zcgnfj+037PJY<`Tk|I~fBHsIzPfp%+`7_(u+y2sD9gI%bLTeS$d0m&W?NV4qb9*M4 zl*Mc~Ts*wpYo*vVQgR$pqN$ETHhFKpBojYZK%@ z@r8rC<&<#%6l)fq9oWTxbPWrDAkEsV8-Ox2O~%1E&yjA$ISkTtb>;k~x^N-co4L<^ zuDJQqshb>-KSHaCd*G+87-2{nTO1`jAZVN9Ac>=1m`S#-?LwxFkpeYgqC^^TtbDJR ztgrPb?!WTt@bfPm&FRQRUG)(j%ji}$?y z=)d{H^RIe(6yP?6M;K4b1cj3MOKLEJ~)T0zc;to6SUhh3R)Qf}J&^E)P zgAks(*|{{7)GIlFm-$Tf)P`x%Yx+P|r?)wN#jN~vNo&#CV`A$(*(kssOj4}+ovPWW zA9=^l6wE*Rmp^jvw*O3VaC8Sl? zbbNeVmpqQLldBiQ<5yRo+PU=X#qwzPRl9ZXHnqDM~>)LLIZ#q++3#gyo!QL^)qTaUw!Z z25gvbZx!GC9h-mhkKJAC$0$r;l15gMYz5sp-jfHnPv&#Fb1>dLhJ#9e`uX=&X1kl7 zzZWi)(@TwSV{1y8bs_T!kUmMOnba7ocG;+r?PlGl4m#qcyV^~US8LHE!;?yspBu(6 z4l{NBiPeXXP7j4i_d7?&cZ&AvWNYX0%78lYt6c6~PG9}ce?44YefP&c*ZmhiaA&mJ z={=^vu?!$3S=#{W%0W?jf$8@4YNzWbv+?1HuNzg?wQ@!V>CcWx$FmBHV0k$P=fas7 zAA$i;%QBRNAVkqv8?mbD$~INr>L#(II(SshvoS78%rb;nkO9zX7O6Pe z=*d?8&_iomTlG(U>i%;tOLJ6HH57h=+*L9*LV%e#m|Bar=$sy6Cu(h-Q*o=&k(--V zQD;#Y#ac%Q8iU3ri*RGmy0o+Q-5(X#UOX6I`vMHF*OS{=pF|WmK!ZL2BBqQfQv^~$ z1Rxxu&G{|Cjh=YhhkxsT$?to*4<%5Q-Jd@{9M$8~mNV<8hf@^O(J*@9xs?xo_E}yV z+^y5Pen>_;stjomy1SQjdW*?{nug6dyO5<;qopFq(l`$RF`yQ?NLr-R%6m`?t6TTN zxx?vW(-*73%~42pP4VNY|9k%A@oBeJ)a9l1r{Xehg|+lTZ~bf6%FTyw&q%x`;Dup+ z%oVwPQAhO*dfB%={ABbH`uAco-tQgZcYNiy{gIb`^!D(2rBcc>P#D+;fldhk3luR6 zB$)(!c+|Y(?y$SKb)$J1-PTTxD;!4)?`4=Nssl9MM-JHuDUwJl6PnVx!c^0FX?fmp zrBYE*6m@0J6fSGsA}jl)iamNs_jg+R>)X6_CGYPnCU&u)CfShB490zW=@ZYx(W^b_ z_fO}Qsfh4gzo%53G$ETLG<5=zSXzug zXo|E{`t{$>Cd-pf(}0~$*@$i$e%W{S{>)!`yffbiH*Vl=q~9_xvU}5FbQq5IMn{t` zO!ndM2=3hb<<};cuOGfutwhztsP;nWnsmYH0G*b6If7JDZTyy<@3X4931@Doi@GOh zE$*Mj)8e=^J=Y|De{Mo`9!$TU9cQ;cxwT>rj!$pCdU|dLzT!P7%i1*e&u@>t>8(Z6 zU-#{=ebcwieboNP|LUpncz>l2O;vM5Oo&Ge ze1K*BO3WN!NnQcHfAEmc00F-UE#%xbKHzdwKJH^jfBa`ZcX~1z z9;?GU&EymgkJ~TZ-1&#!3m<>!(*CSFo@)rLrG>JTiX#@v1P~@}b*8haH?urzk4u;j zr%AK0)F4^rfS>?1)7j8grw~QJ8fhVtq3AE7%eeXt(Mf=e%UkvRX^%FmOi+D|r{SKNO|Ws`GY~zeMC~m~XtypyUm8`+jSDhPGC>*xrZUdkYtnI-)Ay~t`}X!z zALz8t#oe}O*4wnbg}pUAnHRhFjGGI!7@5Nx_lwUi^vO`tby_*u=xtB$QEmp=&Wh|M zGH$$;F`?kPoYk%o?X+etin1kCTdJm7kQ4zFcxhz_fhCYuLTKT&YpAKHu0_8~r$WGI zl81k2v3B(0{np**On6C-b^*1e)I|iEgvdzuf{Y`jgUVcNlhvM(YaUIU_^OO^qo(E+ zuK^Yt4CR0MU-tjZAK%R2rMkGy?V-hY-n+Yg^X5knc3-%AV{+})*-OV4K6~?-k6!!M z=ZDW8+0~$D!q3~1JzEYXhDLHGF$HQIER3@rLSUe{RV%Z$PM5d3(+aOmoESHCeUv$y z2XveZosg`jcJrWo&k?`-P`quJ?$lAMu11l4wQcP*5vgBMFoW<=BE@6x{5Q`$c4M=+ z@S&TJCxcF|R!Ef2PIV)mJ+I#RaC)km+eg_8H>g-RdomA)5KHOvgR+x!^dKc+)hwie zFhw7rXtRxya~gNIIjKH2YshDE754&5@pe% zfaz)#t%!Knjpn<%ZQUILe6ZAd6DB4$p6bs+}I zfES5A39w+f3cd|ex5Ko77@)6#yk39+@ z0J;!D@Rp79Xf4zYM#Nw$0+le3X`G3?(vgso5y4yb2mpaCkfq?5C9-g?K@w8Mzbb>yA%y>&i! zq0UUFJLvb;H#VE8o=!&OA(2V&*iCcioMaIRtp%nMm0g&k+ILMLGzkWxAQ2pBl8Mwd z;N^=CJ<{JadZR(tMHE7XP*zsfCbR)FEwY%?EGpaGI$Hr;U-lU(ux@OyCK%!>lpWDp zX|F1Nel%gKXBsvZ9 zwUhBlS^Lr9te%6bB23N-UnUJG11)14rSdYNq>0iUTXxcwvfFAcW?r<9hV`!W=lns~ zSULTzzm0zD@4JufSBzhcyPIY{*t<`!-MD%0@Z@ybdFA?>pMT+s7bo*_wRGoE#zSmsMTYT5GA6Q`iUK<%RG7%ep4FR<=s>n5eFf z7l*g$CEL8RI~=Z$ubo`EvUNFGg-NuSUXB*$-dld{v!5w{;0r(UkAL%IyN+Aa=5+Ou z3$C}3+hk>U|CRk+EEm!=Sl4A>Z;VSJ)eDkp9^%d-y4(uoe661TtU@)3&1zxPx7H8kJ)?0W8oH|`x=xU}|` zM^_40zI1K;!RPJJTms;ZKYIIR`o4<|FO-mE zpko7QQ8EdsL#LZ}duC^AP?+>HH|7U7_u%+WY8M4-a0>ul@)i&g!}3BDb>WP0rndFG zDJRWh(`;^Z`t6M*jkYo^Pkg@GfAt#deF|pR!3+gDL2 zok2R#t7cefs-Ax0UHgCMcYpjV-jUTVx_JO2KmOcHAOG+VeoTyE%3wnF(yjb-*5AK7 z2M3ULBt!uiA%J)2ngG%V>7Z%=d_^o{0aO;Hltw2h2(sR=t(X6WVu28B2>$GNu>g)h zF<69UN8`X*(NscrE*w{WePc~enlC*6(=L4S(mDC~ntg}+st~T*{Cc~k2ItRhJhmmb z{fmG5b9*0rFX&O|=-u`6FI~L!d5(_eAJt))wB z9kpBOYIptO#$Xk*@1Gt$U)P=fdYmS)1jn*5tU#{h$sn)BxvttPrhN{5ZOSpoHs}t? zOvxlmWJ;;4gEKBmqe#g}3W+oxPL7U`Uek39aH)Sz1&D|iTzB%w$;M6~R?D%Vaf{#~ zQi&3zIPrzV{FaYj951TL6vLcT1x=fsWFjUFG6tQK%7o5@j&!F5=wiJ>Q4adpQJ^?d zkeTRdUOe|(ehdGmZ#R!Wd}q+{4YUj4dvkI9)$Emfdv{LvUwD4|^UuBiZt-}LM6D8# zV$>kzDBu{vB0%aeT~d_~0OIx4eLmwW2ObH6^DMC}tDl3`38F`2B*rCc0R({8Gq{a3 zH3-LR3i?xcleII@QLbNw} zp|1SNtlV9Ism$qVxtMkqGhf#=N%joP?HK!779m1F`;d6UHRr>bCP4-7(Esg~67ID&~w-8|`}SvAXdrfCjBeeKoJfAQOX_}y?Ff z9av4rQ`y_t{*9|!R($@?+`As4^sVP7@47VdS7*~h?j42MkXbCNw!mnY-`+Ze3LRC! zQk@7F*}{)R>ANnm`n>24e6xG9KQoJDFlfoaj$TXhd>*RQvDBK9$QZX+6o}YOGf#ZK zJ_O^ewG=|Ebt}&|R#!GRHd-OefabH}lk?*{L0$3Mdal_-UQOo4Hm;wlt)4w;hjFJ1 zYZu5nkEzNAda#q`BFVB&o^-K0jjV};?`2-WJlI8D-KWKYDqJLh#P-E)SlH9UQ{nw1 z4{gRhcTj4kVp1c3`@BhfdG5~kLo6>;g3!neI-JPAhG_;?3 z{?S)H_bsFPeABMHR&!+(R>GCR9$Pm80wG#VirFGAU6_I~Fa#z7M66t`gk&axWUaGx zqhjJ-}TC{7wCbvQlO%2okc# zI@N#i+yCvtU0cAh879`Rz{gb&SNzW;ANj(0%|md6LST|`-F&$|tN?<5&>@2oaUy$N+*oa0zSMegn7wf4#2g>S zZfGr8i{QsnN5Gz)56t0#sdoy!Sr;5VSuGW&|}vrq!^gl!7GTMI2+tYIw?(QA_ z$mj0ffAq#fa;2Y7SCZQ@HefqarC;+a*6y8r;-eq_4%2^ZWyQCTMk`HypoNKZm>Wa@ zVn7dQ5iAEALgNytiv(!7@k*2js=*sm^*#(M64`*(isxBsW%vOJzwWlKH-sQu*R zX#d5R5AlWDmp^&;%4-Lgi}aCb(CB!+C}P*Dfkr~FI z<9tO%2{-jmy>S1J{^QpUJ)GOZKX^4y#a@;ly!oNaSJ!3$(VzU@oB#GXdia%-uX=j* z@*p%$0BGyy&_rK$g@ptRA>e~cNY3(TV?gKD@{siI9{JOQg)WaHb6VFPLdc}6!?J%l zlUmrr+0qAuAUuZ}!UAo8P_m5dVzbUFpJr>AZ1+Ug&5tMX{@nu@-voajxkf|}u?s1y z7RWZJOvG6y>4(AQxV633yZr4B9sass{x84k@{8b;?)m=l-TLLv$&;ZN>zgN2o>pJK zcJ8-PB&q#c$nWU+LWikRg)u4NsN<>%2aD=)yx&l^7`F#C_xM*!#4+^izjd0v{w<(bM_FUN!a}@TV9NFaSCPhhWef z1_A;u=Zr}roOlf|^Mjjzl~tJTG<-%Dqc!@Yy)w6P7+teT6c z`^4KH-kls2<4Op{j0v%pB-kHO_B`u-sUVJ%whykYArJ=ec$V{lf=~*nRFuS8>#WyS zcGm5#&TLHa)X$ULjKA$$;D7vG2XTVlUTq~~Z;$Wa(Z|Qp%dg)3*uD3E;pK0*GkYtq z%+r+#79y1!Tbp>=Y&5glx{_@QTmUzY4MGK^84&~_(b+3H69Rx1#LmCIKgWa&2qD(O zof!*)7g8?Sih-HYYlRM^H-L4bd|N8vT$nB<`^{Ck^=HO>@1uv`cUXP?;mtC7G$Ckh z=jYkI`ozk~@Bd8)q)$Hhg0>FlHQ&2FS$m|rwxLc=b>%tKC8;2z5H(SYQ-je$#UBm5 z$7k{@`^W#|x7GjSeDk~a>3{u1HZQho~cxTqkWvd+p8jbanLA zkJZ2Zn||n-i$4xV6RVj z1UD`rli-;_AT)rIRm9$NFkBZL8i&MHu^63NaHbfunIl*V$RL;-k20V_shB0A2G$(T zbkqRoU@2zpI(0F%c?)}{>0XM82F;dE_b$jIXVEp+L?dV zJ3qMhL6MbjnUJm4Flr6DA)Co)X;JnNJd;JRz?MNl)3606oOd9Em8@k@w&L9^r@a$h zPkOyxgW>+=sxOofNLbg#6jifm#_XmiN1wvk zkOr~TrJ^|4x~@CzR1g~r&bd}XD{bhdp)evqo`TKNmd7N+B=2OgbIQw!ne3hJ@6Qfr z&1_|*yV+l%!krteUD)n;=}#ARdB_t9nB;{5m(gT4IES7D4;H8(tQNu_;nuBJ)bSqF3 z*z6vB`q5{;O2R|eCNJ*Yxig&K^Vu$77H@23gHpTn>8UHwb9-}#9^Z`m~O+LmAa@btJ)|NONJPTgtf z)oXj^CqB1LE1ls1sm%Y((a}9E2}Yv7cUj?F%cc z%eyaqFxo!=UxA!MyxzDCuI5ovcy;P&0}(0k>jLPR1`ix;#he7szG>z>S=iFfMo`Zr zGO%awJR8Ocgy&_eD<}p*L;?U9JaY)_FbGas3;$Ywr5EtZ{nO(M^YQj7ovyoXn1;`< zKHogtYU(^MSCoY|hm01SedYVUTMmoa_#1wBTF%?M)wx-H>p(U-1mn(HPVWMF1V`YZ zG$17saj2Yi3z4=M*D7@{c74Ds&hj`pG1W;knK`blCfNeu$~I*PPO6xtK&6G4BPt{j zeDHymx!}Y=B&K#AgecP}ic=7ABZxpSbFg-~?vK{`C=tC}c5^kYxg-@)B$Z&sRK;1I zB&E@f{OK1znf6j#Npg^nKKjTLn-|=@QB-=53zbAGz10oQ_sl^6V_UIJ=+htn#A|o2 zh0yLs!Z(&NXhj-jA$xwMzmoL(eqL0ib}Ma6M|2DUK7 z&aPTrUzvW}w=Z_uKiWWC`V*?`^uXM>ae8wXUfw%@I{iAe{Z$ZOOW3y{?R7HM#ltc= zX}qhZ&I}o*s0{_?I)orFM4&JrBB3CHGqwVFa0Tam5U@NdB~m{J=Nz*KfV0U)2mvqv zEE^HvIUB7dsZfI}jRhI&NGPG)aR;WiTT!>S@$LK7um71_KWy}$>x+&^U+e3Q)vh43 z|MXV*YrhF@{*#sGYPnLtd@)JSwUdm9w2oR1OA@w9aUN9M%vO?&i&MDcj%S- zANb|R?^vrZ&gVCFU%WRtywGlsP5WQmPhNT%V7#)`J1%vZ_AXPlM#U?aU|z#R0+Ox@ zi9AlG<<)Wfu2bjw_%A;)IlbPTHY@*gt9~XP`pMmL^N~umowoDVu^l&2-Us0glpt7G zcvv9}k93;Oy}N&M!rab-{grQh_Ah_*3m5Y4nv~#caATk$q^_C8Uw%snJ-G22yydl! zoR1fEC%b{k!;RwdG-(2|Jyzuuyed4iUqp%;KLI8Pgp49A`3ejKFYFz^RKyG*`G)O` zokNve3@fd{%x~?vs^!LW(duF@--XzY!o%01b_cfw!~^ z{%m+72?Y`f1tcb#w;1HHgu0#Tkyme9tiIHnf2qFq3d@Q{_ zOCUt)JF`M%=cf~jqWPee-`&T@`|-uz!G+L7Ui4l%&!M^BIu<>%5-+;Z^_U8()i=KT z$3J!Z_xmsW@o4yX6i)6&?+DRPz~V%KV~~y!6fsnYCAiE5FFa9AsECv^x^aq49dY;S z(QGKHdOh~AIC^=ucqQL_E5xg^bFpY9(vKoO6_t;v6Q~uu5O8*MlZqk{lrV;f2H45A zT7RxqpQ-F$7pFIgWjr7wRP2%2hO%IVDpF~jY14vA$Ru~&TGmNAym0L>z2`N_mwKn? zX?1m_e_>;-ohYr4XTwI#+zK6TP-a})LKa+tiy2HQT2rk!jh|Vces;K$-FWMJ?CE^) z%BNQVzaTrG**Q-2VbEyYrUQ!haA%r~hiz05p&aSz?z8=;)t^1?N z6X$L`GWdiE7qa@ZlSRFMKRJBmK-#|C_o@)JFEgEWO zog`WIqvbOX_22c_-MycY_tv&H&7QuSYG_oipwnE5taQmEqi8(vC%x=^Bfp(K_l@uQ zvFNFnn{xfqKpczS2SO1azxY=_vi3)R!|dyyy!R1EK0jTYOSoKp`=5WVcUZu>v^A~I zQ?VLO$6{MWEr^mj#hV&0b#DLTH{II3h%`(tY*w(o`ENc(xu0Gtj?2#aVA^CApdt1t zNYU11Or`P1V-_%YDBC?~f&aq3_}ACPuX#)KKYnZTRd0LbZEe+U-K%NP$UcCDCQ6j4 zoc?kNi@}aVS?6sKiHwt8(n^n}zMd^?RgP;DSXU z09=mMKmZUd&9P~kCW*5ar_*9O8P@d-gC*fnCdTS0(khQdng-c#p=LG?6fi&#NQitUE(TgUfsi?PU}T8&7yLMJ^)}Na2H9)nHoJE^&Q#qf z9K=}*Bn3ZX*EG$Eux+n2YFxqv%giiMDY>E|SIrj+*QxV<45fD`ZkmHGV=1r+lF}s4 zb=(%Vr^Fb2a8Tz0tb6F#JZY55h+=%(g&nKIvX)Z~TN|wNl~q1#MS0>=p+aR^Svu&n zn|Yx~O^&9|-F-g4p9_kHC*iqvN61Ee@TrW?0!UcU=d{^oNRf9qiNsS3di zA2HK%I++)z#e6m#j~3(cyeg`etwRWo1K?RfC6;C#;AL%vL_qkZ@Rqa8DJe4WuDcR# zto5rIEKWk~gps)yiQriThM4EZu?SHlLRc30C?7nq>|Y0h6Qz=qMaWXM)%DdhZRSsW z?)JOd?H?^H=5e;Va~hhR)$Z!If7?fb+xz~Hf9o(>_v@;dM|LJubcY3`(Z-PqRb*Jz z#>_@;F$?Z|JKE}JFO~MEJ_|qng^k_j!iVnX`UkIn^%L%$Pi?==N6qBqXjI{1ycYLC zt>2s5(dn$RgQOQ7QSYbkZxyqXfKIknK2&aAJwHs>>aiXF^oKw5kAHkN1Q=8Nxm%-X z(JNpeb$Dr*w658g4@4bOpze{+e&Ut%W>eVcFB>;Cq2z>+pM zNO%YioKn!O(0!R27N9Nfxs!2w4SX)rbR{3OUc9?#CUajk=q!83!612F=C4rzWDnjF z7(g3>VX#ZVIA(SrP>=u?07w#5CK9ESL|HF~qk29);d-pu2DHqpKqADfvM%TAly%$v z-o{|O<+NCjS}QUhIll-%=p}mtaK=+0 zmUn~)@TeFONTHNMX%up~QR=Xsu(#Y4U>D$L5T*zX0>jyI11#kv@XR)Z2N!b$KQCB% z4geHFKp~pOjz_bV)yQ=E=27fv2fQ0*D z?kagTq79X;1Q7>34z|gao0B4?v_7Ns5CRf1No_-rViEZP;MdjBzAZihrAV_#De|>u znUMlxoU53c1{Ww5lV2;!XQ%v(kE?D=rnHhq$D$6-HQp%^q~ZV^IB*+7GiMu{g41|) z(8(7rP9YiInU1gTPO@;p`Q+rJym&=#uazOBvKPoNs&V9XnrvE7Hl$J=s|o-J z&z`GHXF%@vH?OR+$%`=Ty#LZip3+$ba|n}D+&j33`}?g)_LNxrJ-YKXr_JQQ=hSw4K2GI` zpZvh}aWA>|rnlXg&ysj_zO~ZCIC|GMp8Mr@%gOc6-h1d?$;q8rav!z4>W|v^&t6&k$g zi-&K0mS6qc&^A^NiW>$0wNIt@USvIPOawmq$nE^Ye{Z__eRq8MnYXt6 zfA^pEAHQU^nMT1ikS?GDF#K{WECI#+a_^pc>yZ{a!8}K`nS=MY-OC(#A zg;s7hy7n!P{P?B*D;b>k&EoFv{;RJh$EWT6qqWbx)Smlwh*vq*Odfp%49=AVl9}m@ zsu;cm76eEjB%aNfmev?=y|7EA&@b3e!7l)6LWe{F7`}*Qk!6?UWzXz?VhLK}!2=!E!d0yZK6_9&7iuR0Ol;bTJiZ z`%)T@yVFxIkn`0Y-A-7@rVftdrLEjI#-EMiiKLWEMh4wUJvFkd&ar-{@k0};ff+QI z5cE{iijvw_K?dpyS*X!yII#Sz@sHNrDw|bE38UlLLPQ>sV=1+wC`B)#xoJE!sSesR z3&a4xP6aGai{b3#t@8XpBo{+(bmItOzHC%CsCzH(c3XGUuqs)&ORH69fJzYgM$0vd z&wi|ktVrlc#yV0;t!{<3lt+8k^-e5vAi#fa6)1asfLXm zk#rnQ#l~u<^p#WT#HeAV7c(C)WdP;N7)%Y8Q6K<%;heKpSmRNm7L7%Hc#3N+x3*HP zb=0uEa%c4R@A>$6-u`Z_ONEyyIrZtC%s+MM;_UbT`p^7{e>wi}ovRTPXH8x z9^nOm2?hb6lBm_#&cfV=Mgb&SFnjMiqU-m?OM9Ki9v1I-=isrg+#F3NclO5~V!$%s zDKLJSqC04)PRqSp&FnPGNo#36&TUMtSks|Z#g|^0g6u%c87u)3!nO-D5L3bWtX#*yd`3E9c_#!!z$Mso zFg~39U1F%n&A?BQ3uXs|90VW%!2dD%J^(N-arPn3TEeBIa&{U(@a$c%0YRy#EatkcvIy{Xl!Dt-LX-riSjeB{USufe1bD)&|) zGlNGqyflIlo)wGUgClSVGO$IU9i@J`Ub~1i=lLdx7DaQkU8yRO>@UU#^C1umiJM8g zTd8Vc*i#TfDW#Y7f)K)c-&7^HVvsVbS+J*8cy>8z8HM6fO;T+0$S z=q9b{dd-hc7CZCCSCuD{5ooMWJwe%uv56Q z^2jQ$u6D9lN5kfY+dU-{!IyUT$lWi8<;G(VKmO>Gi%T1ovBCu-!U}cIYAZZDky%Ks zwNjGWw}<0PSI^yh&odv(^$9oyVR~ca4_{ITr;`JIXz%zvFYlfleC7k@?)9=Ph4JJ) z&~jc%`s@KAi)bmVOG&REk0OBa%%zS}kdh0>tg3({?H>Etb>@Inkp)>;Yq`4hWRXLWzeJ-(B*_9X9Ga^d0j?AgsLS?~OKy9<++ zb|*aOi1t>#y(QWg+H$tBI!H{kb#D7`Hx%AUA%y@BGYLr?HWx}zH4$K(Tw&dk*f=w( zn`46AL@z4ngYBK)^ndDCcQ36|GwVtjM7}jV4FBjS4uAGGIcft|iJw&1`|=3Op$5kK zs=GPArdSk1F>TO?LxzhKxQf9f&>I4MhRFW`Q;v*LYd2C zpp&kM;$BC0dir!Cn~ETm7-|d>NI_Z>ZVTv%tdhwz<()^@Ctv^0&z~DC2re$__+ZH6 z=~aW*4#%_So=-tj)XD-n>ly(`Xi~5hY7H#mb;df|OMkuGB7^`;=z$%$W?8BL1PH!F zUxJ%SKL@A*(18k!;!Hnc2`rHW(9#Tm6qY>Yy${YI+8_y)L@5+Y0O!4tgdqf}5@X7f z<5^ghm%9FTE6k@U$%%&3M*@y7LRG2Q(k~;gVI)1B0jFlTjl*w z8?}9THO;cJvE39A&&tCk^Rlt^WHCOqAsq9-itbt~>t$OG-emYrWBr!wZg*urUWD3t z*VRc!wRSWtI>Aq7y=$+uXI0aVPL;RLb##oyj5V?ihDs5|8D+87P6Y4Jlt^Aybxl&N z_EuxW4yCgR>83RodVw}C>RBd7!gnor_C-gh51re2_1N*@2 z2~7w#UOc0#^38Agr#reSAx>q#7>@4W@87t4y2nr7Tzu1WFUEJD`+hk1{c+OEref>!^)M-oeSq*zBhmQ=4gVThHf@J#W)}mAQCTM^B#aXpygUB3nChi zxm*OTU99du7!E$UKEM9H&%NAl_5Z?GsKKCfsYw2nRlU6EzW=G)Kis|fiB~S!^Xr0Y zXGgXIHYXSFy)Y6WB)OI@%tOfy zg$VK}Rfv^bBOZYZ5HL))Hz4c0f!LDrh=4Yn=_LJiue*S0#ZO|T!V(}1!(=V5> zgyyc9?;YLSd*rE0t1EEh$knw0H0%vSAgzQ-At;6<^0pEwm^s5Szz{>hV2C|21@?dz z&;i9tWof>aWdkYGEcS5%ZiI~m2u?yk)*vDfF$oqCA$5r3t(E$jhxZ;||0Dq!)4g|8 zUfZqikL~SU@#1qE6&cbAg*2cAv`h^P2{Izl4^%Vr>n;mG42(8f1qD;MH~)|C3nIlO}YYQMYM z%B-KU)8(xfw$&>W&OUKx9%SiU6iHwoFWXpwXDz=+MEL;X z*-d?E`+q$rKL=jP@|%kM_ML;LtG!$M^q!ma%fB#sX7{y^!JQwK)e9a5&TUbu0|S#> z+B!UwN8tro#F$VbNnHNW0Thu!lAu9FS}27}ZNZ;;S^y;Y%?){OyK{2vU%qDdPJL6% zA{3)^wsQ{Gx1uL5M9k6ss67&RTKJ5nh)i@A`$Dgm@BuyM>}#ddS!qtDpjMMM%{y_p zbTKl6*pA=%^4+gm>)z`{xB6JO*KUJ(^Ar8@YoC1a+6zydjM{NJj8w`#&V$vu1wqHg z>*hpoh_c)vm?*IBm)I#95fMqHBk2qlOsy=|b%`uTRp6|?x_fP^oOYg%An;*@5|R7LT8+B6tC?KH5MF3LG`H`P_u1tCGtashi2 z{GI=L=5Yq;5Go4+0Gxm*5)sSD7^p+~|3w}aOUR5ro{q+nM5hzXZEK7;%S{3dBqJGT z2r*!ka0p`H#4vyhTn1B6Fo7K~29PZ6Srwpl8pmxNI%o+&a8+;TGAO?4OxVHuv^s_YUseI~slJ!`UZ4{t))}5M%VI6568=VGII6 zC*HLHD?m77BIM-@B*25qH_P%qfQNt~009XEfs!D=k{28i20?_knVvUXKD^Xza{4H^)aOi|JvMMNvogQiUkLXup-Zwl3JDiVh-ya(L?C}Qs`-&ii)x~o~WG|EoJM|D{>GL9luS07~c zS*iDr#<2f9j6;MvS4vm)C~ck9hLS)Ckt9)`W=WD<{bhgl=?nidvn}9n)2;F0QR~KN zZ}v*%FZ{9H`)}Kwd>)E_IC99tS6U{dzz9-!m7vx_=`%-Y@W_Y|==Jgn6oL|@ zQF^g#qJc2*>odX-f@Hh7p60FS#_ieNT`;15dU}eLy5}alckjRJErUm%I45Op8b6)2 zqMZznKl^%Zi%S3y6CyF@#t%EO_l2vh?qsW*?I^Qmb5q!)U7Ia;{CjTS`wMII;f;2$ z-XHt=Gi`3Z_MNAnxjX-XPXsilDLvvHPIaTC@-k}aIs+Slbg7;)@A$Ixt(kEgOp9gk zBJ)kEs^b7Uj%*w`m0=_WOd^=|x`T3ddR5dU_yo)I_4DtZ{MbG0{M+UUv+6NvgS1gQ zZkcvn+9nH1%%i)8Hn-S$ZDz;FdwmXoqA@T`>xA7eorshGebUy4c#jkPQYM6?Y;5dTr(^@IZdE!WiRI z@E4$!CF%l%UM-T;4xV0p?rl%rWq$9p-aa@P9qo?B$MB&K!6!dnN8K?+TzQF6Sn8<3vG))_8j?tsztBBL&R3|({c7hrCeUvo!ECTWzyBNm+Fu<0iBWSk_y5MvKNE$Ei7RU? zYB2$j=pvwmm;)1_U=Uyrfe3QT22Ax@dGMk7`udIT(|P}QKlzULhV;o!a%&y- zPv#33y?J}Z5c`;F@-kCF_{D6rwz<)}+u5B?#?$?F*Rood^E^+c*c-3kI?BHGvAJ}w z>>a#zw0-ZDP%P*rf6_Ww`}*WW!1%Th&}6-goKWrJoX++=fmZ}dh6ZpNav9^on<8;d z4Qd{pC29>cN7Q=!cces2GJ$z z3HB~!gE&cY8A3P8AO7k)9XbY<5UtMV+0jd%z5e-^=beXdM-T7qo^)Ql7w*i)%+&Am zB8OrHqMC#vsfpxLEsh9c2&CeS0bW1PLLg(n1Y|6I!Ya-o2p?uTHiFSEB6fqW{`9-w z^c};|;@ZLCLg&Z(2hHxyXm$YU;IQid)F;Ymvv|kb&L>YvQ|)1r&&F5l<~U1CB%2V3 zL+lYK1I5$WOK<>Mn}ykqij{{|-CVB2Ar>L(+=R_XP3LLp*Lr50ccHcb&_bJa!N8sKTj zsznFgdMj~~T@-Jem&L+Q!o#EHr6>8Pe#Q6$mqss`X!ULwlqa`!8j}DIUgp*Yj(c(H zWY^@?&H@0K1;7e3=dV+G&l7e%pN)4i#&bV}7A(fHs%IDHnUL4cYtj+6Gv%3!6P#W?jzS(dK0Y)rG5 zE{3Pge5}0jO(~+3;&$5YcLx2m9p?$8y6&%ag$!ClmPM6R4%PCM6eOJ%O_py=0j3vs zUjC}De^L8~0~NEezJ2@d>8ab>bw_(1L`IOX(;`VcAQ0!BmX6Y5u?WU#orLlTjRJ2O zJVH1lVnPm#z@#QYv8cw~==J^J{vc3Kl{q@b2P>9LNP^Nhnsl+oAcy4_ z9~?kHI#KSFEt`4{t%R$-bBnM1l}|kT*gSRs!UVXvd!%lj9;nW{R|dcCGsk9la?mX9 zXg>}XnNmcFsz#DX0*R31*+oQf_9_QRC{ZqjOA^cBAt8vylxdP_nbr=$2QA2l>66bq zG`H?(X6Gf3hsTrsBbZKu@gnvDurl`6?Sp=g&Yj>)9I;lTGhVLDrCbS#L82rvZi zR3uT5b4~(kO;M7WI^4Q*@A~mrF3Kpcz1-W-D0S*2;Pw=@?HdD<6S^7CO}}q5G&EjV?yK*Sf*B`HDf)W$5F`JE3MAp zP5MXd@ZMl_S5!^a#@Q5c?-?FE`cewDKfE#V45HZywQ>9 z^xC~%)>kFrz}nE%T-DoUVXM+M#>WnP0LCC=k!P$`-EYC#Dy(jIYA7_AG>uV5AUo_w z0zHPk0uyJ?LufyB>2r@?{1n$;;nHGwygeO-ri^aBy0~+r63Lp>X=S8nq2++YX)kT} zS7DSb=FL(CW#81~>Sg?Ch0Fv&5Cj%*re_f^d&ThjcQ!B(AtV?8Fd#?|38D_mwgW`O zGA7-|B&W1RX-66p0D1YL3DC0-A;2Mj4b+YrwNXU<*38cxMr`;Q`tDzx3<>z~?u*Ev+uEQP|I) zyCv6-{Q6p?wq&fWY&d9Ll9h}I6d2hP2Z2E@zmw6D&I8D$WO!!hCE`j85lOQs5>AC@ ztJRp@y+u_9%K-zZrT18{J6kUfu+V`Qxo(+q7NcusZ7vS3_QKZ6t6|!s%@t>g!_)fS zeBRssjp@eMNLV%!6?@5?X4ZBnl2n3nt|}1G*@Vq)O|#xpD9Ajq$1&Pc%pqjrMcJ#kpFk!edmY5B3K(;M@s?G}#>U$_dVm*IPG0dWm&OhRWnh^*g)w|1K+`~fb_<=!t{ z$EW~^19@TpPi%E|7i@S509w8g!xCa$7C~AYk;S>oe&(9pp9P=X|%P};z@DvRk@joa;RrW9{&o}Am-?sPiFxcQ=~O)@Lo!QqHP2FrOF zQivnS6I|&>YlBo~iW@JvQ36D&Y`Wr`Lkw0H=V-?_&FVwvieLWAKG3Iqp%(M$GY={f z!}sowZr_|iP*Q{A3Sq^1gIb2A0X=D_t9cJb^>|#yGC)(grUX-h5y(uQ1aM$tWC)(% z%<=SqH zf1aPEdbkJ+5T%}3&kJTE{*s@m`&z~^TS~^y3l_3iMOWDKH4>Nd+*-$Yq#&No^G$U z+x>TSAJ4A6{av5keA=htJkO4A9ewr#AJpaDtUj4{`*Cj0$Kw^9k%3@*i__5p*}E@0rflCR9huP!Ez(g2940M+Xu8Iv$Lz8X<&?WfD=MB>*E+BqfKjR8eEZ z(a20HuA3+d} z#f>bhP_`F`Pjy4PERh2(J&6HHk*}mTTvSf z?u$k=bw#BHsTeVM4yI;s5RgMaBxVnE=Ftia2m}a%g8~u|7-;En1&IiZf=Qx?NX0@Y zppzgqGK3H~cp~^x%Lx$9eg^}C3%GR0vp|+IG*%B!7rj1Yv2C?lq=U3WVv(6(Xk>BA z(A%c=+Hh2)`*N){f;4$zWBj)556|j159L#(SaXX{Cr;1(Ffe-$z+&03M64tVva~Lf zOzH@AqFY_vYG>_E+V12!?kW+D_S-WzJuxA8Z4mr?!oOqawYxc@AScymPeSi8Zzav+$&8-v&4^I}8@#5wUZCFt2 z#%j0U?er_LZhafVA!30P1GEAv6bewV(91cXM$)|WuZY(VjuxbrJ_dfy_310mt0q&UR2!JNJdT|NR2`Yfy*$7wyF8<{o$4K*(2xjYX#4y+S+zG zttmLM+`NdCCi2FCQpnImG0h8q@1V4z1?A9JV=|B=W>(|Ajc?rR9G}NT&ZEe%nq!DA ztdAeLw0q>fc_dD$veq@=EK4aNvc$|H5NbjVT0uw@cN17!iCgV-HZOajoC>{waK+z$ zV*Z6I{^eC3Ndnt!d6iXK8QmC-jRS3Y6I4|)hCu8H8Ic2m4UGegD7;QmxMZudJ3t6A z0Pxv%8;9Uuf4lYvO_+nTnndP7+A44hm16tl2KaR@^e#R{d9Rw!d}11-SfGq&PDepV zCWc@_&E;r92+dU2=bx=_dWJgEtBWFByKyUN4+d-7TX~u2!~`)fLQ(V517LxDUDLUN z9JKPaRkPPminPy|DOfb_hM8OzY5BytSywQaPF1S1xpjDS-#Rgy`?{(rs~n4En>GW= zC6O^$KREB?aAj?CbNwckjKxv&s5XvFf$f^6}FfKY4Hb4X>&#kLS#I7)&1Q zA-cehAq0=hjDkp^5Ft6AwcAOWidgG3iIO--QXwb|IKwcBsmu6JMVjqjOG@5cB3dHdvld34f<5B}Rj zlf0m=Kb*e&@apC~L5ar-R7W7OvewH`Mp9e$AOu7Jh#-PDj=l5Xky(KQ$38d+1_-1; zX+1=Bk zNJWB{ob}+oYn>+7tLZePqul`vWqVJI+HA&X-F}MrHNj6-+%z0CYWYwG_4O$n<{AC?0VM-s#3r@ z%qkzMu-q~LARki`7#MB-Igoo8YDYi za1yEoQ6}P6>7&T&r3nQB*anJuh3pq{;wQa42w$9AZS_~WQMNIysTwi4RXd{U)8;z#N zdwZ%X6A(6p3PWG2#Bza{Ib#({@HE{&y`R2z>4_^F1G!8ymz5+JMWIfmitD0qjS;11 zF9I7576A}m&zAw=ka5X6PU4bAATTz>Eda#V6=XUaI6CL_@-Z_5hO<>X2oHc~wJwkc z@Zqd!4+5A}R##;tIZ{RmK^bXpn|e}obPj>NE7Hq_`ubUOdU7Mf3fb-~!+JOD_oM5IYckqla`EQyuUm?bibKnT*xcp6{0(vOoT zgxsAtc*1fIHe`IBQD1P!CU-!109eHPCo^Liz@kObXIDi{|*TQ{UcNwID@Eg5n)VtHg&V8=*ap(Sz@fE@)d ztrgY>?>Klc4oDCJG!2*Y@eCT<)P0@j-Oljd&A*}cg^)AV2|C z`Q^8S*a!>wXd8X6EMH*`1T?m1}IPbkVy{VGc;&{4ur{3Or%fnYM z-5XYiYW3 z4_)31^`Hi|XeOuAj}mQv{xdhOzdA+L7IEx?c80{+EUanrsHIdinNIg^Uhl0&o0m4* zofSzy$X;o$R2fCCc2S=JK(1AG3W(=>;G>jjeL?@blf%AUb24Z=LR}bcct*SYI1w%@+wv3MC0SO|&Mj zg=?iE(O#gD1fsRk)lxsbw)!n!*E$?d{?!Nkr(VlibUQ|B2%H|x7Ez>DH=@<`mCRG} z)CX3d{VAu#-fsWZgT1=-Guw}@&8|Hy(=r|@)6PSy>J;9E1?TPcYGc0&-7sENl7uaS z%Sb8D!3m}ioOfV-Xi$WuRumDcg^$46V12OcTtLAAxvu?WF)1T1XX9)&?smJzIH3|h zcbqaW*=ktWlS#KJ9{np;RzFN#Gv6!SPGAapCDq^Xr5dpnzJT#>9Wn>p6d8^Y-d*Nu5QI$pB z3#9~N1I{p_F-A*GXnXy(R5Th5z0c?6qVLIzz7f7MnO8OlaWKE~;=Rde(eBNwJl+U+ z4c+>=?yc?Bf6*QOUL#gq)ksO5PHT10@#Kn72L)Z?Sj3sqT9&OgM42p&YkYX0|2X;E z(k~{YOH2*r3bA6726iABgtx(4#uTX~eC~_+dSzr&1Z^7)0RbHZzw{;k{1sMYU)Qjf z?+_6DnZ#*=LnneGZ@p<^@NF`MWB>0DW!U^;yzhfM0Ke{ixbUvllNZa;T#k*2AnnO6 zBGvYm>r%~OSh{M;@tkSMw$dU&7l8vWTP9ksX!G7sz4-Fz){W`#)%&BnwY7Xwue3K@TMQT{BFa(cN;sLM zUMh3uk5)R6@JO=q7(fsU1%bRbmTdqp1E>%@0-+F$=sg6_BCvNQkRTNW(vAg#)KV#_ zWZd;3NGZh9_@UygbXK*qrV3dn?zQ8`y48RBHJxAo_QAKj?ZWBxkKDe_RS$A;FenDt zUFD>ty_;Y0%-mnCYFEq~fB)dg{o{A?>V}nfFV!n?&MJbqEz*HXbLe)&S}yv^cQdU- z)9xyc4C^N8sklX}=LVPBo7+3wT~Up9Gv#(ez8^NqEWJ{f-TD!EJZS0pTe)H-zfBl7Y_ft=Fr{B3vZz}dqr;)eVBoLwi6_@=%dppnS+5SAG zxo$>eTCJ9@Od=%Y>5;cts7vH|9_!FzWkfMYV{kR{m3Uj zh^Hqx^@_rcVf?!LU5re<2+#j+!)L|K}ghvXN97b(WPd7`%TaE zzv3ml{$aktL$LZMZ$lwHAEL@_0K z(6JSQqc}(zWy#V4OhGTtkya71L>7`&r8iAAR{q}GA8S9n(?2?%-8rWFMT)!EOj#Hf z_@EV!Bgs;djx(2rSV`@Lf+%>q+Qm0t?QK5jxH@cuZKf0!5phgHks>5gxh;0z{8)Qq zYwOkf&HXV=#wCvy!Z#Euga#rb1ggfwx>&#^J`$)b~rtyl(SA_Zs82|9z!DX+W zENWAMSd{Zl27}BeBE*16x0SY4)`$L9y1Bigq^M?7yBK|}dFq%tPKr2iFHp{85h^JI z>mVamiP3QtC6$a3lU#Nfy$_bXwWe|G068p$6DNbG2bbfpq%iPH`>kcN9<4_g$T4}4 z0fYxZnj71*285W~xb=yfaNKk(Ex@V&Yr9lp; znxlf!gvvm0-c{@y0Kp!aB@kQmwKdcEeE;s=-Rn1wZ{I17?i9oOcD(NwC!t=ry0VQi zwXK<5+*--Sg_YRm{i736-aiPl+Zs7ddjI2}TY37i*T9OZ**MtmAKbt5;r$CY?>}=g z$siob5Txy()S!cR^31`GNJw;v8Qr`eNI4iNd3+y?#*ORD#5g_pL!wadUo_p8IvqTFp<6g_g zIBO~Aiy6yYbNSFt_lZjz51-pmfD#}$`ji*9pcHrR?)I)f7au&= z4KKf~zxy>?)A#h0KtGHRRRR)7nio; z#~xBx++C=YbT8 z*ak&o`Hrh6z3!STVnlS!rRfZ9`!^gntFx+P6wWrTE^J*f%9@1_-dML-l=I1av8bBT zNTGVYmD4#kRa{m5hI%Gu8&{~T7UYFvLI8;zGiW5?B|71aY@v$TOK*W#v6sOD2jN2< zoM+F$FC|MKARv2YUOK;k2oM8-55f6hJ%qV+3cLd>=Pv%jZ62D$g9j(Ryp}K}Mu)&r z(==f|n@zA;?WdjAsv6a?v7N4|H+*#}!(1VHX9X4LgEu@m4b#ySoHw&M%of2MLQ{Y* zff$4UR=@xVwpc8V_9rWmf2h;zMBO|b$e4|3D%Se5QLAY9IKs=tqCP%|4~PD`c;Br3 zX4ScG;6&8>!nT+~?ICGP=d9iunLfUS%vM5qmi@G8M*#%J< zn$OjI8j6Wo9JyKm3X}=D#WE;EA`!v@TtnCdUH~&X1z54Km=@qGuvv(^fC6+RWP}*8 zc->~8^VB%27mIg1z4j}=^;rpv(c$c8Km577;OhCPpIpAOy%7Vry3ld9-pZ=!=NAX( z8}&#wn1R@^%_?Yzp#r-eG31;M;*);zsj+{?qf&V(j18n5ll2rN3KWE1#1zAYj^;iU zk8F2$&aF2n7AWr=oZN2AjaSO){%m%f-@bVVPH(~V`uo4S_p83*rxzHPFYqK$2&nxFEAtm@O3Gl%=E*^Vo@J-(~ zN}&P3(&USIx_A1y=f7~FTx`dy1^b>#_l)&2fhbJ?mrF=Ufs~MuinJ0K$IElrW5py{ zh$xCeTY+~{p>qx~2pLz6t!k62#Z#BocLwQEfiDlu!9+I0(w-jGRgg+W`T?YrD$*!K z0ATB^OhLz?8Lwu|6PG)Kel{v9XKO()7^H*Mer5gfXn1&hG@eZ^uJ2sEyyFAz-JKkc z-DK)RSz%K+rgdz z^NEL?00XRY*+@HE91r3ZE#tLLw&q*hj&Hqsczt|Wr>oJ*x!N)ZPTTDeLK4ZMC@@S> zS!_kTfGqBwYn_6XFmoqGb2>?mPkW7dGHPvB;U(q{+5|O~WocaiA%)aR>$5yF2gE{1 z6^9_2AOld8w=k95SpN66YE4k6r40oI*Mw438Z5yi_f z2a~g`>(DlsvrsmU#F{Bg=Wzb2DJWG4u3;B3BbrP0kR;a8{;&Uyt5;hJAa54n zZCo}t#)~&?ZC@Qc8oJ%q-J4&vd!tw1e%_8piLl@rM8LDg&Pq~emMRQDuBeAc$Ca^F zRrOZdd8U$x&b7ylrKXZ)fhf_b4&=FVt~oul)xwv88?hY3GXw&x0fD^@fnn)d0Q7*2 z=#Vv|f?yd5H35kbTnMgiY%0y;m)73@rgjbm@eF169Z&C!|KdMbyD+%C(TM><(~#1D zFdPo+so3yUq}YapJj#?U$9t!#urW1kg5c?dElV z^JeS$&u@S9r>1al?xJ~W@bFu&UhYh*>h3gtWt`oc4PQPUZsI~^O)o9HZc!wh_v3ON z1d>Dt;38ZoB|)+z1o(BBTz$tdn}Ss2L&Z zMh=3U$0Dmnww{-Ds9}Ft-8&q{7mvs4#>*Gyiw#OWL&!6;kId3UC69`U5qI3LmeO`M#n zH0L-{aU>&+g2J+bAVJJ5Ni+ChrkiWg(@$QKN%YFC!|SKTWP#3DwzcFURn*Jlm2TGS z4Dtl-?Vs%3KbS8vkGT)To?}MKGY7Sn*ly>YLB|7*r;FL5noZxfcW?Ujk6mBeae3M% zBa*0Z58CPF`ASzG&n!u;lXhszMdeW;k+2Sdv{FJ+#=aa+j0>kbYa9I-jzwKH3k%UG zq%60G5O26qMn2bz7*9PmHDKij#&0c#{WMPUIGV*Lua?R2>CILWnrfCP6GGqzzy|=q zO9+V^FoXaAe3q!=!Fw-xXH+)Te5MNLU3pkI>s$;}f4PKZPOmqMNq6H4NnvMZvA}WK zNFW6fh1yhr zqONUGa|>*oYKUX!D+|}6K;Eo?a-|(bxG`Vc*dH%Wp0C#)-n;Nfo~}Ht+LvDQtIm96 zVP6Z4CJrDZkOJ2%P3t7JmJ|^%8eWVG)3~ZCH#WP2LF@c_n?V|f^976-VYcAu%q$8M ztF>a0*3-zBDKr^S0;&V9VmoA8v8|as0%Jh-P2hl>BC2I~ub0uc3Im4_Ted=zFhh_YnE@Af(2ISMThGkdtk+Fmb%5wVO5by?X6lfOd!yTGd?_ z%~xnj?aVx~vE40|o3$wTOv{*n*#5t0I}0$mt}9#b1D9_xG^3bhl$jlRc9=QC%$#q+ z$uI{EGhuY1F~u^)GD{}0S}kZ&b5(WGt&0ah-|qhPBt@56M+?@lM$Pe3rY~Kt*23mmQ%Br2)Rx%CF-h43lVEX83Xx8^%GhU< z>6uBPn-Iiao3RNJ=wGNgkm%@a?)lqGK5^mSM0oHhwB4flfvAefHH z$%BXErZT{q5-cTx6M%RT<2P;Ia7B9EGyUE-zxF6*8;}?c>nS5$1j~y$3qUq;=F7+g z6lKdRQU;n`PY6&w7bRr+T)ENFNU;HGi7!1L=?05=NQ82=EBzXM)gHKI2>MP=DB%s5hT$Dy*lb7P^=TA5pcg@(!6KASl!R%dL}ky=-yN7Z9h zZ`B=*WEbBNa|Tf}Z}>abjrR8U%~h&Lr|Q*E3nDEJr1G;TTnFxGos`pdZT+&#%Lt5I zK2ztY-BDCErc45cAJ>WMsC6Wet!ufw+g~!r!hhTRG^)%QLHOHf$u|m&2yocLqsMX(iS5Uw2GSMT951E_Kd1OGG#Nj6(NxHFN@X52$xV zlBnf=l5i~|m5@aq*E$N5*v(RvT{PbRp_dSX#V}}sI;t(^K5DIntIN#{q3LpGFioQY zD{SP#S|50o#9v{8DFFodSXavqWt64{*apxtMI3W4>QsUI078lc%Pvwz#_d+Huw2Uw zIZn2R=JTp=!CBtnM0kKQ#H69$(eZ%K^%oD#k4Kf>K}OAZXecFu9q0VDczKB=0Fnu1 z3zlknHDHu^((bjgQe_N+IQ2e z6NxBFI*qW?6p0V51&G=J9pC}Nu@vzIQnIN+&Qvx%FiUm9nkBn)IwTTnovrK36o7>~ zC5|9*Kx&(YQ*XH85)Hs_)$CLj5ak-2JU2sKL?uC(nWmmf1rnvPep{h5VPR9ilI2(y z8SyHMDL7I}Uqj4VDxDWBG>Am1<=g(DErcdkfsXqPC&wOCu zwKrX|<%*TG(YZmOE=nM4{8^l$?|cW|&00!|j~2ys{t|jFksz2w^**X-zi` zt3Q=qUtkE94xgTS{zOVzDLthFR{mQZMlae53g(Jh)wL6cj^)xtNR{GP?{J}3e-y>- z=K5Ub^0D4qe)pwYui4J|CHLP~+4tCFyJZ+)Ln4?CLfQsOk8OhMUbjR^6Q`r{`eGOi zQ<@|!O&tpvjE8o+&8-v*I!%az1d^W~0ZK{Wrt)qs|KqzqxY&f>{@7QiYe5n#3w)e( z919E~qBd(Yothbip>U$ne!JkTK0ndGkRh$r#==UnR->R(D;*(X>na`RRk}mBT6LlR zY70~{`PLzK!(eWyR)6ty<@_3HwiD4|p&$M9V1#T_^G(#2Qcqa+T(z&S+~3n%2`a6G zr(C_&q=Ff`l}5@zjMi2o#MTVSdwSe~LfK7AQ+Q!#tr_&08l_@|lBq)WXc+yhO|k|7 z1fmM#;XC&Id| zX9N;Ks0Dt&(~blPc^)So2XAeN--R#ykQvcdlV=|xF*yQs!1 zuN_IR%TRaKEJ8Z z)rDrz0iIyNwC+|!00@fol#8`NQxhUy6M`kOn;qFr?*h;n(_tXVFD5aMMvW20vFqzB6B z45d8nq%Yl*zV@|~0aU^^l-=Dr&xc{V9W@v$K!O38xm5Y8t9m8ZM+OEqtRFvn_Vgo< zKQ*f;_^PlKKX}jH#pNkYPbIn=X(>1DU`ok_qfr4;d4jnD#Ok`yS0vlV(*=hi z-D0S)yt)d@ZADnt4b7whgD8=aiEL_2OwJjWW7-Ddk*QJUYHdt`q9lnBbc2q7w5q{u z*or-~zdtp+ZdX>tg0_RGY+Es?Ypr6@=q!36K?#wvtBA#*q+V32Y$&N4%9WrJCIv$Y z#h?kK*S#=rg*@BzJ%*AJ3IKrXByKn|W}4&<(R3W)OxnWJDuOOE?FrFm)Wr|AN*aFA!JM zp%>n2Qbk@RBvf~tUMfU&1Z(k1YSrdidIO$IHuQCR_hcT#_H=7Rk5Z64f{>B``iv_# zmTrStNK(bLv5q;dAkMQGfwyRc2{HIjPdLEM1g#~BwTzOzaXX~i-JfD#Oj(Pb=CykUH)qS6Mwa2a&crLcRRLZB>|=-!5H2+y zM=I(^mo#FWw>lp2FafF|C9#2OLpPTU)1hWsrnA+2nWr-LNy_J`Z8UzhMzEbDfBnX!<(WUGV&NQqG>)1SG&1tR%{zJm6+Z*@1NcPy`0FmYB1dpbibE^t>1QiX{^a?eea~&bbgeRfqED ze(xV9A3hOvSPbVctB%#QAQCL^rsvkG+BM@h{M>c!1{*QB{Gk&^zx{Nr-n{ZX*Kc~) z9;SSP#K(;r|J@r~A8jt&d(0`9b%=!szp# z{KIptUv}ak{`@~~y6(oEzxd1VPNltO?MA?NF#T&Fif-@cZn%MV+RvY_CHtN{H!-pF zzPGLa^dG;Tc2o>7#9m@u^`%kmH~;Y4h4Sdq{K|WO_l~K`f){JVoB5^J-Tv->*O#Ug zm{Xzf{>w-HHaYsG`=-kyTR*U8=ew`%#Z+N)yhPvkH$Txkal-rEzEPnYoN7p|ZLJtA zAsNPjL6OE&IC8hxM=sg9llG<`JGXpx9z|YpZKc6lfgT3RB#&bzR2ibgq>12O&@%GJ zCMwrlHn?+x{>tfEmA%>ZdqPK>VMMgkS@9)#xJ)N*t9BrTPhNZq>K*kwIiN ztM~TjF4>Wa>QQY*%b?MyQHlH|s%FDBi({}-1=luA9cNQ!B&(}hciAb`|CoXbB@qIm z>dMOW=VkEK25NS4>K_c9IZ%$9K z++Yi7OxZYE-D__NNJm7INhp-{Q$-92jFl0eDF97CvcHFg=b!d;-LMSOHMLldomtE} zj>AUuLb*7$uFw-FwMMX7^%a6Nov!HPfmTfPn$Jv$bRBt7Cu$O`OsX{R+PQ z4L^U|O;@Ux)PaM~AK0^J8<)PTVpwan^Dn&bgSWr`_3wS)>7RVzuJ4bHj9qv2E|Vsm z&^t3x9op4nVAEzKT$>)hcEf9K89=PVT9{bj+)Qoy+}W5F?5wU@IKwndM=>BF5u&YQ zgCLuS9g{Rmz2eeqFA~%|J>}0#CzWMhTdj8Lb>O}L9l9L|?wj`5_MNFQa!HMuMU6;LNY{+nmps%{j%QZ`=@d8h51d(YQ zZFQ3#Cq6+CU>ztyLbc~eu|5=72oRD=SL{K_No8DCX?l_)s-+Sn6UL~bwmPtO0C=`Iaoq;=ix`Z5uy z1%r`Ds_R*yf;Y)hD|B0x4Mlrt#9XY~jz2Da0;Eku9n?NXnwn;6rkkO5*$E@koHAm` z5bD}q6~fEJf+L;tFj$;jE%&XAZq_!gcTX?g7Mb5dng*C@T$;)j(bSEN$_&YLo>+i% z?)xi|2ztVFwggteibcqT3^f@m{;smx0OBZ+%AUnIiX_nxQ3h857^sh>!I=>w0?6<+ z+ph+OVKx?J-*A0oJl8vrSvTgEi~7=nSFiaZR|w2hlqzB~8`hSfv!JUYNV;Yx43Yx2 zgrpd{$po4vY(tWm1E?Jyz;dNJSjvE40BU@E;_*i?5{9KGNwT=K0$59@&7az2VmqEz{JfAg>2`j$8L)4tx~yFT^N1GiqY3rL~WXnyQdpQzO8mtA)K^6J#bKK8pQ z3uU_07uR0*+Do5%`s82z)1#(UZ~Cd6)pyIy?`(EvmRD9yy^wR(i`Y2uY^zc=uit#N zQGmwk+{Zri8LkfuZn{iHm2tH`>zu1~{`&KOcjuPBak812vqxa{_$4=9|IuH)WxT9~ z?9#jM`1-C*1GzLrJU)AF{!4e=bH^7x4gs7war_CIkd1mW0i$Y@b_rO_(g0 zuuPJaTDP0^+R_jGpp1DR)Hat0&i?$lF-V&BN@siPp+|G?@;;6FeA zv1Uo~|EFL{;8aJ7Hh?3kG_NRQXR+myRLYRCO&xV7)n44SdC1>hIJ`z#drZeRr8usg zNx}x`X(L^tPC+x0R63)DIz|`L9J&;DiIlROM_4kAXv~vyXBG^L6$WT&biFWIs!k_N z1QI2wrdM5FB7kBd75Wrm9W=>WD;*wTzY*)MvbSr500kgiNTFgA8Ny6s`$h57JLit|?KyJj)EDpg+Whpw(2gxaUKA!pjelpnlqbmGdvx7oYve&;07TGy)NS`5S-pqX)kF+rR&d1{B(D1Jm*ix4u3U!56;t z^?&%guK*F>zjq&&`b8IS1rZktDG4cMKH@Tty+`)%YsC$riN$&qfegy%wx4|yea*J> z_2t8dkM7*Qxtz*N5Kq7S{DJAid){#i>(amO+xxGBsS@F2t=fM2(DUmq9ozM$t9SmjQ!gC)_22u{%5s~!g-rT`x7_fls1hDN`DCfsJ2*0m0L?B; zA3k|1I(9B^7t{} z31}Js7`jeCExU;o0Dy)}W$A`ixk%Qp&yI|wpFh30I1ekUdZQk-8&wh2ErKXFBZ^3u z1M#1tExT9JT!3b08qL=E^WLU>p|^yW*1{liJwxNH3zY?oE@0e{h#5mEx!T%TZCwHQ zQ3^{;!H_bh)rlHY7;%%P)S^-bUE!ma#7%@P45&*uSD-RR1j5}gYl52{S*s?!{aRni zjoYLhgn^lmSab(RP;@O#i=#-Oj%iwM&RObol2}THgz`fg=|T@^CNS|oxD!YJWwk>8 z%LeQJFi2Ggph?8*#E$#28OO28Sr-{89>qDGl}awM#dtp&>vP-4*uH@tob;%jGx4Zy z>B4U!-KK>Roa?2uZkRF*p$o~A09~KHAl-m*Tvi7PZmQ?c*a?7+QLIZlPYU@7TJ< zwo)K4#W8RWB)2x*T}Z!*Uam-(${VaP@8#;tM^=* z%V(1$;2J#m@IE7-y8OngIB?HvKK8()AN|GO0|YB8E6dA^S6#ddmz;(S-AwxWx4fs%fi3|FV5;Cd$vFZ>QP`j z`agXBTYvZW-)ycjD6Q-1EBwN*|7j3QFIgTL-7(bPPl&>2oj!Bm%=FQ>z4bj{B$G2I z?|=0Ek)g3#z0~x?o=dM5fD@*D?^_RS8W|Hn8;$tf+4F<_gSTFP9p(Yn$ye{b3$bX= zC0hjtKMcS1?H~Taul*q)I5u;<&MJKan`sQ!MNcdfq9owNTUR(65OV-ZVKkZzvcNK7A(hgnT7=6<#KA>K+du( z9i-23hH68loT(#8{7l-MS`FtHz4iJ0+<0bnzV1cT$__e(A%%%Zr6VL$8D!aXc`1k$ zOau$YFZ6*i#HMa5y(|NyCvoJjuArsa&h-~P-(%G=#0gkTM=GW$Dntzq8aItDR9i3t zNtX&5i#P!u1G*sVWWXX22}YtjlgqBfzdL=(E=flH69ViD*@C$Hiv<+WKoLB{P7BPe z#AZ9vqA;wtmeyLW)kb5>h~8JsSSiDGI}27+)7^$)hSWxlgohE538qw`vMfh)ENoC4 zRDcTOiLIMYKl@TE#CLu3-n``|AZqRA$Y_6Ya0nAUNP;8`dy1tXl)C0j%`JWUum1j_ z$M>12kk!qLcWt}v^*7|~oD}}C_JudR?oCp{%1ZLkLl570%at0|UU>1?)XbD-XE}8RL#;6Ni9i4HAOFsWGFD)w z8ktnCUia?2Ah&z zZlJLD`}>xrmWVKffTe|5*7oX474U_bGB4VC360en8&hn%&dOR<09cm8eP-IG9>?v4 zr4sMixP9x#{`#|n{p)g;lTCQ4T#7+1RjM&(Nk$_8r_P-I%}@T}#QqiO`qn^CE_=!5 z%^SW{BMWK5)H5T45!!y~Dl!Jf62 zJpA%PyOF9bEO(k~ganjwqH?dPs&G2$B5S$`itfRHE)0g9sAXH3sBWA&S4)?jk-psO z%9`ieQ4}e-pYqCz?%fwskKxe7VGIqyC!sYL;*LxTtyZ(xdu!Yrkdcou*k(r1PC}Sr zJBg1$08dz=*ju1r?}`GXGF)|wG+SXj&qsO+hM}7d2@(nf#oeHB21rXl>$*C+D$4-V zE?gHGs>g~M>9&jiLrDTc|Hb=K{(ml5n4~aq302)6CPu3rU=~MUrb@^sq|s`o%w*M1 z9ht2zEVReU`VCk0o;u#1J;!+1B|K9wEUN2KUw>Xpn?cZoBmo5-53vSZK|DkkaF9_R zNf`;rn|1B{G#k10CnXdD5J5815z+xo>!BKD(u=?_bVOyhckTkWMS}FCqYP6B1ITXV zpoXAJ-Q$r|Y&P^Cv*RyN(0LbR2B3jL#dckUKvfwtO^`fFT7V6Zb}Jw=^TC?m2wV2R zkeScf8+%e|N@gISL<3!C7V*8NWD)5;UbAiLSeR%=7-n7DB#LGC#8U^YR9~)8N*ivQ z`Rm4={{Gz9=ItS{B#J0OEQy|-Y>w~LMu+?V;*%fy*`Iq~wTAPKRqk6X(M3!ti)xQP z_62G{#?^91b1ZaQ}S|A9?Ah&3M*MXLZL) ztR)>)&n{>+AQ_yr*x&!fUwO>?#a6sx`tuu*9EP#-2*BdhNU4 zOuE3&!MLQUjaM&J`YevKO`JSh%$NF$+bOXoURm*$Tf;g34Y#}f>#a++Rv_wsc<*Cz ztG%|oz+%7#FANsBhFTmnq?ZPU{_gWXZBM_`XjJp5%%hJyL9j7BJ0%z`6~;AeY#uOw z`&V!O$+Hg+7E_e-rw*Q)Tdad!me^1+832je!gCX4TnBR5q}*esbD5_oy+QKQNTXJlgA(t{YqoF!c8 zI1E)u6Zl^qDgVbG{=ZzhGhHphnAYmV)1Adeqmg&rY-uQv(dng%S6SXPlxDg9iJHE& z5Lun`!`rjt!*#}pHMPmj!QT?b2)RJ8A zd=xtU*15d0FjEeW56xCw_x&_uEiiQnEEL`JK&h*hIyHqPIB7~sLD|YFfR5k-@>l>$ zKoK03{G_XzdbO(pT>|Qc3s8zQ9TP(Uk${15L=?+d(u5%v$41mnCrCdfXr;b3(%0O& zp=Y#UM}DGEnuh6Pi<(vvc&LlDCWc83T_U2zd~CQM0nAR%Rceh$=zT*Q`-}a|1l`tl z?Hu1YmaR3KdE53p4+Q_4uRnBd_S7xg#shhy<6?rV&bgTrpZoJaef04|rfEO9 z|GD?P`@KK@@k2r+x|@@FR$67&l!Yx<%^rVb&#k+%g(67!>c4!WZc{?&>{Z}T9@0lZI=3LMZSQ~kJ6`vOk#sTi+N~Aw z_`$~~=R4=7*M9T2o*&KxaeHF_^NTLcu*Af`Q;y}wGzodfYpkw5=VCvH!AU$(KXUiq z|DGh9pMLuBfpT$fX7cdi1KY3I@%lI2`t^T)@JA0k`k{ATUvD+Pd(Zy6zxK`L%Hi<= z=eys%ztq#ayu7?{X8EG68%pWklSiJreAnfl`S=HVZ5O!p*b~o%&CnRgany}H$B61W z)`^1)r9zZ1wzCBpCvf~!W#UXdkvdsjG_=T4M01TtrbL>`rg7BT?LVtl>i<`BEn{Z6 zxEXgSEd$O}E3MvsFPFl!u478N741K@CsHDZt;-aT7RoEStAn34tp2x~TL25g+?t$Nlm2)lOx)PfvfYAR&o%(;?5_VUrqWf5W;nDu+wo)(A zJ8RMTc)?pz0v9KqE-p=DQ*uKv-2o8VFoMm#YVdoM!8}(o7LP5>mMXoI+QC< zc)`#nO=CH6wWyNvW?Hlm83};K8CLB%Z&Jer>@sDj3B2IM4^O=I;_IL75l3N>#CMd(x>W*r59ROv~OU#ZK!L@jh9MpxI3_N*W4x3${z z)S_41NVTLDfFFCNX{nYfh;3!6&9!->1L-4YPl>4JIG*Uas57{Qq1y0p@6ZN|M(bN` z-O8MwJX={=bXaNr^PfNb`85uF-YS8S^rLYTR+6C8>Zkx%NQWWWyZ5079@*XQ1eW13uLp~4 zM0F^-b@`?AUSdrJ9g|rm<&^ zzHoB?OPhCYyl&f$`H9to&rP0LTz0(P^=aG0=+5_lnvLld|GaCXz$bG6#~ylgXSJG5 z_ul!5zl0>Tdd!y>rgEtsGn3iC=u|o!Af*@fpM2(yAKuM9-PMImeBVpJ%(XgM)6~-G zSUPvy^~l}-yw9?b*Ud1>m-_oRZqD{)YKyC9pFJ;DJtu{$DEYIyANtb|U3t@`mp}S~ zcXIZgM<1F${?u7x9USAg*OrsZ_&)F0fm3q_XaKj4o!@Xp@v%of`Sl--oH#p&tlp1) zcK_W!cov;Mcy@6iiA(z*tv?}O!gi;;Zex-ez3rd&^``5mPM!YSzrXjZpTFwY-*Rot zV5y}&@Pi+j=~5`nRBlANJ=8EnR%F*dFE$kGIKM7T2i-I#azh{9C7LJbKNW%=GpHX zzu~P=R1`zp*ms?^*ItXu!cyum0~{d6C?SLk%wmGMiIvrkdQTj|8k0&QpBrUDnV?$D zDTjwCr|UcQ^GCzewL5Qe4^d=Oq_Y7h#xMa+cQNUaOCO{1Cm#D1TRubPrPBvxW}Q9T zE9>f-K7aNx+&jZca#xW>e5+eic1zgGYi@y){TL z-QJc~(6}AfYO}C(cei(@10@2m9uW0F0BET|I%x})iid)^RYOCICDc}(6+WoF{|COu z6y=w`^cC=AE}nn-#FK+N`E=WHsE_F`3efqJr-xh7csyR5JIB)S7yh$feV*;yef8$r z;+e+6S{b!)+;3R%j)fy{^tbyjZr)C_cDNEWj>qR#sDG^e#_d&|^S=B$|IYt39FEt@ zW;RL3&1^6CJ`Cz{cxLTb2IaY@QjB3x^ASZVWAPw2gf7`zY% z3rshb+$}^vFnq! zBl8e0d(-%OyYuF;WBT-oHE6w(U-^7IT72pO953zPy!^<Jofj>O@~<+r1S00!C3iH2MF$L z-SU;g&sz`*{dQbslmV#Lbx8GH$Q|ZORzDQ|P6&no{O^BCNb6K2rI+B0K&aHVDDusX zEU261wT4K-T*upeIi2;r8d$|r&Qy`6GaV$nR*!0l;}|(>y|3)nG4@1gOyOQxaPBZs z19>AZU`e0h0n0*EPkiMP}Qu1b;+)l(QkTZyFVydxY2saQxh%toQWvl@cz#*mr zQQ{Gx${o^50B;aT=OnuK@D()=z(b5N5OPQzT4VsQM}ROzTF4fdYPG1E zpNCqjIof9zZp1p0@tysznq#ajbjm zuD*5$_6zKjGu`w2U;g@+zWCjXAi6l5pJX$j7-&$BTYYUX7ua*~jNs6tz*MJZ;Acy1 zo_y!&(#s2P-dI?E;C=6Y`mx8tA}fCJ3tyZ#-)b!R9zs26))u9Y!l4--4DaRo;5t9G zkUVrYsI`aty|FlL;#zxq>4-SKJkQu# zaO&ayw2Sn`yKnZR_S)PMlzu#!9%;>S;~ApI+Y3-V@VWEYe8gHH~YPA1)B`1-XwuWz^Cc=M>3 zUwQDEQ$#EdrsX)Jqrn3U$@QJIPm>7H?9<OVa83P!5*UgJzHuKJ~L6-JL z!{r6msJZ^Y*syMM=eb6Jz$x#%(Uqdo0rkWY!?_m%6GHHz+KYH}uMRD$eU)wm$Xnt8 z9I_ei?+llYtvq)2*xu&;omXDlyLpj-x4#E6A|$cal8TtA0^TZYg%P|3Vt(gY68-)g zmU75rM6gA`2vHuq@mX5N2_{%O66A`Gr&5_xKyGtpO*g6s$w!x4IR0I27+rCZv=DPQBM-0;^15+}v~gVbpvQctZG$`ZeSi z9W{<(k6SqQ9udqKrW^XeJw!Q*d#vx>|2Zu<- zeOVv`1BPnr-ebp+FS7g|%Az$U+(B;~M1HOtbvu4Em1*t-7v2%84MJ8~i8zT@K*TLv zdv_wDU}@FX4@7$$EF8xz7@Oq9HwJHf^BXa_czV3$!wj|_;{8$Fp$bF0{#n3H@$nnz&46Bom19V`LFtR;wGhJ`o8Sc-6h zNQ8-?LEu0TfWP=he&XHlKKb)M`*Y_{J@)?hpA8WFTmQ>nzJ2$0`}pa{A9<{|-fN+b zq2A##3EMoE4Ij@RTbA#8pm(b6!kV!D*}b!O4-OCwSUn-#IBqoB5VPT(5aoO&JYL`$ zCeb^N)lME=82RM*5&EmwqT%?N_Jf1^EcBtp0GUK>UlXCs6_tKDN>&yc23hYN#RThK z882@6TC7M1#}Nsm1%>^ZL6QI?glQ`JhWG>AO~}gH(!!B*x3@ML5uGz1J$p8N``cy@ zok)U&t#l%G2d!Qk-S!h#$4UuppFAkeOzKb1%4;`o=w&usXnqmNw381%`SdIAV@tOl z|6ma`29UgVWvw^lJ8FGv_X56tA*wAGvl?l*TKiO)t?SuV7}J8y#hs;E_ehj9sfdy& zU>>PiaqZ^LbeQIooH*Lx0T#$&V~JyeBZLselu}Z$?1x$7q6#)~PFd@H#YUbRO%3uhJ~5(qQXB&D-SeOIhxF-r;o>r zE$F3yJXJwF)nkVNGfEr*i;y+WI47+n)uu0|RWh@~_&&bE&Ux^MhB*j)rNBc7TjYe3 zezey+cmDLS>|c55YmoK`5R2&VG8VkAZg*8mIj*{u1;B)HE8TDYh~M$E{O@;4m`og>6EOg&It-5!XsUK?+$ciMO@LEEe_LJKawazkIe8{sJVN*=H$i>DN7BoV! z2C=}ZR6y&cyq&ky$d0c)-;H3^!iqBI!OP#DU*1LUp7yCP0FJsH)P<4A;| zz|2HRRI4E*F|p%kp18V1uHZq@ee(Fj=OzK0ZQR{`mNGnW z2Y2MSM>HTu%d%wv7h}JC{Pd~E@IdaniKF4n+kxeAS(XlIi;%O(8saf^hyn?KHV`Vn zhPSTof9m6>{*6ETy_H9X{FR^o)t~ZmOFq`rukWIBff$4krT+^P#|n{HM*8%1GvcYK5; zA*0x08VHGU$P1n%MUh!&sOCgcdT0lNeZJDz^LWoYR120u5lh3f+#*E`DV#Bs0f(8& zrU%n;ffp7Ur;l}ytVDON>D>!$5iFlRbG==Y;1jYio!^}v6<3x;&(k@@ti@bLiLy_6 z@}801>zf;kX=gA0?tXf4ev2%|?2!lWMD4ka*><<})$hFg=Rp1~L& zUhkD%lu83Za1a7R);puLwUsxL#m>3Pn$aPO5T=uKRwyh`%BUlPV6$lQxNSojPiWvy2gCq}DZOu=fSV3M?`bkj-_P z5nC6uOBnSIN$pEzrA5{xML(_sk6<=HRuf9BJ4Bd(ebsC+cGbj0x!r58ckI*K zBwXNpF^muDL2YG$Hjh$mPnjx;$sEgv=N?Z=v=t>$9;~E%n4(Ls?!UI6K*sk{Z+W3+23PmPoPnn4z9ttm&k0#A z6TT3uOsm(^%WSl3Bpc>Y)_bsB3x;D~B@NmvTUc(@BAlumA(XIy08ulkl&Xx+NxgIf z2K9NmwnR(|V(W>kS;4_DZA)KyS2M$`?K&<OJ5^eW&mm-I228XGbQO^`=Sj5g}_`$gOz?dIQhsSUA{>tmmmB-qH)z$W6YlGFN zzWZ3v76kvTUuTyt?-J4VD3YdD6cOfRaV^wFf)8ioTn^HrD6~|%lqxT1z0Nrg1fiG! z22U{N3=4t?BLopj4@ZK4%;6`Qn`x~vC+aN;BrQs#Q){%t2B;ti02~kiivSa;VVWr( ztB@lige!7#I2;4Olwq}B7hZq_7z(@!IMbGviso7yk9D=vIoA*?T|d(^3|JAS3#+kr z7+C}eF{7liidt;7)lv~$(YwT9iV+-Id!dREMg%#GJVSuNvyfQtLXm9Ux^eT3OQ01E zgaP7^{Vft5{bqr4Gr|Y}_En&^b=a6H77x?=_{;nMeXBYBTj{~=WaR`zfyqM59MT04 zD7>~dl!bS}C?LRb3{F^_5t2LSjAq0ON(I8ClzKYL27TLJTIzP&yRA936IDc_w#EU+ z{;eW_9L5ME53VfZuYUHupZeh7%)=b9iT5`|YS-E?Eg%12nx4zeybC8D&mc+;J ztrRCZ`%gah;)9PqUn_rnZ9W5-8o9GODxZH1f9n|&hxe=83c@p?LYdb znkSF!foy3~@?=iCXe;mb^3y@22E*xmlZRm^sWl5K1&=&xs3J1bV4Qj95XOWuN4O^e z3KA;f5;yA$YdJEXd*zMKe)$rlQ;fVq#e>II+h-qs^qn6*+FkZzd*{ktz0mocOU+46 z3w=H(3pCuledY32DRPl3Pe~Sg0@jrnIn0njyDaF}lG!cT)`1L|_h^1U@B7ShW4Fh5 z=L!8ExQ+FE-!xOwg97e2rD z)o-3(bXO{d1G%6ZKL=7C7+&35S(W0}G0wI2&Vsja-*%?@LI3|ZEGKvK(XIvUIR(yv8E;EK9#P~WFlC|22_tbF zBr1=r?J+J(<5W2#ah;PorPKn-OPOVIRq$@N8#h{ta)dnb9*hCbf9EPUa)({HwsG@L zyPx4xkfl1`ySX>G)Cp$A-24W^r;$ulI0NDZjvFp$geY#~&Ro6O7Km$1J>kSypJmoF zY7{LCR_46SQK`Jq&N(+Ttm;teFnF*MyGdh=G^ID*N~ep`WTh%nQ)WgRXOvSVgbZUS zr7R0%g)o|od*f3l&(`W~rR{!ymS)Bo>@7C<0G#9Ycqj4?Jo5GTz4KQeo!<>zG^zi$ z`~CUB^%HMgdG)oM{A;hi=W;rq+f~TlMDbCmZ6o)(znhw@eD6DhrKW~F=1peJ={zk5 zs+OZQ7VJ-@v`Pnjp*z1YTc1s}1>-;)3mAj5Rsqlo!h67&@qhiOPY5X!kVSXnzd_rQD7sP>i7!NJJxC}p>H#okb4{Ubqi#K9uugdtg6YtsS&QIFW!sEwoJp1JGT=(_&e`Z0>hNQXF$GU#X#<7>&JaSzdZ@}dXPiHKZ0WJbzZ1tDa3$bBfrTE0C{UKz>vUdXqH$fc*Kpq=|(P7Lo0`HIk z(;To{I9cSyLQ?i!v=}@X@SREgErnrmvNEtrt&CT~IzWKu{OHVT9Cem<%jm|2oJs^n zGn*!ihD=flK}_2%2v!&-uGED#vh)g}``*%o5K5_YTq$J=nog7{10$3E*z64R-ZXQ0 z=?>m>au(RBFm0hR;=&|07jmd-H#hD+{NVf}r)j^*Ct0|8FwUi&z}$zM&;5b-ydaXX zsa;$M4zhmKm+*yKjjNZ!U->1qKmIAj#3c7|qlVGzgs*g38xkIvjvZ3pSco3A%^N;_ z6eWPgYN>a3*DH%!m&?>(!mr(CC(iGlTyR$##4R3!?Oqrz6!Id4SOfJw@z4a;@nKVk zi4%dxoyFDmLMLb|(tYG~`v)F!G;y=q4O`o|ZD%|AXuUt!yk1PMS-s)Q{V3bs!1x71 z5C-pkY?Q9xC!9Ly&zQA#wtNqqmqMSN)n8+XQcd{Ux1 zM#vEff%D^Z8oWXwq553(pu2edzRM<4jhFjx<9h2_oemG56!9TWn_u7qp{1XkiywA4Jcl!3pM z?fGVj6VI&=9Rk4tBT6a%jS2$B*r7i5WN`f_+x_Nz`qPueU$!fgLWe_D%j;x3NeRq6 zb{cqz!D@*N5Dhkl!}9)r8^QvX5Bt4ams`t^)FVN|`dnCR@o+nvrONh3vy}zbZPa?P z9Zn1EBZRE?$XRQZ2BW|m>zMMOB|qrl?#lGciEy%cY&Jay$%t5LU0ykZ3UC5D0*-lH zxwVW{n1r+OGK4}1w?ce9<<_(wIyL{?ejkH4(QGBLGqZj-UVQlN5ABN!5KIhPxag& z+SnCayF;eW4#&IGYy@(@jv%%H#)7lR6uQi1SxQcLyDjR?ButvxyCiwz6L0?q%X~YR z&5d4mr*~v)XXU$B${VAfeDPalZ!*E8?seR1ZF^PP;oD42BA*0}WHLNP@pt~xe?EBP z(PadE=cs|SKT5W?^x$Ag`2jJJ^`(?fYaAxOQKT3!LOCS@MCjB6P(_YnbeLmINWf@Z z3w@1g=H22_^YpnhWgXw#n)G(n?cv^NZ+p6ZOYYu+!EKNS02#Pk8V85v@msgPL-r-W z2)}h>!w3=Zham$~%fJy%G4eBgI&43&Jl}1E?>y06S!|lSvlMAc>GIq{y<5*sYOHnO zJ@M5v7hz8Tz+1Opql4KD8*>(il;Ay*@9~^?e_iW0$2*s$JMbZ(8W;~Q1)@RLXOKcL z#csF1eQ>-BA2@eV3n74-RKm=ngWWIR9xmHDgl@`4o{%b_~nToI3y9i32egoLfC|b+I*hbamt3`?Fhr@$da0CLED! zRRS==lrnzriD1SUqQq73mR3Sg2cA16mGhi4qFW?Cy4;#yXziGMV`F33ACzTDFks3E zCKa7(5XByB<;#f)!H58Hh*FwKtc_7+U*HI1lNNof0IL2(3{mQFiAJ0Rm|_;Y)Q7q;)^LS&CaE*^=|cJoSTF*iW@KhI5ZYDiJlVMCx~4Jfy$ZxzU3FGa6j@PUG04 z-KB@~W;+med9D$R!*pylk_}CWwg;YJUo#^*YnjWM`loD&fRK@cT6j1&(@5ON+0 z&MDm;;Hu!QI@Esws|lg&iLcdAvl+KKwPp>+yd0us9R%YE1uGSCxhbWNBM2Bc?2s-j z;y^Kv0>L@O46oSpEvjwV?X6G0^yxvf{-ck4>`#Atz4L{ig+jf==3e!xgj`yMRKL+} zPIs9IyId^U{vMUH=3@`lm^uOeTb_+9a=Qa|^KN~(f8H)ky=_~U0t%ed?RKNllD%z$ zNML{f5byQ9XY3C-Y(zrLA{rz$rdojyXc0FP6GS%-ic9NgxaFsN!_n4d*nI)gOHhun zhr@}TCZb|MaRs{x#;kG>pw2fA0XPEe5Qa*n<^XU2%36&rwSGylPn~@1Z7WN)247n1 z#Wh=&ft+wVlazSD@zh$t1QBdpHBQG6Fm`wt$Pk(WaEj}IW-i~wlRnBtR(xCIH>Z;w zSpbj0҅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 JPDHLkV1fewNY4NO literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/i.png b/src/common/assets/theme/images/i.png new file mode 100644 index 0000000000000000000000000000000000000000..9dca56fcf8d68919b14cb6a023e874ad148fb135 GIT binary patch literal 351 zcmeAS@N?(olHy`uVBq!ia0vp^{2!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD4`zU6XN>v)u#uKUa#JC zuw&A)>$jey7IiINwL7nB;@(5&C(c^CW!H&gr>+6j+}d2a9;k(}B*-tA!Qt7BG!Q4r z+uensgH_f8$YC$>^mS#w$;>FqAXv6!_iUh$hNp{T2*>s01O+aGLlQn}25uQjJ%aZb zQdu}1Bqs6+Xs+WuGV|O428Mq>Sac>&JH!Okqgvt`QIe8al4_M)lnSI6j0_Adbqy?Z z4J|_q4XupLtW1rx4J@q;3_jNEPDRm>o1c=IRteN#0MuZtYhV~+XarPeWoQo3uq&kY Q2T%ipr>mdKI;Vst0Br1S{Qv*} literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/icon_jnode.png b/src/common/assets/theme/images/icon_jnode.png new file mode 100644 index 0000000000000000000000000000000000000000..a0046e549572de930c60ac7c9667b99f04137c84 GIT binary patch literal 3357 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 literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/indent.png b/src/common/assets/theme/images/indent.png new file mode 100644 index 0000000000000000000000000000000000000000..c1bf4a41d9be3a7fb78f49ba8af9944ea84ff0b2 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^{2Eakt!I-ST zXK+ZuN6o-3L#apb9z!Y%r-Q^qJ^{^jygV*U4F7(x=&;^dqy*H!;OXk;vd$@?2>=3T BG)({i literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/indent_hover.png b/src/common/assets/theme/images/indent_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..bc346953fc82b2002249682ada53053d4f5c271a GIT binary patch literal 155 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 R-*Xq7ytIl`J=84h{{UfQ?=%1a literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/plate.png b/src/common/assets/theme/images/plate.png new file mode 100644 index 0000000000000000000000000000000000000000..bd9816ca3c2e25e1adc9aa3ec1eb6c19333485bf GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrA!2~3KZCES|r1U&p978G?Sr2ZMJix%xdhn6_ z^yia}xK7=;Dzx+QyBBgwEh_tB54qZ%^htgeve(|*fZtW$z4S3qCxfS}pUXO@geCxu CVjzwH literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/plateB.gif b/src/common/assets/theme/images/plateB.gif new file mode 100644 index 0000000000000000000000000000000000000000..5afa8756d3b0b77d79dad94c423f7f893cb8d300 GIT binary patch literal 155 zcmZ?wbhEHbWMq(IIKsg2{@vSiXV1KQ`{vcFS9^Bv{{G{~^XJc}O`A4%?%YiqH{QN= z^XHH6|Ni}Z_Vmf;PamHE$N**RLNuc<}!H vI|fvs_>%=JpaUX7b~3O^D450aho-Q#M0P*R;8939yTGN8^*df(T2Olm2;eZXX={7X&e`yXrN zADbjcH>9rKwodwd@#QVDyOwdruY5J@d+pA3ui5W}T3CC>mB#?BV(@hJb6Mw<&;$Ty Cc{`v0 literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/images/plate_top.png b/src/common/assets/theme/images/plate_top.png new file mode 100644 index 0000000000000000000000000000000000000000..3c3296cedc77dace16cf221921008b5e8eefc257 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{M!2~3ezCWG-q~bkY978G?WjmRL8XOoHcAqti ztGj=uj91)4^J1xNgU#sznfB;FkI53DSL3#GE}oHm|HilG1K$Ol{;bWFHVJ)d;V*N$ zZm;Wtq)4;F7dEfcP7S?is{4EA<7&BB^F8-#7~EPE|E+l~l>@Yj!PC{xWt~$(695fa BH(&q& literal 0 HcmV?d00001 diff --git a/src/common/assets/theme/style.css b/src/common/assets/theme/style.css new file mode 100644 index 0000000..565a233 --- /dev/null +++ b/src/common/assets/theme/style.css @@ -0,0 +1,312 @@ +*, +*::before, +*::after { + box-sizing: border-box; +} + +body { + font-family: arial, sans-serif; + color: #333; + min-width: 850px; + background: #003 url(images/bg.png) repeat-y scroll left top; + margin: 0; + font-size: 95%; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin-bottom: 0.5rem; + font-family: inherit; + font-weight: 500; + line-height: 1.2; + color: inherit; +} +h1 { + font-size: 1.802em; +} +h2 { + font-size: 1.602em; +} +h3 { + font-size: 1.424em; +} +h4 { + font-size: 1.266em; +} +h5 { + font-size: 1.125em; +} +h6 { + font-size: 1em; +} + +a { + color: #f66; + text-decoration: none; +} +a:hover { + color: #36f; + text-decoration: none; +} + +table { + width: 100%; +} + +tr, +td, +th { + text-align: left; +} + +.clearfix::after { + content: ""; + display: block; + clear: both; +} + +.hidden { + display: none; +} + +.text-center { + text-align: center; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} + +.font-weight-bold { + font-weight: bold; +} +.font-italic { + font-style: italic; +} + +.even, +.odd { + padding: 2px; + border-bottom: 2px groove #fff; + font-size: 95%; +} + +.plate { + background-image: url(images/plate.png); + border-left: 3px solid #999; + border-right: 3px solid #999; + color: #000; +} +.plate::before { + content: ""; + display: block; + height: 15px; + background: url(images/plate_top.png) repeat-x left top; +} +.plate::after { + content: ""; + display: block; + height: 15px; + background: url(images/plate_bottom.png) repeat-x left bottom; +} +.plate a { + color: #036; +} +.plate a:hover { + color: #36f; +} +.plate h4 { + color: #369; + font-weight: bold; + border-bottom: 2px groove #fff; +} +.block .blockTitle { + height: 21px; + margin-bottom: 0.4rem; + padding: 0 10px 0 32px; + background: url(images/arrow.png) no-repeat 7px top; + color: #369; + line-height: 21px; + font-weight: bold; +} +.block .blockContent { + padding: 0 10px; + font-size: 13px; +} + +.plate td { + padding: 0; + vertical-align: top; + font-family: Verdana, Arial, Helvetica, sans-serif, serif; + line-height: 150%; +} + +.plate th { + padding: 4px; + border-bottom: 2px groove #fff; + vertical-align: middle; + color: #66c; +} + +.plate .head { + padding: 5px; + font-weight: bold; + border-bottom: 2px groove #fff; + font-size: 95%; +} + +#header .left { + float: left; +} +#header .logo { + background-image: url(images/logo.png); + height: 100px; + width: 400px; +} +#header .logo a { + display: block; + width: 100%; + height: 100%; +} +#header .right { + margin: 5px 15px; + text-align: right; +} +#header .searchInput { + margin: 0 5px; + width: 180px; + background-color: #336; + color: #ccc; +} +#header .searchButton { + margin: 0 15px 0 0; + border-top: 2px groove #999; + border-left: 2px groove #999; + border-right: 2px ridge #fff; + border-bottom: 2px ridge #fff; + background-color: #336; + color: #ccc; + font-size: 14px; +} + +#footer { + text-align: right; + margin-top: 30px; +} +#footer .plate { + border: none; +} +#footer .plate::before { + height: 20px; +} +#footer .plate::after { + height: 5px; + background: none; +} +#footer .copyright { + color: #366; + font-size: 80%; + margin-right: 10px; +} +#footer .links { + margin-right: 10px; +} +#footer .links img { + margin: 10px 3px; +} +#main { + margin: 0px 5px; + line-height: 1.5; +} + +.leftcolumn { + float: left; + width: 230px; +} +.leftcolumn .block { + margin: 10px 5px 10px 10px; +} +.centercolumn { + float: right; + width: calc(100% - 230px); +} +.centercolumn > .block, +.centercolumn > .plate { + margin: 10px 10px 10px 5px; +} +.centerCcolumn > .block { + margin: 10px 10px 10px 15px; +} +.centerLcolumn { + float: left; + width: 50%; +} +.centerLcolumn .block, +.centerRcolumn .block { + margin: 10px; +} +.centerRcolumn { + float: right; + width: 50%; +} +.mainContent { + margin: 0 20px; +} +.mainContent table.listTable { + border-collapse: collapse !important; +} +.mainContent table td { + vertical-align: top; +} + +ul.mainmenu { + list-style-type: none; + margin: 0; + padding: 0; +} +.mainmenu a, +.mainmenu a.menuTop, +.mainmenu a.menuMain, +.mainmenu a.menuSub { + display: block; + text-indent: 15px; + color: #333; + background: url(images/indent.png) no-repeat left 2px; +} +.mainmenu a:hover { + color: #f00; + background: url(images/indent_hover.png) no-repeat left 2px; +} + +.welcome { + color: #ccc; + margin-bottom: 30px; + font-size: 14px; + min-height: 420px; + background: url(images/brain-bike.png) no-repeat right bottom; +} +.welcome h3 { + margin-top: 1.5em; +} +.welcome .articles { + padding-left: 30px; +} +.welcome .articles .article .title { + display: inline-block; + max-width: calc(100% - 400px); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.welcome .announce { + max-width: calc(100% - 200px); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/src/common/assets/xoops.css b/src/common/assets/xoops.css new file mode 100644 index 0000000..88f768a --- /dev/null +++ b/src/common/assets/xoops.css @@ -0,0 +1,17 @@ +img {border: 0;} + +#xoopsHiddenText {visibility: hidden; color: #000000; font-weight: normal; font-style: normal; text-decoration: none;} + +.pagneutral {font-size: 10px; width: 16px; height: 19px;text-align: center; background-image: url(./images/pagneutral.gif);} +.pagact {font-size: 10px; width: 16px; height: 19px;text-align: center; background-image: url(./images/pagact.gif);} +.paginact {font-size: 10px; width: 16px; height: 19px;text-align: center; background-image: url(./images/paginact.gif);} + + +#mainmenu a {text-align:left; display: block; margin: 0; padding: 4px;} +#mainmenu a.menuTop {padding-left: 3px;} +#mainmenu a.menuMain {padding-left: 3px;} +#mainmenu a.menuSub {padding-left: 9px;} + +#usermenu a {text-align:left; display: block; margin: 0; padding: 4px;} +#usermenu a.menuTop {} +#usermenu a.highlight {color: #0000ff; background-color: #fcc;} diff --git a/src/common/blocks/MainMenu.tsx b/src/common/blocks/MainMenu.tsx new file mode 100644 index 0000000..beb7251 --- /dev/null +++ b/src/common/blocks/MainMenu.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../config.js'; +import Functions from '../../functions'; +import mainMenus from '../assets/main-menu.json'; + +interface Props { + lang: MultiLang; +} + +const MainMenu = (props: Props) => { + const { lang } = props; + const links = mainMenus.map((item, idx) => { + const title = Functions.mlang(item.title, lang); + const style = idx === 0 ? "menuTop" : "menuMain"; + const link = item.link.match(/^https?:\/\//) ? + {title} : + {title}; + return
  • {link}
  • + }); + return ( +
      + {links} +
    + ); +} + +export default MainMenu; diff --git a/src/common/blocks/SelectLang.tsx b/src/common/blocks/SelectLang.tsx new file mode 100644 index 0000000..7c1480b --- /dev/null +++ b/src/common/blocks/SelectLang.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { RouteComponentProps, withRouter } from 'react-router'; +import { MultiLang } from '../../config'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +const SelectLang = (props: Props) => { + const { lang, history } = props; + const langs: MultiLang[] = ['en', 'ja']; + const titles = { + en: 'English', + ja: 'Japanese', + }; + return ( +
    + + +
    + ); +} + +export default withRouter(SelectLang); \ No newline at end of file diff --git a/src/common/lib/LangFlag.tsx b/src/common/lib/LangFlag.tsx new file mode 100644 index 0000000..191fb21 --- /dev/null +++ b/src/common/lib/LangFlag.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { RouteComponentProps, withRouter } from 'react-router'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../config'; +import mlangEnglish from '../assets/images/mlang_english.gif'; +import mlangJapanese from '../assets/images/mlang_japanese.gif'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +const styleLink = { + fontSize: '8px', +}; +const styleImage = { + verticalAlign: 'middle', + border: '1px solid #000', +}; +const langResources = { + en: { image: mlangEnglish, title: 'English' }, + ja: { image: mlangJapanese, title: 'Japanese' }, +}; + +const LangFlag = (props: Props) => { + const { lang } = props; + const params = new URLSearchParams(props.location.search); + const flagLang = lang === 'en' ? 'ja' : 'en'; + params.set('ml_lang', flagLang); + const url = props.location.pathname + '?' + params.toString(); + return ( + + {langResources[flagLang].title} + + ); +} + + +export default withRouter(LangFlag); diff --git a/src/common/lib/LinkImage.tsx b/src/common/lib/LinkImage.tsx new file mode 100644 index 0000000..251e2cb --- /dev/null +++ b/src/common/lib/LinkImage.tsx @@ -0,0 +1,58 @@ +import React, { Component } from 'react'; +import { Link } from 'react-router-dom'; + +interface Props { + url: string; + title: string; + image: string; + imageHover?: string; +} + +interface State { + image: string; +} + +class LinkImage extends Component { + + constructor(props: Props) { + super(props); + this.state = { + image: props.image, + }; + this.handleMouseOver = this.handleMouseOver.bind(this); + this.handleMouseOut = this.handleMouseOut.bind(this); + } + + handleMouseOver() { + const { imageHover } = this.props; + if (typeof imageHover !== 'undefined') { + this.setState({ image: imageHover }) + } + } + + handleMouseOut() { + const { image: imageNormal, imageHover } = this.props; + if (typeof imageHover !== 'undefined') { + this.setState({ image: imageNormal }) + } + } + + render() { + const { url, title } = this.props; + const image = {title}; + if (url.match(/^(\/|\.)/) === null) { + return ( + + {image} + + ); + } + return ( + + {image} + + ); + } +} + +export default LinkImage; diff --git a/src/common/lib/Loading.tsx b/src/common/lib/Loading.tsx new file mode 100644 index 0000000..7eb83da --- /dev/null +++ b/src/common/lib/Loading.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import Spinner from 'react-spinner-material'; + +const Loading = () => { + return ( +
    + +
    + ); +} + +export default Loading; \ No newline at end of file diff --git a/src/common/lib/NoticeSiteHasBeenArchived.tsx b/src/common/lib/NoticeSiteHasBeenArchived.tsx new file mode 100644 index 0000000..c44a297 --- /dev/null +++ b/src/common/lib/NoticeSiteHasBeenArchived.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; + +interface Props { + lang: MultiLang; +} + +const NoticeSiteHasBeenArchived = (props: Props) => { + const { lang } = props; + const notice = '[en]This site has been archived since FY2019 and is no longer updated.[/en][ja]このサイトは、2019年度よりアーカイブサイトとして運用されています。[/ja]'; + return

    {Functions.mlang(notice, lang)}

    ; +} + +export default NoticeSiteHasBeenArchived; \ No newline at end of file diff --git a/src/common/lib/PageNotFound.tsx b/src/common/lib/PageNotFound.tsx new file mode 100644 index 0000000..e67d1cc --- /dev/null +++ b/src/common/lib/PageNotFound.tsx @@ -0,0 +1,52 @@ +import React, { Component } from 'react'; +import Helmet from 'react-helmet'; +import { RouteComponentProps, withRouter } from 'react-router'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +class PageNotFound extends Component { + + private url = '/'; + private timer: NodeJS.Timer | null = null; + + goToTopPage() { + if (this.props.location.pathname !== '/') { + if (this.timer) { + clearTimeout(this.timer); + } + this.timer = setTimeout(() => { + this.timer = null; + this.props.history.push(this.url); + }, 5000); + } + } + + componentWillUnmount() { + if (this.timer) { + clearTimeout(this.timer); + } + } + + render() { + const { lang } = this.props; + this.goToTopPage(); + return ( +
    + + Page Not Found - {Functions.siteTitle(lang)} + +

    Page Not Found

    +
    +

    The page you were trying to access doesn't exist.

    +

    If the page does not automatically reload, please click here

    +
    +
    + ); + } +} + +export default withRouter(PageNotFound); \ No newline at end of file diff --git a/src/common/lib/UserRankStarImage.tsx b/src/common/lib/UserRankStarImage.tsx new file mode 100644 index 0000000..dd5f9e7 --- /dev/null +++ b/src/common/lib/UserRankStarImage.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import imageRank2 from '../assets/images/rank3dbf8e94a6f72.gif'; +import imageRank3 from '../assets/images/rank3dbf8e9e7d88d.gif'; +import imageRank4 from '../assets/images/rank3dbf8ea81e642.gif'; +import imageRank5 from '../assets/images/rank3dbf8eb1a72e7.gif'; +import imageRank6 from '../assets/images/rank3dbf8edf15093.gif'; +import imageRank7 from '../assets/images/rank3dbf8ee8681cd.gif'; +import imageRank1 from '../assets/images/rank3e632f95e81ca.gif'; + +interface Props { + lang: MultiLang; + rank: number; + posts: number; +} + +const userRanks = [ + { title: '[en]Just popping in[/en][ja]新米[/ja]', min: 0, max: 20, special: false, image: imageRank1 }, + { title: '[en]Not too shy to talk[/en][ja]半人前[/ja]', min: 21, max: 40, special: false, image: imageRank2 }, + { title: '[en]Quite a regular[/en][ja]常連[/ja]', min: 41, max: 70, special: false, image: imageRank3 }, + { title: '[en]Just can\'t stay away[/en][ja]一人前[/ja]', min: 71, max: 150, special: false, image: imageRank4 }, + { title: '[en]Home away from home[/en][ja]長老[/ja]', min: 151, max: 10000, special: false, image: imageRank5 }, + { title: '[en]Moderator[/en][ja]モデレータ[/ja]', min: 0, max: 0, special: true, image: imageRank6 }, + { title: '[en]Webmaster[/en][ja]管理人[/ja]', min: 0, max: 0, special: true, image: imageRank7 }, +]; + +const UserRankStarImage = (props: Props) => { + const { lang, rank, posts } = props; + const findRank = (posts: number) => { + const rank = userRanks.find((userRank) => { + if (posts >= userRank.min && posts <= userRank.max) { + return true; + } + return false; + }); + return typeof rank !== 'undefined' ? rank : userRanks[0]; + + } + const userRank = rank > 0 && rank <= 7 ? userRanks[rank - 1] : findRank(posts); + const title = Functions.mlang(userRank.title, lang); + return {title}; +} + +export default UserRankStarImage; \ No newline at end of file diff --git a/src/common/lib/XoopsCode.tsx b/src/common/lib/XoopsCode.tsx new file mode 100644 index 0000000..d101302 --- /dev/null +++ b/src/common/lib/XoopsCode.tsx @@ -0,0 +1,138 @@ +import React, { ReactElement } from 'react'; +import ReactHtmlParser, { convertNodeToElement } from 'react-html-parser'; +import { HashLink } from 'react-router-hash-link'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; + +interface Props { + lang: MultiLang; + text: string; + dohtml?: boolean; + dosmiley?: boolean; + doxcode?: boolean; + doimage?: boolean; + dobr?: boolean; +} + +const preConvertXCode = (text: string, doxcode: boolean): string => { + if (doxcode) { + return text.replace(/\[code\](.*)\[\/code\]/sg, (m0, m1) => { + return '[code]' + Functions.base64Encode(m1) + '[/code]'; + }); + } + return text; +} + +const postConvertXCode = (text: string, doxcode: boolean, doimage: boolean): string => { + if (doxcode) { + return text.replace(/\[code\](.*)\[\/code\]/sg, (m0, m1) => { + const text = convertXCode(Functions.htmlspecialchars(Functions.base64Decode(m1)), doimage); + return '
    ' + text + '
    '; + }); + } + return text; +} + +const convertClickable = (text: string) => { + text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+[a-zA-Z0-9=]))/g, (...matches) => { + return matches[1] + '' + matches[2] + ''; + }); + text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/:.]+)([a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+)/g, (...matches) => { + return matches[1] + '' + matches[2] + ''; + }); + return text; +} + +const convertXCode = (text: string, doimage: boolean): string => { + // TODO: implement + return text; +} + +const convertSmiley = (text: string) => { + // TODO: implement + return text; +} + +const convertBr = (text: string): string => { + return text.replace(/(\r?\n|\r)/g, '
    '); +} + +interface TransformParsedNode { + type: string; + next: object | null; + prev: object | null; + parent: object | null; + name: string; + attribs: any; + children: object[]; + data: string; +} + +const cssConvert = (text: string): object => { + const ret: any = {}; + text.split(';').forEach((line) => { + const line_ = line.trim(); + if (line.length === 0) { + return; + } + const kv = line_.split(':'); + const key = Functions.camelCase(kv[0].trim()); + const value = kv[1].trim(); + ret[key] = value; + }) + return ret; +} + +const transform = (node: object, idx: number): ReactElement | null | void => { + const node_ = node as TransformParsedNode; + if (node_.type === 'tag' && node_.name === 'a') { + const url = (node_.attribs && node_.attribs['href']) || '/'; + const download = (node_.attribs && node_.attribs['download']) || ''; + const rel = (node_.attribs && node_.attribs['rel']) || ''; + const isFile = download !== '' || url.match(/\.(zip|pdf|png|gif|jpg)$/); + const isExternal = /external/.test(rel) || /^(mailto|https?:?\/\/)/.test(url); + if (!isFile && !isExternal) { + const style = (node_.attribs && node_.attribs['style']) || ''; + const title = (node_.attribs && node_.attribs['title']) || null; + return + {node_.children.map((value: object, index: number) => { + return convertNodeToElement(value, index, transform); + })} + ; + } + } + if (node_.type === 'tag' && node_.name === 'img') { + const src = (node_.attribs && node_.attribs['src']) || ''; + node_.attribs['src'] = src.replace('`XOOPS_URL`', process.env.PUBLIC_URL); + return convertNodeToElement(node_ as object, idx, transform); + } +} + +const XoopsCode = (props: Props) => { + const { lang } = props; + let text = props.text; + const dohtml = !!props.dohtml; + const dosmiley = !!props.dosmiley; + const doxcode = !!props.doxcode; + const doimage = !!props.doimage; + const dobr = !!props.dobr; + text = preConvertXCode(text, doxcode); + if (!dohtml) { + text = Functions.htmlspecialchars(text); + text = convertClickable(text); + } + if (dosmiley) { + text = convertSmiley(text); + } + if (doxcode) { + text = convertXCode(text, doimage); + } + if (dobr) { + text = convertBr(text); + } + text = postConvertXCode(text, doxcode, doimage); + text = Functions.mlang(text, lang); + return
    {ReactHtmlParser(text, { transform })}
    ; +} + +export default XoopsCode; \ No newline at end of file diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..d9725ae --- /dev/null +++ b/src/config.ts @@ -0,0 +1,17 @@ +const SITE_TITLE = 'Dynamic Brain Platform'; +const SITE_SLOGAN = 'Official Site'; +const GOOGLE_ANALYTICS_TRACKING_ID = 'UA-23709948-1'; +const XOONIPS_ITEMTYPES = ['model', 'data', 'tool', 'book', 'paper', 'conference', 'url', 'presentation', 'simulator', 'stimulus', 'memo', 'files', 'binder']; +const PICO_MODULES = ['documents', 'hackathon']; + +export type MultiLang = 'en' | 'ja'; + +const Config = { + SITE_TITLE, + SITE_SLOGAN, + GOOGLE_ANALYTICS_TRACKING_ID, + XOONIPS_ITEMTYPES, + PICO_MODULES, +} + +export default Config; diff --git a/src/credits/Credits.tsx b/src/credits/Credits.tsx new file mode 100644 index 0000000..d51997e --- /dev/null +++ b/src/credits/Credits.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import CreditsAboutUs from './CreditsAboutUs'; +import CreditsPage from './CreditsPage'; +import CreditsUtils from './lib/CreditsUtils'; + +interface Props { + lang: MultiLang; +} + +const Credits = (props: Props) => { + const { lang } = props; + return ( + <> + + {CreditsUtils.getTitle(lang)} - {Functions.siteTitle(lang)} + + + } /> + ) => } /> + + + + ); +} + +export default Credits; diff --git a/src/credits/CreditsAboutUs.tsx b/src/credits/CreditsAboutUs.tsx new file mode 100644 index 0000000..fc52fae --- /dev/null +++ b/src/credits/CreditsAboutUs.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import XoopsCode from '../common/lib/XoopsCode'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import CreditsUtil from './lib/CreditsUtils'; +import NoticeSiteHasBeenArchived from '../common/lib/NoticeSiteHasBeenArchived'; + +interface Props { + lang: MultiLang; +} + +const CreditsAboutUs = (props: Props) => { + const { lang } = props; + const title = Functions.mlang(CreditsUtil.getAboutUsTitle(), lang); + return ( + <> +

    {title}

    + + + + ); +} + +export default CreditsAboutUs; diff --git a/src/credits/CreditsPage.tsx b/src/credits/CreditsPage.tsx new file mode 100644 index 0000000..288b7f2 --- /dev/null +++ b/src/credits/CreditsPage.tsx @@ -0,0 +1,46 @@ +import moment from 'moment'; +import React from 'react'; +import { RouteComponentProps } from 'react-router'; +import PageNotFound from '../common/lib/PageNotFound'; +import XoopsCode from '../common/lib/XoopsCode'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import CreditsUtils from './lib/CreditsUtils'; +import NoticeSiteHasBeenArchived from '../common/lib/NoticeSiteHasBeenArchived'; +import Helmet from 'react-helmet'; + +interface Params { + id: string; +} + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +const CreditsPage = (props: Props) => { + const { lang } = props; + const params = props.match.params; + if (params.id === '') { + return ; + } + const pageId = parseInt(props.match.params.id, 10); + const page = CreditsUtils.getPage(pageId); + if (page === null) { + return ; + } + const title = Functions.mlang(page.title, lang); + return ( + <> + + {title} - {Functions.siteTitle(lang)} + +

    {title}

    + +
    {Functions.mlang('[en]Last Update[/en][ja]最終更新日[/ja]', lang)} : {moment(new Date(page.lastupdate * 1000)).format('MMMM Do, YYYY')}
    +
    + + + ); +} + +export default CreditsPage; \ No newline at end of file diff --git a/src/credits/CreditsXoopsPathRedirect.tsx b/src/credits/CreditsXoopsPathRedirect.tsx new file mode 100644 index 0000000..97d34ac --- /dev/null +++ b/src/credits/CreditsXoopsPathRedirect.tsx @@ -0,0 +1,53 @@ +import React, { Component } from 'react'; +import { Redirect, RouteComponentProps, withRouter } from 'react-router'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +class CreditsXoopsPathRedirect extends Component { + + getRedirectUrl(): string { + const { location } = this.props; + const name = 'credits'; + const pathname = location.pathname || ''; + const query = new URLSearchParams(location.search); + const search = new RegExp(`^/modules/${name}(?:/+(.*))?$`); + const matches = pathname.match(search); + if (matches === null) { + return ''; + } + const path = matches[1] || ''; + switch (path) { + case '': + case 'index.php': { + const id = query.get('id'); + if (id !== null) { + if (id.match(/^\d+$/) !== null) { + return '/' + name + '/' + id; + } + return ''; + } + return '/' + name; + + } + case 'aboutus.php': { + return '/' + name; + } + } + return ''; + } + + render() { + const { lang } = this.props; + const url = this.getRedirectUrl(); + if (url === '') { + return ; + } + return ; + } +} + +export default withRouter(CreditsXoopsPathRedirect); diff --git a/src/credits/block/CreditsMenu.tsx b/src/credits/block/CreditsMenu.tsx new file mode 100644 index 0000000..8f2de78 --- /dev/null +++ b/src/credits/block/CreditsMenu.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import CreditsUtils from '../lib/CreditsUtils'; + +interface Props { + lang: MultiLang; + showAboutUs?: boolean; +} + +const CreditsMenu = (props: Props) => { + const { lang, showAboutUs = true } = props; + const menu = CreditsUtils.getMenu(showAboutUs); + const links = menu.map((item, idx) => { + const title = Functions.mlang(item.title, lang); + const style = idx === 0 ? 'menuTop' : 'menuMain'; + return
  • {title}
  • + }); + return ( +
      + {links} +
    + ); +} + +export default CreditsMenu; diff --git a/src/credits/lib/CreditsUtils.ts b/src/credits/lib/CreditsUtils.ts new file mode 100644 index 0000000..5691ebc --- /dev/null +++ b/src/credits/lib/CreditsUtils.ts @@ -0,0 +1,73 @@ +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import creditsJson from '../assets/credits.json'; + +export interface CreditsPageData { + pid: number; + title: string; + content: string; + lastupdate: number; +} + +interface CreditsData { + organization: string; + pages: CreditsPageData[]; +} + +export interface CreditsMenu { + title: string; + link: string; +} + +class CreditsUtils { + private data: CreditsData; + + constructor(json: CreditsData) { + this.data = json; + } + + getTitle(lang: MultiLang): string { + return Functions.mlang('[en]Site Information[/en][ja]サイト情報[/ja]', lang); + } + + getIndexUrl(): string { + return '/credits'; + } + + getPageUrl(pageId: number): string { + return this.getIndexUrl() + '/' + pageId; + } + + getMenu(showAboutUs: boolean): CreditsMenu[] { + const menu: CreditsMenu[] = []; + this.data.pages.forEach((page) => { + menu.push({ title: page.title, link: this.getPageUrl(page.pid) }); + }); + if (showAboutUs) { + menu.push({ title: this.getAboutUsTitle(), link: this.getIndexUrl() }); + } + return menu; + } + + getPage(pageId: number): CreditsPageData | null { + const page = this.data.pages.find((page) => { return page.pid === pageId; }); + if (typeof page === 'undefined') { + return null; + } + return page; + } + + countPages(): number { + return this.data.pages.length; + } + + getAboutUsTitle(): string { + return 'About Us'; + } + + getAboutUsContent(): string { + return this.data.organization; + } +} + +export default new CreditsUtils(creditsJson); \ No newline at end of file diff --git a/src/custom/blocks/Welcome.tsx b/src/custom/blocks/Welcome.tsx new file mode 100644 index 0000000..7469498 --- /dev/null +++ b/src/custom/blocks/Welcome.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import NoticeSiteHasBeenArchived from '../../common/lib/NoticeSiteHasBeenArchived'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import { Link } from 'react-router-dom'; + +interface Props { + lang: MultiLang; +} + +const articles = { + en: [ + { + title: 'Minoru Tsukada, Memory and Learning mechanism in the Hippocampal Network', + link: '/mediawiki/Memory_and_Learning_mechanism_in_the_Hippocampal_Network' + }, + { + title: 'Yoko Yamaguchi, Theta Rhythm and Memory Formation in Rat Hippocampus', + link: '/mediawiki/Theta_Rhythm_and_Memory_Formation_in_Rat_Hippocampus' + }, + { + title: 'Hatsuo Hayashi, Dynamical features of neurons and the brain: Chaos, synchronization, and propagation', + link: '/mediawiki/Dynamical_features_of_neurons_and_the_brain:_Chaos,_synchronization,_and_propagation' + }, + { + title: 'Ichiro Tsuda, Computational Life Science', + link: '/mediawiki/Computational_Life_Science' + }, + { + title: 'Yutaka Sakai, From synapse to behavior', + link: '/mediawiki/From_synapse_to_behavior' + }, + ], + ja: [ + { + title: '塚田稔「学習と記憶の理論的・実験的研究」', + link: '/mediawiki/学習と記憶の理論的・実験的研究' + }, + { + title: '山口陽子「ラット海馬のシータリズムと記憶形成」', + link: '/mediawiki/ラット海馬のシータリズムと記憶形成' + }, + { + title: '林初男「ニューロンと脳のダイナミクス:カオス、同期、伝搬」', + link: '/mediawiki/ニューロンと脳のダイナミクス:カオス、同期、伝搬' + }, + { + title: '津田一郎 「Computational Life Science」', + link: '/mediawiki/Computational_Life_Science' + }, + { + title: '酒井裕「シナプスから行動へ」 ', + link: '/mediawiki/From_synapse_to_behavior' + }, + ] +}; + +const Welcome = (props: Props) => { + const { lang } = props; + return ( +
    + +

    {Functions.mlang('[en]This site promotes studies on the dynamic principles of brain functions through unifying experimental and computational approaches in cellular, local circuit, global network and behavioral levels. Our goal is to capture the autonomy and the creativity in living organisms which enlightens the complexity of nature and society.[/en][ja]当サイトでは、脳の動的原理を解明することを目的として、細胞、局所回路、脳全域、行動などの様々なレベルでの実験的計算論的アプローチの統合的な研究を推進します。これらの研究から生命の自律性と情報創成の原理を捉え、さらに自然や人間社会の複雑性の理解を進めることを目指します。[/ja]', lang)}

    +

    {Functions.mlang('[en]Feature Articles[/en][ja]特集記事[/ja]', lang)}

    +
      + {articles[lang].map((i) => { + return
    • {i.title}
    • ; + })} +
    +

    {Functions.mlang('[en]Announcements[/en][ja]お知らせ[/ja]', lang)}

    +

    + NIX-odML Global Workshop & Hackathon 2017 in Japan ({Functions.mlang('[en]Sept. 25-28, 2017[/en][ja]2017年9月25-28日[/ja]', lang)}) +

    +
    + ); +} + +export default Welcome; \ No newline at end of file diff --git a/src/database/Database.module.css b/src/database/Database.module.css new file mode 100644 index 0000000..8ea86ba --- /dev/null +++ b/src/database/Database.module.css @@ -0,0 +1,70 @@ +.database { + margin: 0; +} + +.database :global(.list) { + width: 100%; +} + +.database :global(.listTable) { + width: 100%; + border-collapse: separate; + border-spacing: 5px; +} + +.database :global(.listTable .listIcon), +.database :global(.listTable .listExtra) { + vertical-align: middle; + text-align: center; + width: 65px; + line-height: 0; +} + +.database :global(.itemDetail) { + border-collapse: separate; + border-spacing: 1px; +} +.database :global(.itemDetail .head) { + width: 30%; +} + +.database :global(.itemDetail .readme), +.database :global(.itemDetail .rights) { + background-color: #ffffff; + width: 100%; + max-height: 200px; + overflow: auto; +} + +.database :global(.advancedSearch .head) { + width: 30%; +} + +.database :global(.advancedSearch .search) { + text-align: center; + margin: 10px; +} + +.database :global(.advancedSearch .itemtype) { + margin-bottom: 5px; +} + +.database :global(.advancedSearch .itemtype .itemtypeName), +.database :global(.advancedSearch .itemtype .itemtypeFields) { + border-collapse: separate; + border-spacing: 1px; +} + +.database :global(.advancedSearch .itemtype .itemtypeName th) { + padding: 5px; +} + +.database :global(.advancedSearch .fieldDateLabel) { + display: inline-block; + width: 50px; +} + +.database :global(.advancedSearch .fieldDate select), +.database :global(.advancedSearch .fieldDate input) { + margin: 0 5px 0 0; +} diff --git a/src/database/Database.tsx b/src/database/Database.tsx new file mode 100644 index 0000000..51a6e3a --- /dev/null +++ b/src/database/Database.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import styles from './Database.module.css'; +import DatabaseAdvancedSearch from './DatabaseAdvancedSearch'; +import DatabaseDetailItem from './DatabaseDetailItem'; +import DatabaseSearchByAdvancedKeyword from './DatabaseSearchByAdvancedKeyword'; +import DatabaseSearchByIndexId from './DatabaseSearchByIndexId'; +import DatabaseSearchByItemType from './DatabaseSearchByItemType'; +import DatabaseSearchByKeyword from './DatabaseSearchByKeyword'; +import DatabaseTop from './DatabaseTop'; + +interface Props { + lang: MultiLang; +} + +const Database = (props: Props) => { + const { lang } = props; + return ( +
    + + {Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} - {Functions.siteTitle(lang)} + + + } /> + ) => } /> + ) => } /> + } /> + ) => } /> + ) => } /> + } /> + } /> + ) => } /> + ) => } /> + + +
    + ); +} + +export default Database; \ No newline at end of file diff --git a/src/database/DatabaseAdvancedSearch.tsx b/src/database/DatabaseAdvancedSearch.tsx new file mode 100644 index 0000000..6375e4c --- /dev/null +++ b/src/database/DatabaseAdvancedSearch.tsx @@ -0,0 +1,48 @@ +import React, { Component } from 'react'; +import { RouteComponentProps } from 'react-router'; +import Config, { MultiLang } from '../config'; +import Functions from '../functions'; +import ItemType from './item-type'; +import AdvancedSearchQuery from './lib/AdvancedSearchQuery'; +import ItemUtil from './lib/ItemUtil'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +class DatabaseAdvancedSearch extends Component { + + private query: AdvancedSearchQuery = new AdvancedSearchQuery(); + + constructor(props: Props) { + super(props); + this.handleClickSearchButton = this.handleClickSearchButton.bind(this); + } + + handleClickSearchButton() { + if (!this.query.empty()) { + const url = ItemUtil.getSearchByAdvancedKeywordsUrl(this.query); + this.props.history.push(url); + } + } + + render() { + const { lang } = this.props; + return ( +
    +

    {Functions.mlang('[en]Search Items[/en][ja]アイテム検索[/ja]', lang)}

    +
    + +
    + {Config.XOONIPS_ITEMTYPES.map((type) => { + return ; + })} +
    + +
    +
    + ); + } +} + +export default DatabaseAdvancedSearch; \ No newline at end of file diff --git a/src/database/DatabaseDetailItem.tsx b/src/database/DatabaseDetailItem.tsx new file mode 100644 index 0000000..74dfa1a --- /dev/null +++ b/src/database/DatabaseDetailItem.tsx @@ -0,0 +1,89 @@ +import React, { Component } from 'react'; +import Helmet from 'react-helmet'; +import { RouteComponentProps } from 'react-router'; +import Loading from '../common/lib/Loading'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import ItemType from './item-type'; +import ItemUtil, { Item } from './lib/ItemUtil'; + +interface Params { + id: string; + doi: string; +} + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +interface State { + loading: boolean; + item: Item | null; +} + +class DatabaseDetailItem extends Component { + + private id: number; + private doi: string; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + item: null, + }; + const { params } = this.props.match; + this.id = typeof params.id !== 'undefined' ? (params.id.match(/^\d+$/) !== null ? parseInt(params.id, 10) : 0) : 0; + this.doi = typeof params.doi !== 'undefined' ? params.doi : ''; + } + + componentDidMount() { + this.updateItem(); + } + + componentDidUpdate() { + const { params } = this.props.match; + const id = typeof params.id !== 'undefined' ? (params.id.match(/^\d+$/) !== null ? parseInt(params.id, 10) : 0) : 0; + const doi = typeof params.doi !== 'undefined' ? params.doi : ''; + if (this.id !== id || this.doi !== doi) { + this.id = id; + this.doi = doi; + this.updateItem(); + } + } + + updateItem() { + if (this.doi !== '') { + ItemUtil.getByDoi(this.doi, (item) => { + this.setState({ loading: false, item }); + }); + } else if (this.id !== 0) { + ItemUtil.get(this.id, (item) => { + this.setState({ loading: false, item }); + }); + } + } + + render() { + const { lang } = this.props; + if (this.state.loading) { + return ; + } + if (this.state.item === null) { + return ; + } + return ( + <> + + {Functions.mlang(this.state.item.title, lang)} - {Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} - {Functions.siteTitle(lang)} + +

    {Functions.mlang('[en]Detail[/en][ja]詳細[/ja]', lang)}

    +
    + + + ); + } +} + +export default DatabaseDetailItem; \ No newline at end of file diff --git a/src/database/DatabaseSearchByAdvancedKeyword.tsx b/src/database/DatabaseSearchByAdvancedKeyword.tsx new file mode 100644 index 0000000..72427aa --- /dev/null +++ b/src/database/DatabaseSearchByAdvancedKeyword.tsx @@ -0,0 +1,56 @@ +import React, { Component } from 'react'; +import { RouteComponentProps } from 'react-router'; +import { MultiLang } from '../config'; +import AdvancedSearchQuery from './lib/AdvancedSearchQuery'; +import DatabaseListItem from './lib/DatabaseListItem'; +import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil'; + +interface Props extends RouteComponentProps { + lang: MultiLang +} + +interface State { + search: string; + query: AdvancedSearchQuery; +} + +class DatabaseSearchByAdvancedKeyword extends Component { + + constructor(props: Props) { + super(props); + const search = props.location.search; + const query = ItemUtil.getAdvancedSearchQueryByQuery(search); + this.state = { search, query }; + this.searchFunc = this.searchFunc.bind(this); + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + const search = nextProps.location.search; + if (prevState.search !== search) { + const query = ItemUtil.getAdvancedSearchQueryByQuery(search); + return { search, query }; + } + return null; + } + + getUrl() { + return ItemUtil.getSearchByAdvancedKeywordsUrl(this.state.query); + } + + searchFunc(condition: SortCondition, func: SearchCallbackFunc) { + ItemUtil.getListByAdvancedSearchQuery(this.state.query, condition, func); + } + + render() { + const { lang } = this.props; + const baseUrl = this.getUrl(); + return ( +
    +

    Listing item

    + +
    + ); + } +} + +export default DatabaseSearchByAdvancedKeyword; diff --git a/src/database/DatabaseSearchByIndexId.tsx b/src/database/DatabaseSearchByIndexId.tsx new file mode 100644 index 0000000..8e81783 --- /dev/null +++ b/src/database/DatabaseSearchByIndexId.tsx @@ -0,0 +1,88 @@ +import React, { Component, Fragment } from 'react'; +import Helmet from 'react-helmet'; +import { RouteComponentProps } from 'react-router'; +import { Link } from 'react-router-dom'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import DatabaseListIndex from './lib/DatabaseListIndex'; +import DatabaseListItem from './lib/DatabaseListItem'; +import IndexUtil, { Index, INDEX_ID_PUBLIC } from './lib/IndexUtil'; +import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil'; + +interface Params { + id: string; +} + +export interface Props extends RouteComponentProps { + lang: MultiLang; +} + +interface State { + indexId: number; +} + +class DatabaseSearchByIndexId extends Component { + + constructor(props: Props) { + super(props); + const { params } = props.match; + this.state = { + indexId: params.id ? (params.id.match(/^\d+$/) !== null ? parseInt(params.id, 10) : 0) : INDEX_ID_PUBLIC, + } + this.searchFunc = this.searchFunc.bind(this); + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + const { params } = nextProps.match; + const indexId = params.id ? (params.id.match(/^\d+$/) !== null ? parseInt(params.id, 10) : 0) : INDEX_ID_PUBLIC; + if (prevState.indexId !== indexId) { + return { indexId }; + } + return null; + } + + getUrl() { + if (this.state.indexId === 0) { + return '/'; + } + return IndexUtil.getUrl(this.state.indexId); + } + + searchFunc(condition: SortCondition, func: SearchCallbackFunc) { + if (this.state.indexId === 0) { + const res = { total: 0, data: [] }; + func(res); + } else { + ItemUtil.getListByIndexId(this.state.indexId, condition, func); + } + } + + render() { + const { lang } = this.props; + const index = IndexUtil.get(this.state.indexId); + if (index === null) { + return ; + } + const baseUrl = this.getUrl(); + const pIndexes = IndexUtil.getParents(this.state.indexId); + const parents = pIndexes.map((value: Index) => { + const url: string = IndexUtil.getUrl(value.id); + return / {value.title} ; + }); + const title = pIndexes.map((value) => { return '/' + value.title; }).join(''); + return ( +
    + + {Functions.mlang(title, lang)} - {Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} - {Functions.siteTitle(lang)} + +

    {Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}

    +
    {parents}
    + + +
    + ); + } +} + +export default DatabaseSearchByIndexId; diff --git a/src/database/DatabaseSearchByItemType.tsx b/src/database/DatabaseSearchByItemType.tsx new file mode 100644 index 0000000..257538b --- /dev/null +++ b/src/database/DatabaseSearchByItemType.tsx @@ -0,0 +1,73 @@ +import React, { Component } from 'react'; +import { RouteComponentProps } from 'react-router'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import DatabaseListItem from './lib/DatabaseListItem'; +import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil'; + +interface Params { + itemType: string; + subItemType: string; +} + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +interface State { + itemType: string; + subItemType: string; +} + +class DatabaseSearchByItemType extends Component { + + constructor(props: Props) { + super(props); + const { params } = this.props.match; + this.state = { + itemType: params.itemType ? params.itemType : '', + subItemType: params.subItemType ? params.subItemType : '', + }; + this.searchFunc = this.searchFunc.bind(this); + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + const { params } = nextProps.match; + const item_type = params.itemType ? params.itemType : ''; + const sub_item_type = params.subItemType ? params.subItemType : ''; + if (prevState.itemType !== item_type || prevState.subItemType !== sub_item_type) { + return { item_type, sub_item_type }; + } + return null; + } + + searchFunc(condition: SortCondition, func: SearchCallbackFunc) { + if (this.state.itemType === '') { + const res = { total: 0, data: [] }; + func(res); + } else { + ItemUtil.getListByItemType(this.state.itemType, this.state.subItemType, condition, func); + } + } + + getUrl() { + let url = ItemUtil.getItemTypeSearchUrl(this.state.itemType); + if (this.state.subItemType !== '') { + url += '/' + this.state.subItemType; + } + return url; + } + + render() { + const { lang } = this.props; + const baseUrl = this.getUrl(); + return ( +
    +

    {Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}

    + +
    + ); + } +} + +export default DatabaseSearchByItemType; diff --git a/src/database/DatabaseSearchByKeyword.tsx b/src/database/DatabaseSearchByKeyword.tsx new file mode 100644 index 0000000..8961fd8 --- /dev/null +++ b/src/database/DatabaseSearchByKeyword.tsx @@ -0,0 +1,60 @@ +import React, { Component } from 'react'; +import { RouteComponentProps } from 'react-router'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import DatabaseListItem from './lib/DatabaseListItem'; +import ItemUtil, { KeywordSearchType, SearchCallbackFunc, SortCondition } from './lib/ItemUtil'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +interface State { + type: KeywordSearchType; + keyword: string; +} + +class DatabaseSearchByKeyword extends Component { + + constructor(props: Props) { + super(props); + const { type, keyword } = ItemUtil.getSearchKeywordByQuery(this.props.location.search); + this.state = { type, keyword }; + this.searchFunc = this.searchFunc.bind(this); + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + const { type, keyword } = ItemUtil.getSearchKeywordByQuery(nextProps.location.search); + if (prevState.type !== type || prevState.keyword !== keyword) { + return { type, keyword }; + } + return null; + } + + getUrl() { + return ItemUtil.getSearchByKeywordUrl(this.state.type, this.state.keyword); + } + + searchFunc(condition: SortCondition, func: SearchCallbackFunc) { + if (this.state.keyword === '') { + const res = { total: 0, data: [] }; + func(res); + } else { + ItemUtil.getListByKeyword(this.state.type, this.state.keyword, condition, func); + } + } + + render() { + const { lang } = this.props; + const baseUrl = this.getUrl(); + return ( +
    +

    {Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}

    +

    {Functions.mlang('[en]Search Keyword[/en][ja]検索キーワード[/ja]', lang)} : {this.state.keyword}

    + +
    + ); + } +} + +export default DatabaseSearchByKeyword; diff --git a/src/database/DatabaseTop.module.css b/src/database/DatabaseTop.module.css new file mode 100644 index 0000000..a89d26d --- /dev/null +++ b/src/database/DatabaseTop.module.css @@ -0,0 +1,13 @@ +.itemTypes .itemType { + width: 50%; + padding: 5px; +} + +.itemTypes .itemType :global(table) { + width: auto; +} + +.itemTypes .itemType :global(table .itemTypeName) { + vertical-align: middle; + font-size: large; +} \ No newline at end of file diff --git a/src/database/DatabaseTop.tsx b/src/database/DatabaseTop.tsx new file mode 100644 index 0000000..3e88a06 --- /dev/null +++ b/src/database/DatabaseTop.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import Config, { MultiLang } from '../config'; +import styles from './DatabaseTop.module.css'; +import ItemType from './item-type'; + +interface Props { + lang: MultiLang; +} + +const DatabaseTop = (props: Props) => { + const { lang } = props; + const types: string[][] = []; + const len = Config.XOONIPS_ITEMTYPES.length; + for (let i = 0; i < Math.ceil(len / 2); i++) { + const j = i * 2; + const p = Config.XOONIPS_ITEMTYPES.slice(j, j + 2); + types.push(p); + } + return ( + + + {types.map((value, idx) => { + return ( + + {value.map((type, idx) => { + return ( + + ); + })} + + ); + })} + +
    + {type !== '' && } +
    + ); +} + +export default DatabaseTop; diff --git a/src/database/DatabaseXoopsPathRedirect.tsx b/src/database/DatabaseXoopsPathRedirect.tsx new file mode 100644 index 0000000..a38c0d2 --- /dev/null +++ b/src/database/DatabaseXoopsPathRedirect.tsx @@ -0,0 +1,150 @@ +import React, { Component } from 'react'; +import { Redirect, RouteComponentProps, withRouter } from 'react-router'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +class DatabaseXoopsPathRedirect extends Component { + + getRedirectUrl(): string { + const { location } = this.props; + const pathname = location.pathname || ''; + const query = new URLSearchParams(location.search); + const search = new RegExp('^/modules/xoonips(?:/+(.*))?$'); + const matches = pathname.match(search); + if (matches === null) { + return ''; + } + const path = matches[1] || ''; + switch (path) { + case '': + case 'index.php': { + return '/database'; + } + case 'detail.php': { + const id = query.get('id'); + if (id !== null) { + return '/database/item/id/' + Functions.escape(id); + } + const itemId = query.get('item_id'); + if (itemId !== null && itemId.match(/^\d+$/) !== null) { + return '/database/item/' + Functions.escape(itemId); + } + return ''; + } + case 'listitem.php': { + const indexId = query.get('index_id'); + if (indexId !== null && indexId.match(/^\d+$/) !== null) { + const params = new URLSearchParams(); + const map: any = { + orderby: { key: 'orderby', isNumber: false }, + order_dir: { key: 'order_dir', isNumber: true }, + itemcount: { key: 'itemcount', isNumber: true }, + page: { key: 'page', isNumber: true } + }; + for (let k in map) { + const v = query.get(k); + if (v === null || v.length === 0) { + continue; + } + if (map[k].isNumber && v.match(/^\d+$/) !== null) { + continue; + } + params.set(map[k].key, v); + } + const paramStr = params.toString(); + return '/database/list/' + Functions.escape(indexId) + (paramStr.length > 0 ? '?' + paramStr : ''); + } + break; + } + case 'itemselect.php': { + const op = query.get('op'); + if (op === null) { + break; + } + switch (op) { + case 'quicksearch': { + const keyword = query.get('keyword'); + const itemType = query.get('search_itemtype'); + if (keyword === null || itemType === null || keyword === '') { + return ''; + } + const type = itemType.replace('xnp', ''); + if (itemType !== 'basic' && itemType !== 'all' && itemType.match(/^xnp.+/) === null) { + return ''; + } + const params = new URLSearchParams({ type, keyword }); + const map: any = { + orderby: { key: 'orderby', isNumber: false }, + orderdir: { key: 'order_dir', isNumber: true }, + item_per_page: { key: 'itemcount', isNumber: true }, + page: { key: 'page', isNumber: true } + }; + for (let k in map) { + const v = query.get(k); + if (v === null || v.length === 0) { + continue; + } + if (map[k].isNumber && v.match(/^\d+$/) !== null) { + continue; + } + params.set(map[k].key, v); + } + return '/database/search?' + params.toString(); + } + case 'itemtypesearch': { + const itemType = query.get('search_itemtype'); + if (itemType === null || itemType.match(/^xnp.+/) === null) { + return ''; + } + const type = itemType.replace('xnp', ''); + return '/database/search/itemtype/' + Functions.escape(type); + } + case 'itemsubtypesearch': { + let type = ''; + let subtype = ''; + query.forEach((v, k) => { + if (k.match(/^xnp[a-z]+$/) !== null && !!v) { + type = k.replace('xnp', ''); + return; + } + }) + if (type === '') { + return ''; + } + query.forEach((v, k) => { + if (k.match(`^xnp${type}_.+$`) !== null && !!v) { + subtype = v; + return; + } + }); + if (subtype === '') { + return ''; + } + return '/database/search/itemtype/' + Functions.escape(type) + '/' + Functions.escape(subtype); + } + } + return ''; + } + case 'advanced_search.php': { + return '/database/advanced'; + } + } + return ''; + } + + render() { + const { lang } = this.props; + const url = this.getRedirectUrl(); + if (url === '') { + return ; + } + return ; + } +} + +export default withRouter(DatabaseXoopsPathRedirect); diff --git a/src/database/assets/images/icon_binder.gif b/src/database/assets/images/icon_binder.gif new file mode 100644 index 0000000000000000000000000000000000000000..c438f03e7af7b501673a603440ee9db01b84a432 GIT binary patch literal 369 zcmZ?wbhEHblw*)%I3mPwKOy0~fWRdMg+~PiKkwgv+28+W{`~jr*WU>U`1Ah#*YoGE z85lfkXn0y*f78L?)BgQu7#RM80RwSB@h1x-1A`EQ4oEr3P6pO@3sm}2GUsJz$ufvA zv}2|e*}n^6W@O@JVY1E8Dr*pAPETjy?<}ovU@c%^;1irw*TYxE z%R75+*VJ+b%SB5jYjl@$rO#Y5ZyI}y`JA=t>vQux7w_6y&d7RT%d(!PmV-;D^l%2I zpE%#+vH8%+YsYV1EoV7xb$8wJ5JzVw=IAR=LfHfL?UWAIE;EUVQ#;t68NKsJ25a=0|0Ikgqi>V literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_book.gif b/src/database/assets/images/icon_book.gif new file mode 100644 index 0000000000000000000000000000000000000000..6deea1b7b471ffc16ba9f4d4fdaaa57fa06e63d9 GIT binary patch literal 375 zcmV--0f_!bNk%w1VIBY;0K^^u&kzvlkB{bnfZR|}-(X z%m4uY|Nq#(*Z=?kA^8LW0015UEC2ui03HAy000H_peK%GX`bk4M2zC3u*qpa!5Le# z#4vYogvlf@0B|B0MTIwdZ~zBEhLa#1GzWrh1G6X=4a0LF&~!9{Vqy>oa8sP(Q_$9O zGKdKU5}3YG9334L2M9I=1Z`4OMF@WC+P22AE~yk^~nq4hjqr90dpm6p%?EU|FtDag0RaFu VJUDp5fdvK|HZa&hvEzvl06PI`qyGQ^ literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_conference.gif b/src/database/assets/images/icon_conference.gif new file mode 100644 index 0000000000000000000000000000000000000000..ec56f37ef3bb18a7af0aab878c098ff837456cc1 GIT binary patch literal 427 zcmZ?wbhEHblw*)%IKseiKOy0~fWRdMh4<^%zwGb-^ZxzU^XDHG6kIbf_<8^SoB8wa z1Oz;-uYcCiaMQuz)BgQu7#RM80RwSB@h1x-1A`EQ4oEr3P6pQh3sm}2G}X=r&&aVB zV^?AC%AU+EE6QtfXB*2CK}|OXrUl&!24eC8sogJo9Aeqq%TAXnw4IBa{)EBg+=~)s zK?OGsfzOfxvX*y3(-j#WI?MQlmsM1{vNN)9F_%;{DV4VhYA_41_;LICm-e@~O);A3 z#wNfvE2Wz`l!IH4eNAXW*leM4J^>~!Yg=wMUiNN2Ue}F%TUg=Qr^+4ZZ}$aeJ`iXWng4jd5tB0+NJ(gon;|h7`_;GTs`qWDYVooSLe` n_)?N7m}M!89|y|{OQ*=~9BfQ74>XllG%%M4tT7N|Vz34PsKtx5 literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_data.gif b/src/database/assets/images/icon_data.gif new file mode 100644 index 0000000000000000000000000000000000000000..30d35c8ae03fb76a428e84d99c516ced3a8a4f21 GIT binary patch literal 402 zcmZ?wbhEHblw*)%I3mpO=l%Pi_wSz<5V)kEa6cj8{rdHH0s`L5pMTB3;OqJGj|vK2 z_V=IV;X7|&cGJP()BgR>8XC?pF#P}j|Hl3s3`79MpDc_F48jaLAhjSn8Cd^6Q0Ys_ zoTnt{IMCcsh2DzEvdfk(Bw@z6o$BWeDe4j(2c%rWP1 zv|MD%*%sAQEp2l`$vD5Zg^ywDAqS@UYc5&%TCg?nvDZW}R+zC@TQD%QGcr}wnh0=o zNAq**atZM>@v)drGi8}6#FZ(Kz#k$cAm~0#a0$yqw~gyI2(g+iGh-12vS9W^eYqdv)gH`_KGu zpZ!P`s9XCu{QUf-4d1gaScmz^ZEO51lXP+U1O?~n52uziM+7|Lca+hWnlmHdkW;3_ YfBwz@#>G#&?KF~3&GG!~!ogq-0O_fiTL1t6 literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_files.gif b/src/database/assets/images/icon_files.gif new file mode 100644 index 0000000000000000000000000000000000000000..e102eea62efa5ecada08b31cc31df98496fbdf86 GIT binary patch literal 433 zcmZ?wbhEHblw*)%xXJ(m|NsAA!@#hLfng;B!*T|OWef~U7#LVkeb?2ZSCWFdZ$cGPFq@DbalPt;c?Z^??!m| zt?206v9b5k(jMmKJ}E1ER#EZ1rsics!>iWTx82=udwM=hpZ;m~?9cP&eOtc#$J(_& zH*NZ}bLan4r~aQk`~Ts?|6jiXT?KX>0YdR73nK%AF@p|B9mr1%Z08QlEb!2g>OZlh z=wyzN@0zJ4Ua7rvoB|V0zhz4?;17GPyF5-hJwtobj{9P{o?@p>PCnJs5bMaCQBfJK zDx;_*$M4EF>tv&&SKd#l^wqrOw6qk5h<4!lIzTk%@&%rJ!-?!o%$XQ-Qv-1_1le Bo4f!3 literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_folder.gif b/src/database/assets/images/icon_folder.gif new file mode 100644 index 0000000000000000000000000000000000000000..7a69a82c9749d7b69004aa4aa22aad2563d4b81c GIT binary patch literal 1508 zcmdT@Yc~`K03CM94B90Tt(cjdttEwMDcLa|%_y2trW};fNLwm7YOU47%ou}F26^Re z9n1*XYXqN#olwz{e15|_iknRy1MbK2v&qogfGAX zW?y5CI~={R!3P_B;j$G!u;8{0?*8!D0q-FAaN)}Za}WH(zz)YQKDc}YA4JF@gdW1) zBj6oF#4+$=5p@EG;}QJ}VoxFV4C0cIm;$j3DOr$YBQ*y(#mFs1emM#&QB;MJYE(6# zu?>oLv|dB|b@boHz#XUuaqBMTKf;BHjegi1fGuozaNrpPuLUmn*#lMxSfTI>f&X3v z>_gB2aH9}>2>W8di$TP3M4iM>@i?4-BfsK=04Ig`S%mmx#EX$2L1HRSrQu9E&PZ`q zillQ8o`*0KA{o+iAuBpnyAqu$boZm@7J3(|zKh$#7#zXiDDK^d z_5ns8Vr&wxW^wNU#vfyH3Xi7o_!*weVCEGjrts=DX5ZrDC;agz-p?=0=f55OFNOM< zs6!z15Y~Qi|K$?|5(q-FC9|olM@TZU4JB2SUr4s39iW>>_DXh}E7)#pyqRL>Ba8qW zX0raeP;}Y z-5N^3YjAXuQ*^#HmP>xWsh?**oPRVd%ZJ<{f0|T5+_q(4`%+p+ud&*u^PR4tL(8}m z%dWwDPT&4f+nk1)L|2p^rx{Wu>vjHWPFhJdYLwy?`!aOI=3hVMFDB`YzGpPV-FMWpJl2%N2#%EKh?f_|$b5|IJ!HZa3FDpv z`bXu;S&I@WwSRe7oTI=jaP4uCQN3Te*XmMv=HgC%4o_@eoY~Z87DVjoUHaoZJJU3R zIpsxOogdDy;K?U^Zu~>z^z@N~IjUv8Qcf<}Cfr!1rv6P3ePcj%+hzPR%P5xQ9yjl$ lasA9$Wa95!Zr0^&%}+M-i5vaE;7%$(Xql_S*mT0?e*r^Q%hCV< literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_memo.gif b/src/database/assets/images/icon_memo.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6b4cd17263d5b1da29ae918a5201b636af99237 GIT binary patch literal 166 zcmZ?wbhEHblw*)%Sjfn5)4}0C3@H9&VdP?9V$fj#0+2idQ~8wsm8akGFP_80kP_S% z{-wU5&vn`}Pd$eXYi6lLp{1+fLxW4w49 zL0%sKi=6Po+4Opl!!RcR1bUbOYl%Zx7#cu=iW3+*md=gqS_~LZ3IsuJA&keLpiLq) z8k3_YGZdgY1Y05m5C9i?1O^UDE&^vy5&#(oUkXn?77us;5iSl4M;;O#1Cs-X9sv&u zM-l`s9TZ0!004{v1QrT_phq3Bp%)Yif+7M31so4Y4X-T~d2s-9Ed>J_o5ds%01ZAi zI12~{2AwYn0}u)T18j6K2L}rU6%|wO)d=?ZF9-y40un?B!tcX_0R{l9>cFSq7YR_b z@N06RgEvvm-W_0t;gW}6_zv(06#(QrYZyWnF>p{Y0f0Od7!07sFG7VB4hR%X2q|9<`YKkwh)Pe{0CU~nfO;F5yE%l`iJ z0s?R5&wtj?@M-`4n+^_V7#RM80RwSB@h1x-1A`EQ4oEr3P6pQh3sm}2GUsKiT9@-$ z!e58mFWbm_vGKVB5}mD#3$z4SJWd`K^k8Xd?+{67kl;{bXZm!(af;xPhk_CgGC`RO z3mbZvJ6xOsJ?fKt*lIR9h_hu1vhwlqvSc(0#&huZ#4>mb^6_UfFmwj-@C3y(F?LRj z%Cwpx$i^$k%qhe&rIDXy#u7oE`7@_a7GeIub4dbINt$5_EKIZ zr45ZsSPyOP+#`5NiD|`&O%Jzb9$>t@=8zy4TM*arYp;VgC^2(4o)VlmspIVXci*lG zFfQy9sZCw-Lef2dfso6jXG=GQ>NPEGQ)X)Et`K;n(dq4G;4r~$>Y;-Dd@)S3MK8rQ zIovUkopR#R!j`5o1Ktf^&p+BYO^MIp3DZGdCN?(jM43c~Mp-6S6^nom35}P%tavO1 ryqp+4qvE}Myb=@+Fe-Ya@F)Z>=#|z{XH(dixp>{(-4(Cf7#OSpAnB}> literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_presentation.gif b/src/database/assets/images/icon_presentation.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7e1b31e0586474949dfbe7dc3b5ea09034d0918 GIT binary patch literal 423 zcmZ?wbhEHblw*)%I3mPwKOy0~fWRdMh4<^%zwGb-^ZxzU^XDHG6kIbf_<8^SoB8wa z1Oz;-uYcCiaMQuz)BgQu7#RM80RwSB@h1x-1A`EQ4oEr3P6pQh3sm}&KiY7vT=!-L zOF)fC?pnTpV3+qv|AiP8oO)~&G!wW#X$Y~hJl*uN#mluX$LzU{(w2k|jVz2N=NLE| ze{d+A`(Sa)ahZ^;VMN07H_|VaeO%ocn7LRO+3RZg8gn&9rj%h$@z%f@YK&9#7UNn^-n_RflhPI(I$IA5q^6@9*K1l2!NJlk zE!HqF&>kM#P*CQ8fZJ(l-FJ88vaL9AoRg-;s63*KKJg zKyW`s9fF{P8E6<71j7eAL_UfDN8+gtHkw+6*_tUdgQ~d75in?6RWK0tZ~y={nb26K z4FXOzfZ=Q$8hRcL3MFYaR2&!uVpxm>0f#dfRSkk-02Ce@Cn-!B4uSw1V;%tn9uf`# zo<0T;9eW6+MIICk5H)E6q!Jy11pxqi4+jQY2^NMe2MQRPwi*in7yyg~1R6w34;UR! zEfWF(8mLtp8*K#()4v)z933hTEf5)a4y9EK8rp$Z=`iTP5Xl7t0ss(fD8M0rus{u{ zlyU$`!GsnDIuLqrV}}3$8pRCo!^lks7A_*MFksPvRe}>5t}Up>4;p|B3M}-1kjnx9 z0_GM35EGBe1_TIN^{^lS%qB`>knYPsFHHtg4rYznFwDaOa7-dR;N_-4DLPd&T-d_o z!2$wQ3TPlzr9dAK43l!HZ~|&Pg^GrHKyadJ*bfJ-2(x76fb&`CVYPG4l;KtO~HgiDylTrb0g4+azza}fdnJNuQ- A2LJ#7 literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_stimulus.gif b/src/database/assets/images/icon_stimulus.gif new file mode 100644 index 0000000000000000000000000000000000000000..09de6b82c98fd156c7cc438b640232ba8992a803 GIT binary patch literal 302 zcmZ?wbhEHblw*)%I3mRG=l%Qh0s?R5&%dOg@b&!pYX%0N_V2%+kZ>m;;OG7OFZ=s% zIygLQXn0y*|EQqg{rdH17#RM80RwSB@h1x-1A`EQ4oEr3P6pQ13sm}2GUsJz2?;FN zr)nTlpsN&+eE5`rgte%m0tZWQ1Cw)u#Uj3L4kt$@fjO=YDg_OE3IbUL867HoJgtol z8Elh#I%?z+MPeM?L;MUfcp1YT`2|?x6POtoTq4-Am6(|XS=s&6n3x6mOs1($bmg3@ zG9zV?vJpS4)iNbsZVv7>O5Gftn}m271)A1$3ovaL;uDymKh1mHn NG9+ERu}P7^8UVNmS`z>O literal 0 HcmV?d00001 diff --git a/src/database/assets/images/icon_tool.gif b/src/database/assets/images/icon_tool.gif new file mode 100644 index 0000000000000000000000000000000000000000..b71b3f6956b29d680644915f1d93950c686127a7 GIT binary patch literal 399 zcmZ?wbhEHblw*)%I3mn&)4}0cL&Kl<@4ucue@Q{%&HVX4@87=@5O7{V;Qjjb*9;8q zCnP*7C^*N@|FXaT)BgQeZEVgkF#P}j|J}QH3`79MpDc_F48jaLAhjSn8Cd^6Q0Ys_ zoTn24PlZ9_E2;?5w8z44f|38A@5!42@ms<>p+C zOoG#z&G~1$%?-D%oMXn)+c%w`BRX5#pV*E0^{uOZFNT!Nv;=&dJAOY6Tfm*&5H=vobKVvg|PD2>94FGeS-9Nk%w1VIBY;0K^&q`QP9C@9*i4kIony;&5>9udm!tP|{y)(|3o@FgDbK zl-8TC(Ntf}3=YvqQS6_e-(X<%&(GE{Fxfyr^1r{*ARy*|fX@&R%m4uY|Nq#(*Z=?k z000000000000000A^8LW000^QEC2ui03HAy000I5peBxFX`U#lFbU>j38SRxFsw7y5 z@~FfWC6rYa5Z6mWnKURqi~QA-C$}W1Qxw5Ox^O!H=qC$IxQ zMC+hHbziwQfDaT-cXhNtSN~omomDx&5h_1j%ZDHk@9@73{FGtA1UN_;c*j7S@(1}f zQYzNYZ%v~h&^4_)S{kOIKSr$|JmJCxUG8+wtEkl5j%t4RL7re%@{C`cuTS&#G-M=~ zS2udV6f!(GfUpU!ST;_oUJUWmvv6fIL}LW}X3o=uX8kj`B}$=*E(#C}7YX(Z!SW>A zZBNVX2W|x1M16#BwElvb(XMW8&h#hKpu;bQM!PD6NJ8OmVMM_q{rMZ5XTk0nucd`W zTNAqa?Sb;H)xuGP4PGd7CH5iR*ONQ=ARXHNMQmMn;TXaGChMcC85}OC!&oFVX817s zYJ=8mHrb;91VRXf5o=qqHh7gRSW_*!+AD~Q&=k;4Gvp5f6+S%fqKA{o6P`Y#gOgFI zrcgT5|y;-e|h6oWh5tUAsFwzdpJAxsR>83OwAz^%JLRImu%aDCw8E zcSDDG&B4#~$mi$hL9yYTT|29va(MqJ?~ZW|S>B%wp2R*P%d+6@+SSyXxpSOZT!E1= zV5&CVO!AUD+dEshy5tqN#Rk%VGI>wzhQh8GL@B;U8cyq*07?GMk3Zb_g=i{ z(%0nJ=BO$Rvvv-KF-?mk*|DR^6ZeKv?cf!?3J4VOcdIv7-1^cF`Wojs?AH9+RCI(u zAjC|$%OIBun;l-gTJ(Pu!ie;_FpM8!DWB7Tz$-9X5U?$No*LQaa9r@9uHD<+-F@pw zR!}AH(XU^>K%f~f*0q2z;@sTaYgbDm$QU6MpP-9iQT&l<7()yc0Y7Wl^fg%`bxo{u zoo$IeSRW_;-I+i8-W7HBQ(8(21zzllBPEoBwnJhsd+iNhgev0U8T zw&;5N5mHQS?muK+_sfyB!Xcgr8tYb{i`^RzZf+DRDk>Hh7V8DY#S0#mQ$sEf-jjh8 za)hYh--5V{2#$e)%+Aiv?7X}>)uyQC8Lj3SFKRCg+F0)uQ8Caq#iKxk^${>Euz?76 zXUDyaQvOme67{cNzQBh3cWTUPd>`5#-A#6siOysE%1-)uO)8+B>+@Pbo~z|TuZv|?h^>bft(-`cb@ zesp5k2*i$tr{4_>;D(cNJf;8^T0%}Pd1=X!OEr=`&n_H+>^=_w#S+3E&846@uunV+ z*xA{SzgDRpRx44#r(S8M_#NWRi(imz9x6)Z)41KgfA!P9Fe2Vv9Kh4X$~qWy@7}%R zANa21fc6Zfoi@@3Q*Sl+v)!qEOky%mewQAZxGH2Oq@_`9{p{qFmX;3PjaYbOgQOhW z=S#E@RCd;v8q~d>)BEPXn#-kMFMNL*LVkZ$pmveEW?F-*tt0-_L_GUER_aGBs|zWL zKK1aLZK2iF)SQ0*fNiSYJ`4CAMbrBGmplFxMdPeS6ciMDA8$r8+?w+v z>>%Vn@wQ|g92)Az-XALpxr_L{nqySN4Ssx^bR&@Cy_I*nt7VzV4$s&a6hW_g%vTh; zOf~m#Or>oHOEj)F{qeTeA^bX7AWHLqODC(2C?CAV&J($(0i4=vx&aKVt==_l^;9wx z#Ih?gENboZvzlApKV+`m&w!I8!af@@Wv-lOpgGu`8b69uh~$k-H#$@P3|*m(ygFML zN~YyBuEBks!DiD}jjeux-+49E;!Q(Cvv|Y)1PXxd@Ahm;cqg4LzTc~q4h0#PF(^_F zlX|#0Ssg>#kcymmZLD$7&C~;{Fbz&;NQB9}Fo+~tFU0SjO?O2prGIp?*uF6QfvEWW zDi&5d#vn92eU)BJ1>aMq2Nhs6!i3ypz7&(R=i{~-Y$YRqY*|W8SjwcrZ_!2(_B*OwSj{D=pf);1wlgWE@>D2vb;kJ?RT$u zxfiv~#Q0DiaDmD%6q6LOh0ZiFC7eF0-L9{P375!LS57Q{e1O^8OPrUH$3j4%j zZWD*MkKq>m&VU-et+#<)tQ4eE7-R<1%W<>eWC@M=KpL-O99xtUx-nx~dwA;b--b#EjTGvM2 zm+Ff`IT3|LE{4UffHEgexh!5tp$|rB{rajgG!-_aj^5 z)~)W|o;?Xhoal4!1O>X+E3xg!=h&Yu8r)SCGz-3P{Zz9b8RP4-zTMnLY8Ns9s|DI- z-H0U z{iY7$IL0#SK9C!il_p(REFtRV>3!pTYz+R=(pz94F%-vYQ?F!r!|*uzxg>K)YVI7H zT__y+VM|JR|BJMQfiw?g4|~FjJk{Xz2hPXIui_WQHC%5mSAX&6+M55s1~A>3L%}cp z+(CtuJ>_B0&bt}18oUNENbC$(-*8@C^+YuYss-m$CrcwUCV9tPkr=`iIQrFTJ^%im z@R%BXvsuEFyZS?}20mvI=HW%vag-+@L_$y2@|Mn2WegrTr(n?6h7Z4LrqET$&bG+H z2V4_jRO%XnUWWh3J#)oj`^Wo7>j?8+J%}#en`+uU)`Ar|*Ug(`ZU+Xf-oEX(n#{Q< z$msY(6LSj!-aK!X(>|K;VHO z4RPx78Lg!~$5p!+?h@t_W~{e>iZoNDMyTBf5(qe+4~o|=HPigw1k!`c(%viGPhEoA31#B?*bx_I8D~x(}~)OEGVLZL^r_wWBKD$)7ZeQ3L(kqR~m) zIt$5hUJi4NPFdlTR?S@9+VZd~@px|afz^;7{ECmOY!o`hFaIIKF~9+2D9346rbKr- zIMl05|0T%U3yovoK7Dc$$&(>zD*8-%Kj_AilFcNXz`fNBQoY>RiZCdl+!NI{h zS&4oDK4pk;i7bb%kx_!8p?l}%38BnXL|vCk0}{&TUZ^6vqyUE{mK5kYcGc5A{hn)# zF0HY-{l<=RjmuPW)Z$q+tU&*IwyvOqrP+(U@pr=tyyckhKc)S>hy0Ce%^CwYzPHGk zO;?(UK>jpOx${|yzK^`s@MSBVWf3G_0mGnR@rL3ILdwEqg=jxL$$31bp~v%GgAtUX zu{wLCQd=y)FSf3~>8%9lc6JXtDZ!@f&3kThR0&)@lc};h6pGQ{GM>zvk;@40bd3V> z=WB_-NTMP8BLI0aUMjpyQTSvkD6zz|VDXcS1@b{1b$?S|Uv=%<%=TQ-R8!FmX#G#l zWPkAE$}D-3atzSEk{tuLhzNN3=b^%cFuV1uU`1NED>XRr9U1*s#{+s89OTDBO+pR< znMqx<8%d0&=-vS>8S!`IUfQyuh(GMb>4jr$o_sT^SuINSa@}V?VAiOaLp~-nbsC) z?V$Iedc8p^%wmp~wZC){+o=$}D+q~n*vI{Z{&(9Gk!k4TjHGnTc!U;9Ot>^lvZGi) z93PC)7Oz1C*IDUQtk5=?aA2np8?nlWj}86+z;cM{__+B&B+-S6H{;9elnXx|aeKOJUjCYTE^Mp~ z%X^N2V`G{jg{&N0RXEbuIEOYQKx0et!=^PBCxe{p`S~8+Clstj#NDAlReCk!cj*F* zv8g5xzA6ARbsUdRu|cvOT}WInpV(k{j1ITZ+aQrBMV8Dt`T4@M*EuRxNdi9OyJ*!PQ{UyCQJDZ!=^IvMe8Hd=W zLcmJJLrag4@ns%d^AW}{JeE6_e= zn{rvec2o0e=AP-JCKpn{pX_#fe`kZEzdWbMvSEm+OTvtOJf^6ZV2g?m)yu3 zd0tdBD2umY${qSW%GfVaS%GQZG*@F|P^?a5L-9S+Te95^XDf>OI}@x53rZ@9{mq_G zMr>fB0>IkQ;7GbjD2@py2&)@BPrDEm#2S+b2&KjdH!kM8-Pap_niARB8Vvj_|eLzBMA{NyWVbPd%t&5Gy7e0My zOu~SJni`}`ge{@kmPraIgtOHrWK5(DxUhfp^l4~&4Jxc;<2MN}J@Bcp&`*MuNGyaB zU)%4c_&C|4PmU%udr_GAQO5WJV3>fp^6*|A53%9Eq8CDpR4`Pul?byZ2k5xVeq3hT zL~lbUfp#2b-?i(!@x9`BKv*>{g(n;`+v;mC(<(p`-%sVCVKUJZ#O)(Rl?Cg-1_)h` zh!|IsjN1vgR_U#I)M1uRy|}ZXSdd2MX>0r3riJF-{JePaEt=3Yts8%&r$n><`^7+# zO7lQ!u;Bq7={3_t&So3P!0~vHe?d4AW{V%vpNN!g$`%-Rmr=cqnE%LbjX|3Z9lqR+ z6t3(1YZbXFz#CUUMmy`$MZa?f^9&K@QxkLdzlTp6RFKL|(l3ik^iD~7Y=q$IR~LVI z8z-}54E@Tk+#g#{+zaAHP4HbK6(M&NI|yT0L{~EdexvdJ7|%ba2*B(9=0o>_zn#6k zz1`OnLkqC4t!h>8BBC_(!i3=EwB%?#_T;$TNP^OIN0_u(z1?H#n;jB`-yrnQSVX+V z%_giki#+cS?td$1-v6|^ky%%Ydt(n<4J(%1>)AvdlEr^fPcSgWeJaH`d3r+CPCgkm zM4bf#nkC_3mpiriv2xxg7oPu^1RU45Ha9ue3f11aT`uozgz+HTR~aMsUn~sZyDx(# ziHCpX@)-qFDOEwml5H8iQ!*CV%w)%sBHa?!ffVgsTGF8Y*a~7p5O*C~t2_&4g!A-P zJMN|Tn=rVw^rof`N__7AHOnuS?JJN9(#iM&ZsEl(-@&gh zmHNF8TSO(%e@{W@d`cqP)7Z?)x_)S6mk0aOj2z80mM%rIEwP7s2hP9Nv}Js_4G2(x z`rFoWt)J)${#f^sAqBaMSvIZOgG*+-T9QReog0AfoeTFVNt^`PaI3vKOYdfYENni0w%0|!e9`uEzd}7ZlW*+$7e;9Lv?AZGQXVIQat0#ow zq4jlxD1sHVX zaX;^EseCOL2SwFc&fq87iJI?%o|WF?6Ca{5nd^KxppFlMz#C$&qV@Il7i;V6T`EmQllnrm)Zbfao13$}!EIhgtaXK2W#o=x>&mQZosM?q|JiOi z-=7)8`fi@C-IQxi42(__jxV3v9K;Nqh1GYRitL_Y!uAS*<0dRk9izILDyLsAekR5I&)+&{;?pjI9$W9xF2z;d?Qf%(P^Z{>FG2i?qRO zmyJUxt2iH1$ob5r8pWJWShNQSZ61cVMMO~?WuqX=XO}lH-@CUqHo`oB8<2!rI^xaE z6oHd2s_Jc2;RgPzlEbF6h_Zwgr9_?mbqozzsy&5;~eSBC`DkeGFgSfN^=ZL4!b2Gz}k zd9OZ&7_EtSH~&@N@Gj$JVevI|{wurs2dLE1#3#iPgJ=_>0Rg|N64oo#%Xew~w_Yyy z&s_HfKT$V1Vnkg^=8Zg?+^4&GKyOe@SxGYTQU`J(>FkvdkS5Qeh~VSdUO7h%{5@8r z;_U{~fl;?+=;B`+5c?knR^vGi|ho6Y^Aa%8=K81*)a zr3dBEdiAd`o7sVgve7(gL}`DBhO>NR?4RemXGUjTSGuajS10*AD;H&|%G~(NzP`S& zg38)Tj887w?k-|p-MZcomc?qlbT-|bFoFIIbSEQh-Pu!*0s$cQ|Bv2Uh%xPIwrWVJ zJ;^B>m5QnKutW`eBG!ua5H~9@cIprW346v>48k?(;U%Zu1{G@9w;W>>UUch5;%gRY j((QvE?%GFcVHa!{=Vpt?(rI|$5ew*!wxL!X$|3%LJN8-v literal 0 HcmV?d00001 diff --git a/src/database/assets/images/star.gif b/src/database/assets/images/star.gif new file mode 100644 index 0000000000000000000000000000000000000000..f90543e6882626b06bcf8cec21549306525587e9 GIT binary patch literal 538 zcmZ?wbhEHb2vb@RSOozqInO6T#O8h?|_5XzQpEL5` zkEr}RWB%`q#lQ1be=gYWYzo-Z9l5$WZ9{wB!sd!&4UR`TJuc33yV4MQvpeSSvY*r1C*w)v!W=ij>sT22X*>Yo2+uhmIk1Uz`eDS2m8z$dg zyZGR?ZRhsxdAVWD^ZmPC?AY=2RPVp{UH{+q{`=JV??czWk3jZ>|F5Thf3oD}sbl|t zpZfmf^1ok?8E6j_f3h$#FvK(HfUE+=2?Kk1Lwr+HAhTa{N3(~IYiFl>EKgr^fOniq zr+}V_ux3T`K xoV=_FYp1`Fy{@>KoswIJm#q#Hm!gfKONW6Pi*J0ivN~^vGkd2hcT*#SH2{Fq*#H0l literal 0 HcmV?d00001 diff --git a/src/database/assets/images/tree_line.png b/src/database/assets/images/tree_line.png new file mode 100644 index 0000000000000000000000000000000000000000..2865cd20fb9cfa723ce1f0e439fdfaddd6d8f829 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^DnKm4!3HFsR?RmBQs$m6jv*C{$p@JKIcFZq(qR98 zGSKAJf?UjSN`WDz)9lp2%Qq5$Mlg7~ L`njxgN@xNAS$`qN literal 0 HcmV?d00001 diff --git a/src/database/assets/images/tree_node.png b/src/database/assets/images/tree_node.png new file mode 100644 index 0000000000000000000000000000000000000000..b23e4b19c8cf04983a897e5beb12cfd53fa6c7b3 GIT binary patch literal 1251 zcmV<91RVQ`P)mg0000sHa3imjeC84Mn_0RMn)bU z9yd2PXJ=<}adCctfpm6vXhbtvHY7hoMFIl^US3{hWo2@7b!|N*qCyL#MGb2>9zj4r zOifNEB_&*3TxDlyS5{VaIUJ=$3$@*E`u+dWoPe`Y48dX-JKH-O(;EfL1qi|i54jB%uoE8= z3Xn`2iA4^DJqd$$+u9Ll_b-tx`y`*+OKR^BI$oklv_|}^C)S2|smxpvycVe=*5ob!;R*`jO4+KtB_~*Mt zbibx^y`*xxqH#YzJs%wy?AyG&pltl{+xqCq`RK^`=g9cy$N1*P_vXg;<;C^ixbxVo z^4F`ho_gZYu+zh+@X(s>%#-cQlI+Tn>c^1j#*gR3jpoCQ<-&|sNHpxpk>0(D)WV_P z&a&mfi{!wH0J4K^VmG{-4X>E-CKrkRvhfBzS^*jBB_d9-(;v8SWC{?&o*U zXJ^r^!J(i2zN)T`8vS7YS^<)>@!1ygfjZfEj3gBURHf|2V9Z;nql)I z+4hm-GiuZXQh5MySMnLPXaRr#xFnxZKkOlu%IAEY;+&toWQ_8L6Xp6N#kmM*$QWrH zQI1O1C7hBp{%|UC9?+06(sX#!9NyZ3bt?d<3%)Ya0$lDNm8`3p0q{Kd%1CRlX((j9 zWPL}cB#kpc=wbl49SD6hrb1t2(g2bxr0*}xl@$C)!R5yb|Kp~OBvr`8XPU1C-ff94 zKC=rK!92-lOmqR}Rmf*d07$}Sg3p*ke3~&nV@}(7ch0_HK#Yr7h*FF8oyDA?uK0RS zgplYK=Yplc)@=c|p { + + constructor(props: Props) { + 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); + const res = this.load(); + this.state = { + tree: res.elements, + expandableKeys: res.keys, + expandedKeys: res.expandedKeys, + selectedKeys: [], + }; + } + + load() { + const { lang } = this.props; + let keys: string[] = []; + let eKeys: string[] = []; + const makeTreeNode = (index: Index, depth: number): DataNode => { + const title = Functions.mlang(index.title, lang) + (index.numOfItems > 0 ? ' (' + index.numOfItems + ')' : ''); + const children = IndexUtil.getChildren(index.id); + if (children.length === 0) { + return {key: String(index.id), title: title }; + } + const childTreeNodes = children.map((value: Index) => { + return makeTreeNode(value, depth + 1); + }); + if (depth < 1) { + eKeys.push(String(index.id)); + } + keys.push(String(index.id)); + return {key: String(index.id), title: title, children: childTreeNodes }; + }; + let elements: DataNode[] = []; + const index = IndexUtil.get(INDEX_ID_PUBLIC); + if (index !== null) { + elements.push(makeTreeNode(index, 0)); + } + return { + elements: elements, + keys: keys, + expandedKeys: eKeys, + } + } + + handleClickOpenAll() { + this.setState({ expandedKeys: this.state.expandableKeys }) + } + + handleClickCloseAll() { + this.setState({ expandedKeys: [] }) + } + + handleExpand(expandedKeys: (string|number)[], info: { + node: NodeInstance; + expanded: boolean; + nativeEvent: MouseEvent; + }): void { + const keys: string[] = expandedKeys.map((key) => { + return typeof key === 'string' ? key : String(key); + }); + this.setState({ expandedKeys: keys }); + } + + handleSelect(selectedKeys: (string|number)[], info: { + event: 'select'; + selected: boolean; + node: NodeInstance; + selectedNodes: DataNode[]; + nativeEvent: MouseEvent; + }): void { + const selectedKey = selectedKeys.shift() || 0; + const key = typeof selectedKey === 'string' ? parseInt(selectedKey, 10) : selectedKey; + const url = IndexUtil.getUrl(key); + this.props.history.push(url); + this.setState({ selectedKeys: [] }); + } + + render() { + return ( +
    + + + +
    + ); + } +} + +export default withRouter(IndexTree); diff --git a/src/database/blocks/Rankings.module.css b/src/database/blocks/Rankings.module.css new file mode 100644 index 0000000..362a532 --- /dev/null +++ b/src/database/blocks/Rankings.module.css @@ -0,0 +1,28 @@ +.heading { + margin: 0 0 3px; + font-size: 100%; + font-weight: normal; +} + +.item { + display: flex; + white-space: nowrap; + width: 100%; +} + +.order { + margin-right: 5px; +} + +.title { + overflow: hidden; + text-overflow: ellipsis; +} + +.count { + margin-left: 10px; +} + +.star { + margin-left: 5px; +} \ No newline at end of file diff --git a/src/database/blocks/Rankings.tsx b/src/database/blocks/Rankings.tsx new file mode 100644 index 0000000..bcaadfc --- /dev/null +++ b/src/database/blocks/Rankings.tsx @@ -0,0 +1,66 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import imageStar from '../assets/images/star.gif'; +import rankings from '../assets/rankings.json'; +import ItemUtil, { ItemCore } from '../lib/ItemUtil'; +import styles from './Rankings.module.css'; + +interface Props { + lang: MultiLang; +} + +const orderLabel = (order: number, lang: string) => { + return String(order) + (lang === 'en' ? Functions.ordinal(order) : '位') +} + +const Rankings = (props: Props) => { + const items = [ + { + title: Functions.mlang('[en]Frequently accessed items[/en][ja]頻繁に閲覧されるアイテム[/ja]', props.lang), + list: rankings.accessed.map((item, idx) => { + const url = ItemUtil.getUrl(item as ItemCore); + const title = Functions.mlang(item.title, props.lang); + const order = orderLabel(idx + 1, props.lang); + return ( +
    +
    {order}
    +
    {title}
    + {idx === 0 &&
    {order}
    } +
    + ); + }), + }, + { + title: Functions.mlang('[en]Frequently downloaded items[/en][ja]頻繁にダウンロードされるアイテム[/ja]', props.lang), + list: rankings.downloaded.map((item, idx) => { + const url = ItemUtil.getUrl(item as ItemCore); + const title = Functions.mlang(item.title, props.lang); + const order = orderLabel(idx + 1, props.lang); + return ( +
    +
    {order}
    +
    {title}
    + {idx === 0 &&
    {order}
    } +
    + ); + }), + }, + ]; + return ( +
    + {items.map((item, idx) => { + return ( + + {idx !== 0 &&
    } +

    {item.title}

    +
    {item.list}
    +
    + ); + })} +
    + ); +} + +export default Rankings; \ No newline at end of file diff --git a/src/database/blocks/RecentContents.module.css b/src/database/blocks/RecentContents.module.css new file mode 100644 index 0000000..6466fb7 --- /dev/null +++ b/src/database/blocks/RecentContents.module.css @@ -0,0 +1,28 @@ +.heading { + margin: 0 0 3px; + font-size: 100%; + font-weight: normal; +} + +.item { + display: flex; + white-space: nowrap; + width: 100%; +} + +.order { + margin-right: 5px; +} + +.title { + overflow: hidden; + text-overflow: ellipsis; +} + +.date { + margin-left: 10px; +} + +.star { + margin-left: 5px; +} \ No newline at end of file diff --git a/src/database/blocks/RecentContents.tsx b/src/database/blocks/RecentContents.tsx new file mode 100644 index 0000000..166cddd --- /dev/null +++ b/src/database/blocks/RecentContents.tsx @@ -0,0 +1,39 @@ +import moment from 'moment'; +import React from 'react'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import imageStar from '../assets/images/star.gif'; +import contents from '../assets/recent-contents.json'; +import ItemUtil, { ItemCore } from '../lib/ItemUtil'; +import styles from './RecentContents.module.css'; + +interface Props { + lang: MultiLang; +} + +const RecentContents = (props: Props) => { + const { lang } = props; + const list = contents.map((item, idx) => { + const url = ItemUtil.getUrl(item as ItemCore); + const title = Functions.mlang(item.title, lang); + const date = moment(new Date(item.last_update_date * 1000)).format('Y/M/D'); + const order = String(idx + 1) + (lang === 'en' ? Functions.ordinal(idx + 1) : '位'); + return ( +
    +
    {order}
    +
    {title}
    +
    ({date})
    + {idx === 0 &&
    {order}
    } +
    + ); + }); + return ( +
    +

    {Functions.mlang('[en]Newly Arrived Items[/en][ja]新着アイテム[/ja]', lang)}

    +
    {list}
    +
    + ); +} + +export default RecentContents; \ No newline at end of file diff --git a/src/database/blocks/Search.tsx b/src/database/blocks/Search.tsx new file mode 100644 index 0000000..3ea0738 --- /dev/null +++ b/src/database/blocks/Search.tsx @@ -0,0 +1,90 @@ +import React, { ChangeEvent, Component, FormEvent } from 'react'; +import { Link, RouteComponentProps, withRouter } from 'react-router-dom'; +import Config, { MultiLang } from '../../config'; +import Functions from '../../functions'; +import ItemUtil, { KeywordSearchType } from '../lib/ItemUtil'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +interface State { + type: KeywordSearchType; + keyword: string; + pathname: string; +} + +class Search extends Component { + + constructor(props: Props) { + super(props); + this.state = { + type: 'all', + keyword: '', + pathname: '', + }; + this.handleChangeType = this.handleChangeType.bind(this); + this.handleChangeKeyword = this.handleChangeKeyword.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + const pathname = nextProps.location.pathname; + if (pathname !== prevState.pathname) { + if (pathname === '/database/search') { + const { type, keyword } = ItemUtil.getSearchKeywordByQuery(nextProps.location.search); + return { type, keyword, pathname }; + } + return { + type: prevState.type, + keyword: prevState.keyword, + pathname + }; + } + return null; + } + + handleChangeKeyword(event: ChangeEvent) { + const keyword = event.target.value.trim(); + this.setState({ keyword }); + } + + handleChangeType(event: ChangeEvent) { + const type = event.target.value as KeywordSearchType; + this.setState({ type }); + } + + handleSubmit(event: FormEvent) { + event.preventDefault(); + const url = ItemUtil.getSearchByKeywordUrl(this.state.type, this.state.keyword); + this.props.history.push(url); + } + + render() { + const { lang } = this.props; + const options = [ + { value: 'all', label: '[en]All[/en][ja]全て[/ja]' }, + { value: 'basic', label: '[en]Title & Keyword[/en][ja]タイトル&キーワード[/ja]' }, + ]; + Config.XOONIPS_ITEMTYPES.forEach((type) => { + options.push({value: type, label: Functions.pascalCase(type)}) + }); + return ( +
    + +    + +
    + +      + {Functions.mlang('[en]Advanced[/en][ja]詳細検索[/ja]', lang)} +
    + ); + } +} + +export default withRouter(Search); \ No newline at end of file diff --git a/src/database/item-type/binder/BinderAdvancedSearch.tsx b/src/database/item-type/binder/BinderAdvancedSearch.tsx new file mode 100644 index 0000000..55c33b3 --- /dev/null +++ b/src/database/item-type/binder/BinderAdvancedSearch.tsx @@ -0,0 +1,26 @@ +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class BinderAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'binder'; + this.title = 'Binder'; + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + ]; + return rows; + } +} + +export default BinderAdvancedSearch; diff --git a/src/database/item-type/binder/BinderDetail.tsx b/src/database/item-type/binder/BinderDetail.tsx new file mode 100644 index 0000000..45b2158 --- /dev/null +++ b/src/database/item-type/binder/BinderDetail.tsx @@ -0,0 +1,95 @@ +import React, { Component } from 'react'; +import Functions from '../../../functions'; +import ItemUtil, { ItemBinder, Item } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import { MultiLang } from '../../../config'; +import ItemType from '..'; + +interface Props { + lang: MultiLang; + item: ItemBinder; +} + +interface State { + items: Item[]; +} + +class BinderLinkItems extends Component { + constructor(props: Props) { + super(props); + this.state = { + items: [], + }; + } + + componentDidMount() { + this.updateItems(); + } + + componentDidUpdate(prevProps: Props, prevState: State) { + const prevItemIds = prevProps.item.item_link; + const nextItemIds = this.props.item.item_link; + if (prevItemIds.toString() !== nextItemIds.toString()) { + this.updateItems(); + } + } + + updateItems() { + const { item } = this.props; + const itemIds = item.item_link; + ItemUtil.getList(itemIds, (results) => { + const items = results.data; + this.setState({ items }); + }); + } + + render() { + const { lang } = this.props; + return ( + + + {this.state.items.map((item, idx) => { + const evenodd = idx % 2 ? 'even' : 'odd'; + return ; + })} + +
    + ); + } +} + +class BinderDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemBinder; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: 'Index', value: }, + ]; + } + + render() { + const { lang } = this.props; + const item = this.props.item as ItemBinder; + const detail = super.render.call(this); + return ( + <> + {detail} +

    Registered Items

    + + + ); + } +} + +export default BinderDetail; \ No newline at end of file diff --git a/src/database/item-type/binder/BinderList.tsx b/src/database/item-type/binder/BinderList.tsx new file mode 100644 index 0000000..2393869 --- /dev/null +++ b/src/database/item-type/binder/BinderList.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_binder.gif'; +import { ItemBinder } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class BinderList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Binder'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemBinder; + return ( + <> + {Functions.mlang(item.title, lang)}
    + {Functions.mlang(item.description, lang)} + + ); + } +} + +export default BinderList; diff --git a/src/database/item-type/binder/BinderTop.tsx b/src/database/item-type/binder/BinderTop.tsx new file mode 100644 index 0000000..cc714b7 --- /dev/null +++ b/src/database/item-type/binder/BinderTop.tsx @@ -0,0 +1,15 @@ +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_binder.gif'; + +class BinderTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'binder'; + this.label = 'Binder'; + this.icon = iconFile; + this.description = '[en]Binder collection.[/en][ja]バインダー[/ja]'; + } +} + +export default BinderTop; \ No newline at end of file diff --git a/src/database/item-type/binder/index.tsx b/src/database/item-type/binder/index.tsx new file mode 100644 index 0000000..3ae15c1 --- /dev/null +++ b/src/database/item-type/binder/index.tsx @@ -0,0 +1,13 @@ +import BinderAdvancedSearch from './BinderAdvancedSearch'; +import BinderDetail from './BinderDetail'; +import BinderList from './BinderList'; +import BinderTop from './BinderTop'; + +const ItemTypeBinder = { + Top: BinderTop, + List: BinderList, + Detail: BinderDetail, + AdvancedSearch: BinderAdvancedSearch, +}; + +export default ItemTypeBinder; diff --git a/src/database/item-type/book/BookAdvancedSearch.tsx b/src/database/item-type/book/BookAdvancedSearch.tsx new file mode 100644 index 0000000..b08534f --- /dev/null +++ b/src/database/item-type/book/BookAdvancedSearch.tsx @@ -0,0 +1,38 @@ +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class BookAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'book'; + this.title = 'Book'; + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['author'] = ''; + this.state.values['editor'] = ''; + this.state.values['publisher'] = ''; + this.state.values['publication_year'] = ''; + this.state.values['isbn'] = ''; + this.state.values['file.book_pdf.original_file_name'] = ''; + } + + getRows() { + const rows = [ + { label: '[en]Book Title[/en][ja]著書名[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Author[/en][ja]著者[/ja]', value: this.renderFieldInputText('author', 50) }, + { label: '[en]Editor[/en][ja]編集者[/ja]', value: this.renderFieldInputText('editor', 50) }, + { label: '[en]Publisher[/en][ja]出版社[/ja]', value: this.renderFieldInputText('publisher', 50) }, + { label: '[en]Publication Year[/en][ja]出版年[/ja]', value: this.renderFieldInputText('publication_year', 10) }, + { label: 'ISBN', value: this.renderFieldInputText('isbn', 50) }, + { label: '[en]PDF File[/en][ja]PDF ファイル[/ja]', value: this.renderFieldInputText('file.book_pdf.original_file_name', 50) }, + ]; + return rows; + } +} + +export default BookAdvancedSearch; diff --git a/src/database/item-type/book/BookDetail.tsx b/src/database/item-type/book/BookDetail.tsx new file mode 100644 index 0000000..9099abe --- /dev/null +++ b/src/database/item-type/book/BookDetail.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import Functions from '../../../functions'; +import { ItemBook } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; + +class BookDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemBook; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Book Title[/en][ja]著書名[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Author[/en][ja]著者[/ja]', value: }, + { label: '[en]Editor[/en][ja]編集者[/ja]', value: Functions.mlang(item.editor, lang) }, + { label: '[en]Publisher[/en][ja]出版社[/ja]', value: Functions.mlang(item.publisher, lang) }, + { label: '[en]Publication Year[/en][ja]出版年[/ja]', value: item.publication_year }, + { label: 'URL', value: {item.url} }, + { label: '[en]PDF File[/en][ja]PDF ファイル[/ja]', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + } +} + +export default BookDetail; diff --git a/src/database/item-type/book/BookList.tsx b/src/database/item-type/book/BookList.tsx new file mode 100644 index 0000000..9267be1 --- /dev/null +++ b/src/database/item-type/book/BookList.tsx @@ -0,0 +1,31 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_book.gif'; +import { ItemBook } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class BookList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Book'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemBook; + const authors = item.author.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {authors} + + ); + } +} + +export default BookList; diff --git a/src/database/item-type/book/BookTop.tsx b/src/database/item-type/book/BookTop.tsx new file mode 100644 index 0000000..4fb2c35 --- /dev/null +++ b/src/database/item-type/book/BookTop.tsx @@ -0,0 +1,15 @@ +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_book.gif'; + +class BookTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'book'; + this.label = 'Book'; + this.icon = iconFile; + this.description = '[en]Related book collection.[/en][ja]関連書籍[/ja]'; + } +} + +export default BookTop; \ No newline at end of file diff --git a/src/database/item-type/book/index.tsx b/src/database/item-type/book/index.tsx new file mode 100644 index 0000000..3187d8b --- /dev/null +++ b/src/database/item-type/book/index.tsx @@ -0,0 +1,13 @@ +import BookTop from './BookTop'; +import BookList from './BookList'; +import BookDetail from './BookDetail'; +import BookAdvancedSearch from './BookAdvancedSearch'; + +const ItemTypeBook = { + Top: BookTop, + List: BookList, + Detail: BookDetail, + AdvancedSearch: BookAdvancedSearch, +}; + +export default ItemTypeBook; diff --git a/src/database/item-type/conference/ConferenceAdvancedSearch.tsx b/src/database/item-type/conference/ConferenceAdvancedSearch.tsx new file mode 100644 index 0000000..505835c --- /dev/null +++ b/src/database/item-type/conference/ConferenceAdvancedSearch.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { ItemConferenceSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class ConferenceAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'conference'; + this.title = 'Conference'; + const now = new Date(); + const year = String(now.getFullYear()); + const month = String(now.getMonth() + 1); + const mday = String(now.getDate()); + this.state.values['title'] = ''; + this.state.values['presentation_type'] = ''; + this.state.values['author'] = ''; + this.state.values['conference_from_year'] = year; + this.state.values['conference_from_month'] = month; + this.state.values['conference_from_mday'] = mday; + this.state.values['conference_to_year'] = year; + this.state.values['conference_to_month'] = month; + this.state.values['conference_to_mday'] = mday; + this.setIgnoreKey('conference_from_year'); + this.setIgnoreKey('conference_from_month'); + this.setIgnoreKey('conference_from_mday'); + this.setIgnoreKey('conference_to_year'); + this.setIgnoreKey('conference_to_month'); + this.setIgnoreKey('conference_to_mday'); + } + + renderDate() { + return ( + <> +
    + {this.renderFieldDate('From', 'conference_from_year', 'conference_from_month', 'conference_from_mday')} + +
    +
    + {this.renderFieldDate('To', 'conference_to_year', 'conference_to_month', 'conference_to_mday')} +
    + + ); + } + + getRows() { + const rows = [ + { label: '[en]Presentation Title[/en][ja]発表議題[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Presentation Type[/en][ja]発表資料ファイル形式[/ja]', value: this.renderFieldSelect('presentation_type', ItemConferenceSubTypes) }, + { label: '[en]Author[/en][ja]発表者[/ja]', value: this.renderFieldInputText('author', 50) }, + { label: '[en]Date[/en][ja]日付[/ja]', value: this.renderDate() } + ]; + return rows; + } +} + +export default ConferenceAdvancedSearch; \ No newline at end of file diff --git a/src/database/item-type/conference/ConferenceDetail.tsx b/src/database/item-type/conference/ConferenceDetail.tsx new file mode 100644 index 0000000..6d2d6e3 --- /dev/null +++ b/src/database/item-type/conference/ConferenceDetail.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import Functions from '../../../functions'; +import { ItemConference } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import ConferenceUtil from './ConferenceUtil'; + +class ConferenceDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemConference; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Conference Title[/en][ja]学会名[/ja]', value: Functions.mlang(item.conference_title, lang) }, + { label: '[en]Place[/en][ja]開催地[/ja]', value: item.place }, + { label: '[en]Date[/en][ja]日付[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Presentation Title[/en][ja]発表議題[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Author[/en][ja]発表者[/ja]', value: }, + { label: '[en]Abstract[/en][ja]要約[/ja]', value: }, + { label: '[en]Presentation File[/en][ja]発表資料[/ja]', value: }, + { label: '[en]Presentation Type[/en][ja]発表資料ファイル形式[/ja]', value: }, + { label: '[en]Conference Paper[/en][ja]学会資料[/ja]', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + } +} + +export default ConferenceDetail; \ No newline at end of file diff --git a/src/database/item-type/conference/ConferenceList.tsx b/src/database/item-type/conference/ConferenceList.tsx new file mode 100644 index 0000000..b03298c --- /dev/null +++ b/src/database/item-type/conference/ConferenceList.tsx @@ -0,0 +1,33 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import { ItemConference } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; +import ConferenceUtil from './ConferenceUtil'; +import iconFile from '../../assets/images/icon_conference.gif'; +import Functions from '../../../functions'; + +class ConferenceList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Conference'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemConference; + const authors = item.author.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {Functions.mlang(item.conference_title, lang)} ()
    + {authors} + + ); + } +} + +export default ConferenceList; \ No newline at end of file diff --git a/src/database/item-type/conference/ConferenceTop.tsx b/src/database/item-type/conference/ConferenceTop.tsx new file mode 100644 index 0000000..885d9b7 --- /dev/null +++ b/src/database/item-type/conference/ConferenceTop.tsx @@ -0,0 +1,19 @@ +import { ItemConferenceSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_conference.gif'; + +class ConferenceTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'conference'; + this.label = 'Conference'; + this.icon = iconFile; + // DBPF: + // this.description = '[en]Electrical presentation files for conference.[/en][ja]学会発表[/ja]'; + this.description = '[en]Presentations in conferences.[/en][ja]学術会議での発表[/ja]'; + this.subTypes = ItemConferenceSubTypes; + } +} + +export default ConferenceTop; \ No newline at end of file diff --git a/src/database/item-type/conference/ConferenceUtil.tsx b/src/database/item-type/conference/ConferenceUtil.tsx new file mode 100644 index 0000000..6cdbe2b --- /dev/null +++ b/src/database/item-type/conference/ConferenceUtil.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemConference, ItemConferenceSubType, ItemConferenceSubTypes } from '../../lib/ItemUtil'; + +interface PresentationTypeProps { + lang: MultiLang; + type: ItemConferenceSubType; +} + +const PresentationType = (props: PresentationTypeProps) => { + const { type } = props; + const subtype = ItemConferenceSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +interface ConferenceDateProps { + lang: MultiLang; + item: ItemConference; +} + +const ConferenceDate = (props: ConferenceDateProps) => { + const { item } = props; + const monthStr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const from = 'From: ' + monthStr[item.conference_from_month - 1] + ' ' + item.conference_from_mday + ', ' + item.conference_from_year; + const to = 'To: ' + monthStr[item.conference_to_month - 1] + ' ' + item.conference_to_mday + ', ' + item.conference_to_year; + return ({from} {to}); +} + +const ConferenceUtil = { + PresentationType, + ConferenceDate, +} + +export default ConferenceUtil; \ No newline at end of file diff --git a/src/database/item-type/conference/index.tsx b/src/database/item-type/conference/index.tsx new file mode 100644 index 0000000..75272c4 --- /dev/null +++ b/src/database/item-type/conference/index.tsx @@ -0,0 +1,13 @@ +import ConferenceTop from './ConferenceTop'; +import ConferenceList from './ConferenceList'; +import ConferenceDetail from './ConferenceDetail'; +import ConferenceAdvancedSearch from './ConferenceAdvancedSearch'; + +const ItemTypeConference = { + Top: ConferenceTop, + List: ConferenceList, + Detail: ConferenceDetail, + AdvancedSearch: ConferenceAdvancedSearch, +}; + +export default ItemTypeConference; \ No newline at end of file diff --git a/src/database/item-type/data/DataAdvancedSearch.tsx b/src/database/item-type/data/DataAdvancedSearch.tsx new file mode 100644 index 0000000..e408d8b --- /dev/null +++ b/src/database/item-type/data/DataAdvancedSearch.tsx @@ -0,0 +1,46 @@ +import { ItemDataSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class DataAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'data'; + this.title = 'Data'; + const now = new Date(); + const year = String(now.getFullYear()); + const month = String(now.getMonth() + 1); + const mday = String(now.getDate()); + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['data_type'] = ''; + this.state.values['experimenter'] = ''; + this.state.values['publication_year'] = year; + this.state.values['publication_month'] = month; + this.state.values['publication_mday'] = mday; + this.state.values['file.preview.caption'] = ''; + this.state.values['file.data_file.original_file_name'] = ''; + this.setIgnoreKey('publication_year'); + this.setIgnoreKey('publication_month'); + this.setIgnoreKey('publication_mday'); + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Data Type[/en][ja]データタイプ[/ja]', value: this.renderFieldSelect('data_type', ItemDataSubTypes) }, + { label: '[en]Experimenter[/en][ja]実験者[/ja]', value: this.renderFieldInputText('experimenter', 50) }, + { label: '[en]Date[/en][ja]日付[/ja]', value: this.renderFieldDate('', 'publication_year', 'publication_month', 'publication_mday') }, + { label: '[en]Caption[/en][ja]キャプション[/ja]', value: this.renderFieldInputText('file.preview.caption', 50) }, + { label: '[en]Data File[/en][ja]データファイル[/ja]', value: this.renderFieldInputText('file.data_file.original_file_name', 50) }, + ]; + return rows; + } +} + +export default DataAdvancedSearch; \ No newline at end of file diff --git a/src/database/item-type/data/DataDetail.tsx b/src/database/item-type/data/DataDetail.tsx new file mode 100644 index 0000000..bf3a024 --- /dev/null +++ b/src/database/item-type/data/DataDetail.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import Functions from '../../../functions'; +import ItemUtil, { ItemData } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import SimPFLinkIcon from '../lib/field/SimPFLinkIcon'; +import DataUtil from './DataUtil'; + +class DataDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemData; + const fields = [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Date[/en][ja]日付[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Data Type[/en][ja]データタイプ[/ja]', value: }, + { label: '[en]Experimenter[/en][ja]実験者[/ja]', value: }, + { label: '[en]Preview[/en][ja]プレビュー[/ja]', value: }, + { label: '[en]Data File[/en][ja]データファイル[/ja]', value: }, + { label: 'Readme', value: }, + { label: 'Rights', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id); + if (simpfLinkUrl !== '') { + const field = { label: 'Online Simulation', value: }; + fields.splice(14, 0, field); + } + return fields; + } +} + +export default DataDetail; \ No newline at end of file diff --git a/src/database/item-type/data/DataList.tsx b/src/database/item-type/data/DataList.tsx new file mode 100644 index 0000000..be78ce1 --- /dev/null +++ b/src/database/item-type/data/DataList.tsx @@ -0,0 +1,31 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_data.gif'; +import { ItemData } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class DataList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Data'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemData; + const authors = item.experimenter.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {authors} + + ); + } +} + +export default DataList; \ No newline at end of file diff --git a/src/database/item-type/data/DataTop.tsx b/src/database/item-type/data/DataTop.tsx new file mode 100644 index 0000000..3054495 --- /dev/null +++ b/src/database/item-type/data/DataTop.tsx @@ -0,0 +1,19 @@ +import { ItemDataSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_data.gif'; + +class DataTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'data'; + this.label = 'Data'; + this.icon = iconFile; + // DBPF: + // this.description = '[en]Result data in numerical text/image/movie formats.[/en][ja]実験結果の数値データ/画像/動画など[/ja]'; + this.description = '[en]Data from experiments or simulations.[/en][ja]実験やシミュレーションで得られたデータ[/ja]'; + this.subTypes = ItemDataSubTypes; + } +} + +export default DataTop; \ No newline at end of file diff --git a/src/database/item-type/data/DataUtil.tsx b/src/database/item-type/data/DataUtil.tsx new file mode 100644 index 0000000..9944054 --- /dev/null +++ b/src/database/item-type/data/DataUtil.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemDataSubType, ItemDataSubTypes } from '../../lib/ItemUtil'; + +interface DataTypeProps { + lang: MultiLang; + type: ItemDataSubType; +} + +const DataType = (props: DataTypeProps) => { + const { type } = props; + const subtype = ItemDataSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +const DataUtil = { + DataType, +} + +export default DataUtil; \ No newline at end of file diff --git a/src/database/item-type/data/index.tsx b/src/database/item-type/data/index.tsx new file mode 100644 index 0000000..21a88d8 --- /dev/null +++ b/src/database/item-type/data/index.tsx @@ -0,0 +1,13 @@ +import DataTop from './DataTop'; +import DataList from './DataList'; +import DataDetail from './DataDetail'; +import DataAdvancedSearch from './DataAdvancedSearch'; + +const ItemTypeData = { + Top: DataTop, + List: DataList, + Detail: DataDetail, + AdvancedSearch: DataAdvancedSearch, +}; + +export default ItemTypeData; \ No newline at end of file diff --git a/src/database/item-type/files/FilesAdvancedSearch.tsx b/src/database/item-type/files/FilesAdvancedSearch.tsx new file mode 100644 index 0000000..57b27d3 --- /dev/null +++ b/src/database/item-type/files/FilesAdvancedSearch.tsx @@ -0,0 +1,30 @@ +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class FilesAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'files'; + this.title = 'Files'; + this.state.values['title'] = ''; + this.state.values['data_file_name'] = ''; + this.state.values['data_file_mimetype'] = ''; + this.state.values['data_file_filetype'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '- [en]File Name[/en][ja]ファイル名[/ja]', value: this.renderFieldInputText('data_file_name', 50) }, + { label: '- [en]MIME Type[/en][ja]MIMEタイプ[/ja]', value: this.renderFieldInputText('data_file_mimetype', 50) }, + { label: '- [en]File Type[/en][ja]ファイルタイプ[/ja]', value: this.renderFieldInputText('data_file_filetype', 20) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + ]; + return rows; + } +} + +export default FilesAdvancedSearch; \ No newline at end of file diff --git a/src/database/item-type/files/FilesDetail.tsx b/src/database/item-type/files/FilesDetail.tsx new file mode 100644 index 0000000..89091d0 --- /dev/null +++ b/src/database/item-type/files/FilesDetail.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import Functions from '../../../functions'; +import { ItemFiles } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; + +class FilesDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemFiles; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Data File[/en][ja]データファイル[/ja]', value: }, + { label: '- [en]File Name[/en][ja]ファイル名[/ja]', value: item.data_file_name }, + { label: '- [en]MIME Type[/en][ja]MIMEタイプ[/ja]', value: item.data_file_mimetype }, + { label: '- [en]File Type[/en][ja]ファイルタイプ[/ja]', value: item.data_file_filetype }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + } +} + +export default FilesDetail; diff --git a/src/database/item-type/files/FilesList.tsx b/src/database/item-type/files/FilesList.tsx new file mode 100644 index 0000000..465237d --- /dev/null +++ b/src/database/item-type/files/FilesList.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_files.gif'; +import { ItemFiles } from '../../lib/ItemUtil'; +import Contributer from '../lib/field/Contributer'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class FilesList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Files'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemFiles; + return ( + <> + {Functions.mlang(item.title, lang)}
    +
    + {item.data_file_mimetype} + + ); + } +} + +export default FilesList; \ No newline at end of file diff --git a/src/database/item-type/files/FilesTop.tsx b/src/database/item-type/files/FilesTop.tsx new file mode 100644 index 0000000..3e6fae9 --- /dev/null +++ b/src/database/item-type/files/FilesTop.tsx @@ -0,0 +1,17 @@ +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_files.gif'; +import { ItemFilesSubTypes } from '../../lib/ItemUtil'; + +class FilesTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'files'; + this.label = 'Files'; + this.icon = iconFile; + this.description = '[en]Various type of File.[/en][ja]ファイル[/ja]'; + this.subTypes = ItemFilesSubTypes; + } +} + +export default FilesTop; \ No newline at end of file diff --git a/src/database/item-type/files/FilesUtil.tsx b/src/database/item-type/files/FilesUtil.tsx new file mode 100644 index 0000000..0e10e42 --- /dev/null +++ b/src/database/item-type/files/FilesUtil.tsx @@ -0,0 +1,5 @@ + +const FilesUtil = { +} + +export default FilesUtil; \ No newline at end of file diff --git a/src/database/item-type/files/index.tsx b/src/database/item-type/files/index.tsx new file mode 100644 index 0000000..00ebdea --- /dev/null +++ b/src/database/item-type/files/index.tsx @@ -0,0 +1,13 @@ +import FilesTop from './FilesTop'; +import FilesList from './FilesList'; +import FilesDetail from './FilesDetail'; +import FilesAdvancedSearch from './FilesAdvancedSearch'; + +const ItemTypeFiles = { + Top: FilesTop, + List: FilesList, + Detail: FilesDetail, + AdvancedSearch: FilesAdvancedSearch, +}; + +export default ItemTypeFiles; \ No newline at end of file diff --git a/src/database/item-type/index.tsx b/src/database/item-type/index.tsx new file mode 100644 index 0000000..900cacc --- /dev/null +++ b/src/database/item-type/index.tsx @@ -0,0 +1,179 @@ +import React from 'react'; +import { MultiLang } from '../../config'; +import AdvancedSearchQuery from '../lib/AdvancedSearchQuery'; +import { Item, ItemBinder, ItemBook, ItemConference, ItemData, ItemFiles, ItemModel, ItemPaper, ItemPresentation, ItemSimulator, ItemStimulus, ItemTool, ItemUrl, ItemMemo } from '../lib/ItemUtil'; +import ItemTypeBinder from './binder'; +import ItemTypeBook from './book'; +import ItemTypeConference from './conference'; +import ItemTypeData from './data'; +import ItemTypeFiles from './files'; +import ItemTypeMemo from './memo'; +import ItemTypeModel from './model'; +import ItemTypePaper from './paper'; +import ItemTypePresentation from './presentation'; +import ItemTypeSimulator from './simulator'; +import ItemTypeStimulus from './stimulus'; +import ItemTypeTool from './tool'; +import ItemTypeUrl from './url'; + +interface TopProps { + lang: MultiLang; + type: string; +} +const Top = (props: TopProps) => { + const { lang, type } = props; + switch (type) { + case 'xnpbinder': + return ; + case 'xnpbook': + return ; + case 'xnpconference': + return ; + case 'xnpdata': + return ; + case 'xnpfiles': + return ; + case 'xnpmemo': + return ; + case 'xnpmodel': + return ; + case 'xnppaper': + return ; + case 'xnppresentation': + return ; + case 'xnpsimulator': + return ; + case 'xnpstimulus': + return ; + case 'xnptool': + return ; + case 'xnpurl': + return ; + default: + return null; + } +} + +interface ListProps { + lang: MultiLang; + item: Item; +} +const List = (props: ListProps) => { + const { lang, item } = props; + switch (item.item_type_name) { + case 'xnpbinder': + return ; + case 'xnpbook': + return ; + case 'xnpconference': + return ; + case 'xnpdata': + return ; + case 'xnpfiles': + return ; + case 'xnpmemo': + return ; + case 'xnpmodel': + return ; + case 'xnppaper': + return ; + case 'xnppresentation': + return ; + case 'xnpsimulator': + return ; + case 'xnpstimulus': + return ; + case 'xnptool': + return ; + case 'xnpurl': + return ; + default: + return null; + } +} + +interface DetailProps { + lang: MultiLang; + item: Item; +} +const Detail = (props: DetailProps) => { + const { lang, item } = props; + switch (item.item_type_name) { + case 'xnpbinder': + return ; + case 'xnpbook': + return ; + case 'xnpconference': + return ; + case 'xnpdata': + return ; + case 'xnpfiles': + return ; + case 'xnpmemo': + return ; + case 'xnpmodel': + return ; + case 'xnppaper': + return ; + case 'xnppresentation': + return ; + case 'xnpsimulator': + return ; + case 'xnpstimulus': + return ; + case 'xnptool': + return ; + case 'xnpurl': + return ; + default: + return null; + } +} + +interface AdvancedSearchProps { + lang: MultiLang; + type: string; + query: AdvancedSearchQuery; +} +const AdvancedSearch = (props: AdvancedSearchProps) => { + const { lang, type, query } = props; + switch (type) { + case 'xnpbinder': + return ; + case 'xnpbook': + return ; + case 'xnpconference': + return ; + case 'xnpdata': + return ; + case 'xnpfiles': + return ; + case 'xnpmemo': + return ; + case 'xnpmodel': + return ; + case 'xnppaper': + return ; + case 'xnppresentation': + return ; + case 'xnpsimulator': + return ; + case 'xnpstimulus': + return ; + case 'xnptool': + return ; + case 'xnpurl': + return ; + default: + return null; + } +} + +const ItemType = { + Top, + List, + Detail, + AdvancedSearch +} + +export default ItemType; \ No newline at end of file diff --git a/src/database/item-type/lib/AdvancedSearchBase.tsx b/src/database/item-type/lib/AdvancedSearchBase.tsx new file mode 100644 index 0000000..f1c5286 --- /dev/null +++ b/src/database/item-type/lib/AdvancedSearchBase.tsx @@ -0,0 +1,189 @@ +import React, { ChangeEvent, Component } from 'react'; +import { MultiLang } from '../../../config'; +import Functions from '../../../functions'; +import AdvancedSearchQuery from '../../lib/AdvancedSearchQuery'; +import { ItemSubTypes } from '../../lib/ItemUtil'; + +export interface AdvancedSearchBaseProps { + lang: MultiLang; + query: AdvancedSearchQuery; +} + +interface State { + show: boolean; + values: any; +} + +class AdvancedSearchBase extends Component { + + protected type: string = 'base' + protected title: string = 'Base'; + protected query: AdvancedSearchQuery; + protected ignoreKeys: string[] = []; + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.state = { + show: false, + values: {}, + } + this.query = props.query; + this.handleChangeTitleCheck = this.handleChangeTitleCheck.bind(this); + } + + updateQuery(key: string, value: string) { + if (this.ignoreKeys.includes(key)) { + this.query.delete(this.type, key); + } else { + this.query.set(this.type, key, value); + } + } + + setIgnoreKey(key: string) { + if (!this.ignoreKeys.includes(key)) { + this.ignoreKeys = this.ignoreKeys.concat(key); + } + this.query.delete(this.type, key); + } + + deleteIgnoreKey(key: string) { + if (this.ignoreKeys.includes(key)) { + this.ignoreKeys = this.ignoreKeys.filter((v) => { + return (v !== key); + }); + } + this.query.set(this.type, key, this.state.values[key]); + } + + updateField(key: string, value: string) { + let values = Object.assign({}, this.state.values); + values[key] = value; + this.updateQuery(key, value); + this.setState({ values }); + } + + handleChangeTitleCheck(e: ChangeEvent) { + const show = e.target.checked; + if (show) { + Object.keys(this.state.values).forEach((key) => { + const value = this.state.values[key]; + this.updateQuery(key, value); + }); + } else { + this.query.deleteType(this.type); + } + this.setState({ show }); + } + + getRows(): { label: string, value: JSX.Element }[] { + return []; + } + + renderFieldInputText(key: string, size: number) { + const onChange = (e: ChangeEvent) => { + this.updateField(key, e.target.value); + }; + return ( + + ); + } + + renderFieldSelect(key: string, values: ItemSubTypes) { + const onChange = (e: ChangeEvent) => { + this.updateField(key, e.target.value); + }; + const options = values.map(({ type, label }, i) => { + return ; + }); + return ( + + ); + } + + renderFieldDate(label: string, keyYear: string, keyMonth: string, keyMday: string) { + const onChange = (e: ChangeEvent) => { + if (e.target.checked) { + this.deleteIgnoreKey(keyYear); + keyMonth !== '' && this.deleteIgnoreKey(keyMonth); + keyMday !== '' && this.deleteIgnoreKey(keyMday); + } else { + this.setIgnoreKey(keyYear); + keyMonth !== '' && this.setIgnoreKey(keyMonth); + keyMday !== '' && this.setIgnoreKey(keyMday); + } + }; + const month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const monthOptions = month.map((value, i) => { + return ; + }) + let mdayOptions: JSX.Element[] = []; + for (let i = 1; i <= 31; i++) { + mdayOptions.push() + } + return ( +
    + + {label.length !== 0 && } + {keyMonth !== '' && + + } + {keyMday !== '' && + + } + this.updateField(keyYear, e.target.value)} /> +
    + ); + } + + renderBody() { + const { lang } = this.props; + if (this.state.show === false) { + return null; + } + const rows = this.getRows(); + const fields = rows.map((value, idx) => { + const evenodd = idx % 2 === 0 ? 'even' : 'odd'; + return ( + + {Functions.mlang(value.label, lang)} + {value.value} + + ); + }); + return ( + + + {fields} + +
    + ); + } + + render() { + return ( +
    + + + + + + +
    + + {this.title} +
    + {this.renderBody()} +
    + ); + } + +} + +export default AdvancedSearchBase; \ No newline at end of file diff --git a/src/database/item-type/lib/DetailBase.tsx b/src/database/item-type/lib/DetailBase.tsx new file mode 100644 index 0000000..3208d12 --- /dev/null +++ b/src/database/item-type/lib/DetailBase.tsx @@ -0,0 +1,43 @@ +import React, { Component, ReactNode } from 'react'; +import { MultiLang } from '../../../config'; +import Functions from '../../../functions'; +import { Item } from '../../lib/ItemUtil'; + +export interface DetailBaseField { + label: string; + value: ReactNode; +} + +export interface DetailBaseProps { + lang: MultiLang; + item: Item +} + +class DetailBase extends Component { + + getFields(): DetailBaseField[] { + return []; + } + + render() { + const { lang } = this.props; + const elements = this.getFields().map((value, idx) => { + const evenodd = idx % 2 === 0 ? 'even' : 'odd'; + return ( + + {Functions.mlang(value.label, lang)} + {value.value} + + ) + }); + return ( + + + {elements} + +
    + ); + } +} + +export default DetailBase; \ No newline at end of file diff --git a/src/database/item-type/lib/ListBase.tsx b/src/database/item-type/lib/ListBase.tsx new file mode 100644 index 0000000..435eb36 --- /dev/null +++ b/src/database/item-type/lib/ListBase.tsx @@ -0,0 +1,50 @@ +import React, { Component } from 'react'; +import { MultiLang } from '../../../config'; +import ItemUtil, { Item } from '../../lib/ItemUtil'; +import SimPFLinkIcon from './field/SimPFLinkIcon'; + +export interface ListBaseProps { + lang: MultiLang; + item: Item +}; + +class ListBase extends Component { + + protected label = ''; + protected icon = ''; + protected url: string; + protected simpfLinkUrl: string; + + constructor(props: ListBaseProps) { + super(props); + this.url = ItemUtil.getUrl(props.item); + this.simpfLinkUrl = ItemUtil.getSimPFLinkUrl(props.item.item_id); + } + + renderBody() { + return <>; + } + + render() { + const { lang } = this.props; + return ( + + + + + + + + +
    + {this.label} + + {this.renderBody()} + + +
    + ); + } +} + +export default ListBase; \ No newline at end of file diff --git a/src/database/item-type/lib/TopBase.tsx b/src/database/item-type/lib/TopBase.tsx new file mode 100644 index 0000000..a41f596 --- /dev/null +++ b/src/database/item-type/lib/TopBase.tsx @@ -0,0 +1,47 @@ +import React, { Component, Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../../config'; +import Functions from '../../../functions'; +import ItemUtil, { ItemSubTypes } from '../../lib/ItemUtil'; + +export interface TopBaseProps { + lang: MultiLang; +} + +class TopBase extends Component { + + protected type: string = ''; + protected label: string = ''; + protected icon: string = ''; + protected description: string = ''; + protected subTypes: ItemSubTypes = []; + + render() { + const { lang } = this.props; + const url = ItemUtil.getItemTypeSearchUrl(this.type); + const links = this.subTypes.map(({ type, label }, i) => { + return {i > 0 && ' / '}{label}; + }); + return ( +
    + + + + + + + +
    + {this.label} + + {this.label} +
    +
    +
    {Functions.mlang(this.description, lang)}
    + {links} +
    + ); + } +} + +export default TopBase; \ No newline at end of file diff --git a/src/database/item-type/lib/field/Author.tsx b/src/database/item-type/lib/field/Author.tsx new file mode 100644 index 0000000..9181ca8 --- /dev/null +++ b/src/database/item-type/lib/field/Author.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; + +interface Props { + lang: MultiLang; + author: string[]; +} + +const Author = (props: Props) => { + const { author } = props; + if (author.length === 0) { + return null; + } + const elements = author.map((value, idx) => { + const evenodd = idx % 2 === 0 ? 'even' : 'odd'; + return {value}; + }); + return {elements}
    ; +} + +export default Author; \ No newline at end of file diff --git a/src/database/item-type/lib/field/ChangeLog.tsx b/src/database/item-type/lib/field/ChangeLog.tsx new file mode 100644 index 0000000..f3d9ba9 --- /dev/null +++ b/src/database/item-type/lib/field/ChangeLog.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; +import { ItemBasicChangeLog } from '../../../lib/ItemUtil'; +import DateTime from './DateTime'; + +interface Props { + lang: MultiLang; + changelog: ItemBasicChangeLog[]; +} + +const ChangeLog = (props: Props) => { + const { lang, changelog } = props; + if (changelog.length === 0) { + return null; + } + const elements = changelog.map((value, i) => { + return ( + + + {Functions.mlang(value.log, lang)} + + ); + }); + return ({elements}
    ); +} + +export default ChangeLog; \ No newline at end of file diff --git a/src/database/item-type/lib/field/Contributer.tsx b/src/database/item-type/lib/field/Contributer.tsx new file mode 100644 index 0000000..63261a9 --- /dev/null +++ b/src/database/item-type/lib/field/Contributer.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; + +interface Props { + lang: MultiLang; + uname: string; + name: string +} + +const Contributer = (props: Props) => { + const { lang, name, uname } = props; + const unsubscribed = '([en]Unsubscribed User[/en][ja]退会済みユーザ[/ja])'; + const label = uname === '' ? unsubscribed : (name === '' ? uname : name + ' (' + uname + ')'); + return {Functions.mlang(label, lang)}; +} + +export default Contributer; \ No newline at end of file diff --git a/src/database/item-type/lib/field/CreativeCommons.tsx b/src/database/item-type/lib/field/CreativeCommons.tsx new file mode 100644 index 0000000..b545f02 --- /dev/null +++ b/src/database/item-type/lib/field/CreativeCommons.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; + +export type CreativeCommonsType = 'by' | 'by-nc' | 'by-nc-nd' | 'by-nc-sa' | 'by-nd' | 'by-sa'; + +export const getCreativeCommonsType = (ccCommercialUse: number, ccModification: number): CreativeCommonsType => { + const cc = ccCommercialUse * 10 + ccModification; + switch (cc) { + case 0: + return 'by-nc-nd'; + case 1: + return 'by-nc-sa'; + case 2: + return 'by-nc'; + case 10: + return 'by-nd'; + case 11: + return 'by-sa'; + case 12: + default: + return 'by'; + } +} + +interface Props { + lang: MultiLang; + type: CreativeCommonsType; +} + +const CreativeCommons = (props: Props) => { + const { type } = props; + const url = 'http://creativecommons.org/licenses/' + type + '/4.0/'; + const logoUrl = 'https://i.creativecommons.org/l/' + type + '/4.0/88x31.png'; + const labels = { + by: 'Attribution', + nc: 'NonCommercial', + nd: 'NoDerivatives', + sa: 'ShareAlike', + } + const label = type.split('-').map((value) => { + const prop = value as 'by' | 'nc' | 'nd' | 'sa'; + return labels[prop]; + }).join('-'); + return ( + + + + + + + +
    Creative Commons LicenseThis work is licensed under a Criative Commons {label} 4.0 International License.
    + ); +} + +export default CreativeCommons; \ No newline at end of file diff --git a/src/database/item-type/lib/field/DateTime.tsx b/src/database/item-type/lib/field/DateTime.tsx new file mode 100644 index 0000000..0e9b1dc --- /dev/null +++ b/src/database/item-type/lib/field/DateTime.tsx @@ -0,0 +1,21 @@ +import moment from 'moment'; +import React from 'react'; +import { MultiLang } from '../../../../config'; + +interface Props { + lang: MultiLang; + date: number; + onlyDate?: boolean +} + +const DateTime = (props: Props) => { + const { date, onlyDate } = props; + const d = moment(new Date(date * 1000)); + let format = 'MMM D, Y'; + if (typeof onlyDate === 'undefined' || !onlyDate) { + format += ' HH:mm:ss'; + } + return {d.format(format)}; +} + +export default DateTime; diff --git a/src/database/item-type/lib/field/Description.tsx b/src/database/item-type/lib/field/Description.tsx new file mode 100644 index 0000000..353b3d9 --- /dev/null +++ b/src/database/item-type/lib/field/Description.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import XoopsCode from '../../../../common/lib/XoopsCode'; +import { MultiLang } from '../../../../config'; + +interface Props { + lang: MultiLang; + description: string; + className?: string; +} + +const Description = (props: Props) => { + const { lang, description, className } = props; + const textarea = ; + const name = typeof className === 'undefined' ? 'description' : className; + return (
    {textarea}
    ); +} + +export default Description; \ No newline at end of file diff --git a/src/database/item-type/lib/field/FileDownloadButton.module.css b/src/database/item-type/lib/field/FileDownloadButton.module.css new file mode 100644 index 0000000..dd40e7e --- /dev/null +++ b/src/database/item-type/lib/field/FileDownloadButton.module.css @@ -0,0 +1,21 @@ +.downloadButton { + display: inline-block; + padding: 7px 20px; + text-decoration: none !important; + font-weight: normal !important; + background: #f0f0f0; + color: #000 !important; + border: solid 1px #e0e0e0; + box-shadow: 2px 2px #bbbbbb; + border-radius: 5px; +} + +.downloadButton:hover { + background: #e8e8e8 !important; + border: solid 1px #cccccc; +} + +.downloadButton:active { + transform: translate(2px, 2px); + box-shadow: none; +} \ No newline at end of file diff --git a/src/database/item-type/lib/field/FileDownloadButton.tsx b/src/database/item-type/lib/field/FileDownloadButton.tsx new file mode 100644 index 0000000..968d441 --- /dev/null +++ b/src/database/item-type/lib/field/FileDownloadButton.tsx @@ -0,0 +1,55 @@ +import React, { Component } from 'react'; +import { MultiLang } from '../../../../config'; +import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil'; +import styles from './FileDownloadButton.module.css'; +import LicenseAgreementDialog from './LicenseAgreementDialog'; + +interface Props { + lang: MultiLang; + file: ItemBasicFile; + rights: string; + useCc: number; + ccCommercialUse: number; + ccModification: number; +} + +interface State { + show: boolean; +} + +class FileDownloadButton extends Component { + + constructor(props: Props) { + super(props); + this.state = { + show: false, + }; + this.handleClickDownload = this.handleClickDownload.bind(this); + this.unsetShow = this.unsetShow.bind(this); + } + + handleClickDownload(e: React.MouseEvent) { + if (this.props.rights !== '') { + e.stopPropagation(); + e.preventDefault(); + this.setState({ show: true }); + } + } + + unsetShow() { + this.setState({ show: false }); + } + + render() { + const { lang, file, rights, useCc, ccCommercialUse, ccModification } = this.props; + const url = ItemUtil.getFileUrl(this.props.file); + return ( + <> + Download + + + ); + } +} + +export default FileDownloadButton; \ No newline at end of file diff --git a/src/database/item-type/lib/field/FileSize.tsx b/src/database/item-type/lib/field/FileSize.tsx new file mode 100644 index 0000000..0198e89 --- /dev/null +++ b/src/database/item-type/lib/field/FileSize.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; + +interface Props { + lang: MultiLang; + size: number; +} + +const FileSize = (props: Props) => { + const { size } = props; + const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + const power = size > 0 ? Math.floor(Math.log(size) / Math.log(1024)) : 0; + const label = Math.round(size / Math.pow(1024, power) * 10) / 10 + ' ' + units[power] + return {label}; +} + +export default FileSize; \ No newline at end of file diff --git a/src/database/item-type/lib/field/FreeKeyword.tsx b/src/database/item-type/lib/field/FreeKeyword.tsx new file mode 100644 index 0000000..d33437e --- /dev/null +++ b/src/database/item-type/lib/field/FreeKeyword.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; + +interface Props { + lang: MultiLang; + keyword: string[]; +} + +const FreeKeyword = (props: Props) => { + const { keyword } = props; + if (keyword.length === 0) { + return null; + } + const label = keyword.join(', '); + return ({label}); +} + +export default FreeKeyword; \ No newline at end of file diff --git a/src/database/item-type/lib/field/ItemFile.tsx b/src/database/item-type/lib/field/ItemFile.tsx new file mode 100644 index 0000000..12d52e1 --- /dev/null +++ b/src/database/item-type/lib/field/ItemFile.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; +import { ItemBasicFile } from '../../../lib/ItemUtil'; +import DateTime from './DateTime'; +import FileDownloadButton from './FileDownloadButton'; +import FileSize from './FileSize'; + +interface Props { + lang: MultiLang; + file: ItemBasicFile[]; + type: string; + rights?: string; + useCc?: number; + ccCommercialUse?: number; + ccModification?: number; + downloadLimit?: number; +} + +const ItemFile = (props: Props) => { + const { lang, file, type } = props; + const rights = typeof props.rights === 'undefined' ? '' : props.rights; + const useCc = typeof props.useCc === 'undefined' ? 0 : props.useCc; + const ccCommercialUse = typeof props.ccCommercialUse === 'undefined' ? 0 : props.ccCommercialUse; + const ccModification = typeof props.ccModification === 'undefined' ? 0 : props.ccModification; + const downloadLimit = typeof props.downloadLimit === 'undefined' ? 0 : props.downloadLimit; + const data = file.find((value) => { + return value.file_type_name === type; + }); + if (typeof data === 'undefined') { + return null; + } + const date = new Date(data.timestamp); + const timestamp = Math.floor(date.valueOf() / 1000); + return ( +
    + {data.original_file_name}
    + + + + + + +
    Type: {data.mime_type}{downloadLimit === 0 && }
    Size:
    Last updated:
    + {downloadLimit === 1 && <>
    ({Functions.mlang('[en]File has been removed[/en][ja]ファイルは削除されました[/ja]', lang)})} +
    + ); +} + +export default ItemFile; \ No newline at end of file diff --git a/src/database/item-type/lib/field/ItemIndex.tsx b/src/database/item-type/lib/field/ItemIndex.tsx new file mode 100644 index 0000000..02937f6 --- /dev/null +++ b/src/database/item-type/lib/field/ItemIndex.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; +import IndexUtil from '../../../lib/IndexUtil'; +import { ItemBasicIndex } from '../../../lib/ItemUtil'; + +interface Props { + lang: MultiLang; + index: ItemBasicIndex[]; +} + +const ItemIndex = (props: Props) => { + const { lang, index } = props; + if (index.length === 0) { + return null; + } + const elements = index.map((value, idx) => { + const evenodd = idx % 2 === 0 ? 'even' : 'odd'; + const url = IndexUtil.getUrl(value.index_id); + return ({Functions.mlang(value.title, lang)}); + }); + return ({elements}
    ); +} + +export default ItemIndex; \ No newline at end of file diff --git a/src/database/item-type/lib/field/Language.tsx b/src/database/item-type/lib/field/Language.tsx new file mode 100644 index 0000000..4099c0b --- /dev/null +++ b/src/database/item-type/lib/field/Language.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { ItemBasicLang } from '../../../lib/ItemUtil'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; + +interface Props { + lang: MultiLang; + itemLang: ItemBasicLang; +} + +const Language = (props: Props) => { + const { lang, itemLang } = props; + const langStr = { + eng: '[en]English[/en][ja]英語[/ja]', + jpn: '[en]Japanese[/en][ja]日本語[/ja]', + fra: '[en]French[/en][ja]フランス語[/ja]', + deu: '[en]German[/en][ja]ドイツ語[/ja]', + esl: '[en]Spanish[/en][ja]スペイン語[/ja]', + ita: '[en]Italian[/en][ja]イタリア語[/ja]', + dut: '[en]Dutch[/en][ja]オランダ語[/ja]', + sve: '[en]Swedish[/en][ja]スウェーデン語[/ja]', + nor: '[en]Norwegian[/en][ja]ノルウェー語[/ja]', + dan: '[en]Danish[/en][ja]デンマーク語[/ja]', + fin: '[en]Finnish[/en][ja]フィンランド語[/ja]', + por: '[en]Portuguese[/en][ja]ポルトガル語[/ja]', + chi: '[en]Chinese[/en][ja]中国語[/ja]', + kor: '[en]Korean[/en][ja]韓国語[/ja]', + } + if (!(itemLang in langStr)) { + return null; + } + return ({Functions.mlang(langStr[itemLang], lang)}); +} + +export default Language; \ No newline at end of file diff --git a/src/database/item-type/lib/field/LicenseAgreementDialog.module.css b/src/database/item-type/lib/field/LicenseAgreementDialog.module.css new file mode 100644 index 0000000..b2f4525 --- /dev/null +++ b/src/database/item-type/lib/field/LicenseAgreementDialog.module.css @@ -0,0 +1,38 @@ +.overlay { + position: fixed; + z-index: 90; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: #000000; + opacity: 0.8; +} + +.dialog { + position: fixed; + background-color: #d8d8d8; + width: 570px; + z-index: 100; + top: 50%; + left: 50%; + right: auto; + bottom: auto; + margin: 0 auto; + padding: 20px; + transform: translate(-50%, -50%); + border-radius: 5px; +} + +.box { + background-color: #fff; + padding: 10px; +} + +.download { + text-align: center; +} + +.download button { + margin: 5px 5px 0; +} \ No newline at end of file diff --git a/src/database/item-type/lib/field/LicenseAgreementDialog.tsx b/src/database/item-type/lib/field/LicenseAgreementDialog.tsx new file mode 100644 index 0000000..3d065a6 --- /dev/null +++ b/src/database/item-type/lib/field/LicenseAgreementDialog.tsx @@ -0,0 +1,115 @@ +import React, { ChangeEvent, Component, MouseEvent } from 'react'; +import { Modal } from 'react-overlays'; +import { RouteComponentProps, withRouter } from 'react-router'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; +import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil'; +import DateTime from './DateTime'; +import FileSize from './FileSize'; +import styles from './LicenseAgreementDialog.module.css'; +import Rights from './Rights'; + +interface Props extends RouteComponentProps { + lang: MultiLang; + file: ItemBasicFile; + rights: string; + useCc: number; + ccCommercialUse: number; + ccModification: number; + show: boolean; + unsetShow: () => void; +} + +interface State { + show: boolean; + disabled: boolean; +} + +class LicenseAgreementDialog extends Component { + + constructor(props: Props) { + super(props); + this.state = { + show: props.show, + disabled: false, + }; + this.handleChangeCheckbox = this.handleChangeCheckbox.bind(this); + this.handleClickDownload = this.handleClickDownload.bind(this); + this.handleClickCancel = this.handleClickCancel.bind(this); + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + if (nextProps.show && !prevState.show) { + return { disabled: true, show: nextProps.show }; + } + return null; + } + + handleChangeCheckbox(e: ChangeEvent) { + const disabled = e.target.value === '0'; + this.setState({ disabled }); + } + + handleClickDownload(e: MouseEvent) { + this.props.unsetShow(); + this.setState({ show: false }); + } + + handleClickCancel(e: MouseEvent) { + this.props.unsetShow(); + this.setState({ show: false }); + } + + renderBackdrop(props: any) { + return
    ; + } + + render() { + const { lang } = this.props; + const date = new Date(this.props.file.timestamp); + const timestamp = Math.floor(date.valueOf() / 1000); + const url = ItemUtil.getFileUrl(this.props.file); + return ( + +
    +
    + {Functions.mlang('[en]Download file information[/en][ja]ダウンロードするファイルの情報[/ja]', lang)} +
    + {this.props.file.original_file_name}
    + + + + + + +
    Type: {this.props.file.mime_type}
    Size:
    Last updated:
    +
    +
    +
    +
    + {Functions.mlang('[en]License agreement[/en][ja]ファイルのライセンス[/ja]', lang)} +
    + {Functions.mlang('[en]Please read the following license agreement carefully.[/en][ja]このファイルには下記のライセンスが設定されています。[/ja]', lang)} +
    + + {Functions.mlang('[en]I accept the terms in the license agreement.[/en][ja]ライセンスに同意します。[/ja]', lang)}
    + {Functions.mlang('[en]I do not accept the terms in the license agreement.[/en][ja]ライセンスに同意しません。[/ja]', lang)}
    +
    +
    +
    +
    +
    + Acceptance is needed to download this file. +
    + + + + +
    +
    +
    + ); + } +} + +export default withRouter(LicenseAgreementDialog); \ No newline at end of file diff --git a/src/database/item-type/lib/field/Preview.module.css b/src/database/item-type/lib/field/Preview.module.css new file mode 100644 index 0000000..7ce5431 --- /dev/null +++ b/src/database/item-type/lib/field/Preview.module.css @@ -0,0 +1,23 @@ +.previewBox { + text-align: center; + margin: 10px; +} + +.previewBox::after { + content: ""; + display: block; + clear: both; +} + +.preview { + width: 200px; + margin: 0 auto; + float: left; + text-align: center; +} + +.preview caption { + width: 200px; + margin: 5px; + font-size: 80%; +} \ No newline at end of file diff --git a/src/database/item-type/lib/field/Preview.tsx b/src/database/item-type/lib/field/Preview.tsx new file mode 100644 index 0000000..86ec5b3 --- /dev/null +++ b/src/database/item-type/lib/field/Preview.tsx @@ -0,0 +1,84 @@ +import React, { Component } from 'react'; +import Lightbox from 'react-image-lightbox'; +import 'react-image-lightbox/style.css'; +import { MultiLang } from '../../../../config'; +import Functions from '../../../../functions'; +import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil'; +import styles from './Preview.module.css'; + +interface Props { + lang: MultiLang; + file: ItemBasicFile[]; +} + +interface State { + isOpen: boolean; + imageIndex: number; +} + +class Preview extends Component { + + constructor(props: Props) { + super(props); + this.state = { + isOpen: false, + imageIndex: 0, + }; + } + + render() { + const { lang, file } = this.props; + const data = file.filter((value) => { + return value.file_type_name === 'preview'; + }); + if (data.length === 0) { + return null; + } + let imageUrls: string[] = []; + const previews = data.map((value, idx) => { + const fileUrl = ItemUtil.getFileUrl(value); + const previewUrl = ItemUtil.getPreviewFileUrl(value); + const caption = Functions.mlang(value.caption, lang); + imageUrls.push(fileUrl); + return ( +
    + { + e.preventDefault(); + this.setState({ isOpen: true, imageIndex: idx }); + }}> + {caption} + +
    {caption}
    +
    + ); + }); + const { isOpen, imageIndex } = this.state; + return ( + <> +
    + {previews} +
    + {isOpen && + this.setState({ isOpen: false })} + onMovePrevRequest={() => + this.setState({ + imageIndex: (imageIndex + data.length - 1) % data.length, + }) + } + onMoveNextRequest={() => + this.setState({ + imageIndex: (imageIndex + 1) % data.length, + }) + } + /> + } + + ); + } +} + +export default Preview; \ No newline at end of file diff --git a/src/database/item-type/lib/field/PublicationDate.tsx b/src/database/item-type/lib/field/PublicationDate.tsx new file mode 100644 index 0000000..6da3a62 --- /dev/null +++ b/src/database/item-type/lib/field/PublicationDate.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import DateTime from './DateTime'; + +interface Props { + lang: MultiLang; + year: number; + month: number; + mday: number; +} + +const PublicationDate = (props: Props) => { + const { lang, year, month, mday } = props; + const d = new Date(year + '-' + month + '-' + mday); + const timestamp = Math.floor(d.valueOf() / 1000); + return ; +} + +export default PublicationDate; \ No newline at end of file diff --git a/src/database/item-type/lib/field/Readme.tsx b/src/database/item-type/lib/field/Readme.tsx new file mode 100644 index 0000000..6fbd19b --- /dev/null +++ b/src/database/item-type/lib/field/Readme.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import Description from './Description'; + +interface Props { + lang: MultiLang; + readme: string; +} + +const Readme = (props: Props) => { + const { lang, readme } = props; + return ; +} + +export default Readme; \ No newline at end of file diff --git a/src/database/item-type/lib/field/RelatedTo.tsx b/src/database/item-type/lib/field/RelatedTo.tsx new file mode 100644 index 0000000..87cd518 --- /dev/null +++ b/src/database/item-type/lib/field/RelatedTo.tsx @@ -0,0 +1,74 @@ +import React, { Component } from 'react'; +import { MultiLang } from '../../../../config'; +import ItemType from '../../../item-type'; +import ItemUtil from '../../../lib/ItemUtil'; + +interface Props { + lang: MultiLang + relatedTo: number[]; +} + +interface State { + elements: JSX.Element[]; +} + +class RelatedTo extends Component { + + private isActive: boolean; + + constructor(props: Props) { + super(props); + this.state = { + elements: [], + }; + this.isActive = false; + } + + componentDidMount() { + this.isActive = true; + this.updateElements(this.props.relatedTo); + } + + componentDidUpdate(prevProps: Props) { + if (JSON.stringify(this.props.relatedTo) !== JSON.stringify(prevProps.relatedTo)) { + this.updateElements(this.props.relatedTo); + } + } + + componentWillUnmount() { + this.isActive = false; + } + + updateElements(relatedTo: number[]) { + const { lang } = this.props; + if (relatedTo.length === 0) { + this.setState({ elements: [] }); + } else { + ItemUtil.getList(relatedTo, (results) => { + const elements = results.data.map((item, idx) => { + const evenodd = idx % 0 ? 'even' : 'odd'; + return ; + }); + if (this.isActive) { + this.setState({ elements }); + } + }); + } + } + + render() { + if (this.state.elements.length === 0) { + return null; + } + return ( + + + + {this.state.elements} + +
    Item summary
    + ); + } +} + +export default RelatedTo; \ No newline at end of file diff --git a/src/database/item-type/lib/field/Rights.tsx b/src/database/item-type/lib/field/Rights.tsx new file mode 100644 index 0000000..25f65cf --- /dev/null +++ b/src/database/item-type/lib/field/Rights.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import CreativeCommons, { getCreativeCommonsType } from './CreativeCommons'; +import Description from './Description'; + +interface Props { + lang: MultiLang; + rights: string; + useCc: number; + ccCommercialUse: number; + ccModification: number; +} + +const Rights = (props: Props) => { + const { lang, rights, useCc, ccCommercialUse, ccModification } = props; + if (useCc === 0) { + return ; + } + const ccType = getCreativeCommonsType(ccCommercialUse, ccModification); + return ; +} + +export default Rights; \ No newline at end of file diff --git a/src/database/item-type/lib/field/SimPFLinkIcon.tsx b/src/database/item-type/lib/field/SimPFLinkIcon.tsx new file mode 100644 index 0000000..1bfc8cb --- /dev/null +++ b/src/database/item-type/lib/field/SimPFLinkIcon.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { MultiLang } from '../../../../config'; +import imageButton from '../../../assets/images/simpf_button.png'; + +interface Props { + lang: MultiLang; + url: string; + isDetail: boolean; +} + +const SimPFLinkIcon = (props: Props) => { + const { url, isDetail } = props; + const title = 'Online Simulation'; + const size = isDetail ? 64 : 35; + if (url === '') { + return null; + } + return ( + + {title} + + );; +} + +export default SimPFLinkIcon; diff --git a/src/database/item-type/lib/field/index.tsx b/src/database/item-type/lib/field/index.tsx new file mode 100644 index 0000000..12e70e6 --- /dev/null +++ b/src/database/item-type/lib/field/index.tsx @@ -0,0 +1,39 @@ +import Author from './Author'; +import ChangeLog from './ChangeLog'; +import Contributer from './Contributer'; +import CreativeCommons from './CreativeCommons'; +import DateTime from './DateTime'; +import Description from './Description'; +import FileSize from './FileSize'; +import FileDownloadButton from './FileDownloadButton'; +import FreeKeyword from './FreeKeyword'; +import ItemFile from './ItemFile'; +import ItemIndex from './ItemIndex'; +import Language from './Language'; +import Preview from './Preview'; +import PublicationDate from './PublicationDate'; +import Readme from './Readme'; +import RelatedTo from './RelatedTo'; +import Rights from './Rights'; + +const ItemTypeField = { + Author, + ChangeLog, + Contributer, + CreativeCommons, + DateTime, + Description, + FileDownloadButton, + FileSize, + FreeKeyword, + ItemFile, + ItemIndex, + Language, + Preview, + PublicationDate, + Readme, + RelatedTo, + Rights, +}; + +export default ItemTypeField; \ No newline at end of file diff --git a/src/database/item-type/memo/MemoAdvancedSearch.tsx b/src/database/item-type/memo/MemoAdvancedSearch.tsx new file mode 100644 index 0000000..9438658 --- /dev/null +++ b/src/database/item-type/memo/MemoAdvancedSearch.tsx @@ -0,0 +1,28 @@ +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class MemoAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'memo'; + this.title = 'Memo'; + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['item_link'] = ''; + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Item Link[/en][ja]リンク[/ja]', value: this.renderFieldInputText('item_link', 50) }, + ]; + return rows; + } +} + +export default MemoAdvancedSearch; diff --git a/src/database/item-type/memo/MemoDetail.tsx b/src/database/item-type/memo/MemoDetail.tsx new file mode 100644 index 0000000..100441d --- /dev/null +++ b/src/database/item-type/memo/MemoDetail.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import XoopsCode from '../../../common/lib/XoopsCode'; +import Functions from '../../../functions'; +import { ItemMemo } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; + +class MemoDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemMemo; + const fields = [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Item Link[/en][ja]リンク[/ja]', value: }, + { label: '[en]Memo File[/en][ja]メモファイル[/ja]', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + return fields; + } +} + +export default MemoDetail; diff --git a/src/database/item-type/memo/MemoList.tsx b/src/database/item-type/memo/MemoList.tsx new file mode 100644 index 0000000..1fbd2cd --- /dev/null +++ b/src/database/item-type/memo/MemoList.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import XoopsCode from '../../../common/lib/XoopsCode'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_memo.gif'; +import { ItemMemo } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class MemoList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Memo'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemMemo; + const link = item.item_link !== '' ? : null; + return ( + <> + {Functions.mlang(item.title, lang)}
    + {link} + + ); + } +} + +export default MemoList; diff --git a/src/database/item-type/memo/MemoTop.tsx b/src/database/item-type/memo/MemoTop.tsx new file mode 100644 index 0000000..8245f96 --- /dev/null +++ b/src/database/item-type/memo/MemoTop.tsx @@ -0,0 +1,15 @@ +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_memo.gif'; + +class MemoTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'memo'; + this.label = 'Memo'; + this.icon = iconFile; + this.description = '[en]Personal Memo Pad.[/en][ja]汎用メモパッド[/ja]'; + } +} + +export default MemoTop; diff --git a/src/database/item-type/memo/index.tsx b/src/database/item-type/memo/index.tsx new file mode 100644 index 0000000..d5d2951 --- /dev/null +++ b/src/database/item-type/memo/index.tsx @@ -0,0 +1,13 @@ +import MemoTop from './MemoTop'; +import MemoList from './MemoList'; +import MemoDetail from './MemoDetail'; +import MemoAdvancedSearch from './MemoAdvancedSearch'; + +const ItemTypeMemo = { + Top: MemoTop, + List: MemoList, + Detail: MemoDetail, + AdvancedSearch: MemoAdvancedSearch, +}; + +export default ItemTypeMemo; \ No newline at end of file diff --git a/src/database/item-type/model/ModelAdvancedSearch.tsx b/src/database/item-type/model/ModelAdvancedSearch.tsx new file mode 100644 index 0000000..02cfd40 --- /dev/null +++ b/src/database/item-type/model/ModelAdvancedSearch.tsx @@ -0,0 +1,35 @@ +import { ItemModelSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class ModelAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'model'; + this.title = 'Model'; + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['model_type'] = ''; + this.state.values['creator'] = ''; + this.state.values['file.preview.caption'] = ''; + this.state.values['file.model_data.original_file_name'] = ''; + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Model Type[/en][ja]モデルタイプ[/ja]', value: this.renderFieldSelect('model_type', ItemModelSubTypes) }, + { label: '[en]Creator[/en][ja]作成者[/ja]', value: this.renderFieldInputText('creator', 50) }, + { label: '[en]Caption[/en][ja]キャプション[/ja]', value: this.renderFieldInputText('file.preview.caption', 50) }, + { label: '[en]Model File[/en][ja]モデルファイル[/ja]', value: this.renderFieldInputText('file.model_data.original_file_name', 50) }, + ]; + return rows; + } +} + +export default ModelAdvancedSearch; \ No newline at end of file diff --git a/src/database/item-type/model/ModelDetail.tsx b/src/database/item-type/model/ModelDetail.tsx new file mode 100644 index 0000000..837b712 --- /dev/null +++ b/src/database/item-type/model/ModelDetail.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import Functions from '../../../functions'; +import ItemUtil, { ItemModel } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import SimPFLinkIcon from '../lib/field/SimPFLinkIcon'; +import ModelUtil from './ModelUtil'; + +class ModelDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemModel; + const fields = [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Model Type[/en][ja]モデルタイプ[/ja]', value: }, + { label: '[en]Creator[/en][ja]作成者[/ja]', value: }, + { label: '[en]Preview[/en][ja]プレビュー[/ja]', value: }, + { label: '[en]Model File[/en][ja]モデルファイル[/ja]', value: }, + { label: 'Readme', value: }, + { label: 'Rights', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id); + if (simpfLinkUrl !== '') { + const field = { label: 'Online Simulation', value: }; + fields.splice(13, 0, field); + } + return fields; + } +} + +export default ModelDetail; \ No newline at end of file diff --git a/src/database/item-type/model/ModelList.tsx b/src/database/item-type/model/ModelList.tsx new file mode 100644 index 0000000..b709fa2 --- /dev/null +++ b/src/database/item-type/model/ModelList.tsx @@ -0,0 +1,31 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_model.gif'; +import { ItemModel } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class ModelList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Model'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemModel; + const authors = item.creator.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {authors} + + ); + } +} + +export default ModelList; \ No newline at end of file diff --git a/src/database/item-type/model/ModelTop.tsx b/src/database/item-type/model/ModelTop.tsx new file mode 100644 index 0000000..e5431f2 --- /dev/null +++ b/src/database/item-type/model/ModelTop.tsx @@ -0,0 +1,19 @@ +import { ItemModelSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_model.gif'; + +class ModelTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'model'; + this.label = 'Model'; + this.icon = iconFile; + // DBPF: + //this.description = '[en]Model programs/scripts.[/en][ja]モデル プログラム/スクリプト[/ja]'; + this.description = '[en]Descriptions of models[/en][ja]モデルの記述[/ja]'; + this.subTypes = ItemModelSubTypes; + } +} + +export default ModelTop; \ No newline at end of file diff --git a/src/database/item-type/model/ModelUtil.tsx b/src/database/item-type/model/ModelUtil.tsx new file mode 100644 index 0000000..43a0c89 --- /dev/null +++ b/src/database/item-type/model/ModelUtil.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemModelSubType, ItemModelSubTypes } from '../../lib/ItemUtil'; + +interface ModelTypeProps { + lang: MultiLang; + type: ItemModelSubType; +} + +const ModelType = (props: ModelTypeProps) => { + const { type } = props; + const subtype = ItemModelSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +const ModelUtil = { + ModelType, +} + +export default ModelUtil; \ No newline at end of file diff --git a/src/database/item-type/model/index.tsx b/src/database/item-type/model/index.tsx new file mode 100644 index 0000000..dba8611 --- /dev/null +++ b/src/database/item-type/model/index.tsx @@ -0,0 +1,13 @@ +import ModelTop from './ModelTop'; +import ModelList from './ModelList'; +import ModelDetail from './ModelDetail'; +import ModelAdvancedSearch from './ModelAdvancedSearch'; + +const ItemTypeModel = { + Top: ModelTop, + List: ModelList, + Detail: ModelDetail, + AdvancedSearch: ModelAdvancedSearch, +}; + +export default ItemTypeModel; \ No newline at end of file diff --git a/src/database/item-type/paper/PaperAdvancedSearch.tsx b/src/database/item-type/paper/PaperAdvancedSearch.tsx new file mode 100644 index 0000000..a74e2d4 --- /dev/null +++ b/src/database/item-type/paper/PaperAdvancedSearch.tsx @@ -0,0 +1,39 @@ +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class PaperAdvancedSearch extends AdvancedSearchBase { + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'paper'; + this.title = 'Paper'; + this.state.values['pubmed_id'] = ''; + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['author'] = ''; + this.state.values['journal'] = ''; + this.state.values['publication_year'] = ''; + this.state.values['volume'] = ''; + this.state.values['number'] = ''; + this.state.values['page'] = ''; + } + + getRows() { + const rows = [ + { label: 'PubMed ID', value: this.renderFieldInputText('pubmed_id', 50) }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Author[/en][ja]著者[/ja]', value: this.renderFieldInputText('author', 50) }, + { label: '[en]Journal[/en][ja]ジャーナル[/ja]', value: this.renderFieldInputText('journal', 50) }, + { label: '[en]Publication Year[/en][ja]出版年[/ja]', value: this.renderFieldInputText('publication_year', 10) }, + { label: '[en]Volume[/en][ja]巻[/ja]', value: this.renderFieldInputText('volume', 50) }, + { label: '[en]Number[/en][ja]号[/ja]', value: this.renderFieldInputText('number', 50) }, + { label: '[en]Page[/en][ja]ページ[/ja]', value: this.renderFieldInputText('page', 50) }, + ]; + return rows; + } +} + +export default PaperAdvancedSearch; \ No newline at end of file diff --git a/src/database/item-type/paper/PaperDetail.tsx b/src/database/item-type/paper/PaperDetail.tsx new file mode 100644 index 0000000..5884fbe --- /dev/null +++ b/src/database/item-type/paper/PaperDetail.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import Functions from '../../../functions'; +import { ItemPaper } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import PaperUtil from './PaperUtil'; + +class PaperDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemPaper; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: 'PubMed ID', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Author[/en][ja]著者[/ja]', value: }, + { label: '[en]Journal[/en][ja]ジャーナル[/ja]', value: Functions.mlang(item.journal, lang) }, + { label: '[en]Publication Year[/en][ja]出版年[/ja]', value: item.publication_year }, + { label: '[en]Volume[/en][ja]巻[/ja]', value: item.volume }, + { label: '[en]Number[/en][ja]号[/ja]', value: item.number }, + { label: '[en]Page[/en][ja]ページ[/ja]', value: item.page }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + } +} + +export default PaperDetail; \ No newline at end of file diff --git a/src/database/item-type/paper/PaperList.tsx b/src/database/item-type/paper/PaperList.tsx new file mode 100644 index 0000000..673d6d3 --- /dev/null +++ b/src/database/item-type/paper/PaperList.tsx @@ -0,0 +1,38 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_paper.gif'; +import { ItemPaper } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; +import PaperUtil from './PaperUtil'; + +class PaperList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Paper'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemPaper; + const authors = item.author.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {authors}
    + {Functions.mlang(item.journal, lang)} + {item.publication_year} + {item.volume !== null && ' ;' + item.volume} + {item.number !== null && ' (' + item.number + ')'} + {item.page !== '' && ' :' + item.page} + {item.pubmed_id !== '' && <> [PMID:]} + + ); + } +} + +export default PaperList; \ No newline at end of file diff --git a/src/database/item-type/paper/PaperTop.tsx b/src/database/item-type/paper/PaperTop.tsx new file mode 100644 index 0000000..2d6ea43 --- /dev/null +++ b/src/database/item-type/paper/PaperTop.tsx @@ -0,0 +1,15 @@ +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_paper.gif'; + +class PaperTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'paper'; + this.label = 'Paper'; + this.icon = iconFile; + this.description = '[en]Related paper collection.[/en][ja]関連論文[/ja]'; + } +} + +export default PaperTop; \ No newline at end of file diff --git a/src/database/item-type/paper/PaperUtil.tsx b/src/database/item-type/paper/PaperUtil.tsx new file mode 100644 index 0000000..419b6a6 --- /dev/null +++ b/src/database/item-type/paper/PaperUtil.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; + +interface PubmedLinkProps { + lang: MultiLang; + pubmedId: string; +} + +const PubmedLink = (props: PubmedLinkProps) => { + const { pubmedId } = props; + if (pubmedId === '') { + return null; + } + const url = 'https://www.ncbi.nlm.nih.gov/pubmed/' + pubmedId; + return ({pubmedId}); +} + +const PaperUtil = { + PubmedLink, +} + +export default PaperUtil; \ No newline at end of file diff --git a/src/database/item-type/paper/index.tsx b/src/database/item-type/paper/index.tsx new file mode 100644 index 0000000..a781a94 --- /dev/null +++ b/src/database/item-type/paper/index.tsx @@ -0,0 +1,13 @@ +import PaperTop from './PaperTop'; +import PaperList from './PaperList'; +import PaperDetail from './PaperDetail'; +import PaperAdvancedSearch from './PaperAdvancedSearch'; + +const ItemTypePaper = { + Top: PaperTop, + List: PaperList, + Detail: PaperDetail, + AdvancedSearch: PaperAdvancedSearch, +}; + +export default ItemTypePaper; \ No newline at end of file diff --git a/src/database/item-type/presentation/PresentationAdvancedSearch.tsx b/src/database/item-type/presentation/PresentationAdvancedSearch.tsx new file mode 100644 index 0000000..d763def --- /dev/null +++ b/src/database/item-type/presentation/PresentationAdvancedSearch.tsx @@ -0,0 +1,46 @@ +import { ItemPresentationSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class PresentationAdvancedSearch extends AdvancedSearchBase { + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'presentation'; + this.title = 'Presentation'; + const now = new Date(); + const year = String(now.getFullYear()); + const month = String(now.getMonth() + 1); + const mday = String(now.getDate()); + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['meeting_name'] = ''; + this.state.values['presentation_type'] = ''; + this.state.values['creator'] = ''; + this.state.values['publication_year'] = year; + this.state.values['publication_month'] = month; + this.state.values['publication_mday'] = mday; + this.state.values['file.preview.caption'] = ''; + this.state.values['file.presentation_file.original_file_name'] = ''; + this.setIgnoreKey('publication_year'); + this.setIgnoreKey('publication_month'); + this.setIgnoreKey('publication_mday'); + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Presentation Type[/en][ja]ファイル形式[/ja]', value: this.renderFieldSelect('presentation_type', ItemPresentationSubTypes) }, + { label: '[en]Creator[/en][ja]作成者[/ja]', value: this.renderFieldInputText('creator', 50) }, + { label: '[en]Date[/en][ja]日付[/ja]', value: this.renderFieldDate('', 'publication_year', 'publication_month', 'publication_mday') }, + { label: '[en]Caption[/en][ja]キャプション[/ja]', value: this.renderFieldInputText('file.preview.caption', 50) }, + { label: '[en]Presentation File[/en][ja]発表資料[/ja]', value: this.renderFieldInputText('file.presentation_file.original_file_name', 50) }, + ]; + return rows; + } +} + +export default PresentationAdvancedSearch; \ No newline at end of file diff --git a/src/database/item-type/presentation/PresentationDetail.tsx b/src/database/item-type/presentation/PresentationDetail.tsx new file mode 100644 index 0000000..2924449 --- /dev/null +++ b/src/database/item-type/presentation/PresentationDetail.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import Functions from '../../../functions'; +import { ItemPresentation } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import PresentationUtil from './PresentationUtil'; + +class PresentationDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemPresentation; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Date[/en][ja]日付[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Presentation Type[/en][ja]ファイル形式[/ja]', value: }, + { label: '[en]Creator[/en][ja]作成者[/ja]', value: }, + { label: '[en]Preview[/en][ja]プレビュー[/ja]', value: }, + { label: '[en]Presentation File[/en][ja]発表資料[/ja]', value: }, + { label: 'Readme', value: }, + { label: 'Rights', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + } +} + +export default PresentationDetail; \ No newline at end of file diff --git a/src/database/item-type/presentation/PresentationList.tsx b/src/database/item-type/presentation/PresentationList.tsx new file mode 100644 index 0000000..a6c8e61 --- /dev/null +++ b/src/database/item-type/presentation/PresentationList.tsx @@ -0,0 +1,33 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_presentation.gif'; +import { ItemPresentation } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; +import PresentationUtil from './PresentationUtil'; + +class PresentationList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Presentation'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemPresentation; + const authors = item.creator.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    +
    + {authors} + + ); + } +} + +export default PresentationList; \ No newline at end of file diff --git a/src/database/item-type/presentation/PresentationTop.tsx b/src/database/item-type/presentation/PresentationTop.tsx new file mode 100644 index 0000000..91a7e89 --- /dev/null +++ b/src/database/item-type/presentation/PresentationTop.tsx @@ -0,0 +1,18 @@ +import iconFile from '../../assets/images/icon_presentation.gif'; +import { ItemPresentationSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; + +class PresentationTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'presentation'; + this.label = 'Presentation'; + this.icon = iconFile; + // DBPF: + this.description = '[en]Presentation files.[/en][ja]プレゼンテーション ファイル[/ja]'; + this.subTypes = ItemPresentationSubTypes; + } +} + +export default PresentationTop; \ No newline at end of file diff --git a/src/database/item-type/presentation/PresentationUtil.tsx b/src/database/item-type/presentation/PresentationUtil.tsx new file mode 100644 index 0000000..e5140bc --- /dev/null +++ b/src/database/item-type/presentation/PresentationUtil.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemPresentationSubType, ItemPresentationSubTypes } from '../../lib/ItemUtil'; + +interface PresentationTypeProps { + lang: MultiLang; + type: ItemPresentationSubType; +} + +const PresentationType = (props: PresentationTypeProps) => { + const { type } = props; + const subtype = ItemPresentationSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +const PresentationUtil = { + PresentationType, +} + +export default PresentationUtil; \ No newline at end of file diff --git a/src/database/item-type/presentation/index.tsx b/src/database/item-type/presentation/index.tsx new file mode 100644 index 0000000..13493a3 --- /dev/null +++ b/src/database/item-type/presentation/index.tsx @@ -0,0 +1,13 @@ +import PresentationTop from './PresentationTop'; +import PresentationList from './PresentationList'; +import PresentationDetail from './PresentationDetail'; +import PresentationAdvancedSearch from './PresentationAdvancedSearch'; + +const ItemTypePresentation = { + Top: PresentationTop, + List: PresentationList, + Detail: PresentationDetail, + AdvancedSearch: PresentationAdvancedSearch, +}; + +export default ItemTypePresentation; \ No newline at end of file diff --git a/src/database/item-type/simulator/SimulatorAdvancedSearch.tsx b/src/database/item-type/simulator/SimulatorAdvancedSearch.tsx new file mode 100644 index 0000000..463681a --- /dev/null +++ b/src/database/item-type/simulator/SimulatorAdvancedSearch.tsx @@ -0,0 +1,44 @@ +import { ItemSimulatorSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class SimulatorAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'simulator'; + this.title = 'Simulator'; + const now = new Date(); + const year = String(now.getFullYear()); + const month = String(now.getMonth() + 1); + const mday = String(now.getDate()); + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['simulator_type'] = ''; + this.state.values['developer'] = ''; + this.state.values['publication_year'] = year; + this.state.values['publication_month'] = month; + this.state.values['publication_mday'] = mday; + this.state.values['file.preview.caption'] = ''; + this.setIgnoreKey('publication_year'); + this.setIgnoreKey('publication_month'); + this.setIgnoreKey('publication_mday'); + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Simulator Type[/en][ja]シミュレータータイプ[/ja]', value: this.renderFieldSelect('simulator_type', ItemSimulatorSubTypes) }, + { label: '[en]Developer[/en][ja]開発者[/ja]', value: this.renderFieldInputText('developer', 50) }, + { label: '[en]Date[/en][ja]日付[/ja]', value: this.renderFieldDate('', 'publication_year', 'publication_month', 'publication_mday') }, + { label: '[en]Caption[/en][ja]キャプション[/ja]', value: this.renderFieldInputText('file.preview.caption', 50) }, + ]; + return rows; + } +} + +export default SimulatorAdvancedSearch; diff --git a/src/database/item-type/simulator/SimulatorDetail.tsx b/src/database/item-type/simulator/SimulatorDetail.tsx new file mode 100644 index 0000000..d876cb2 --- /dev/null +++ b/src/database/item-type/simulator/SimulatorDetail.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import Functions from '../../../functions'; +import ItemUtil, { ItemSimulator } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import SimPFLinkIcon from '../lib/field/SimPFLinkIcon'; +import SimulatorUtil from './SimulatorUtil'; + +class SimulatorDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemSimulator; + const fields = [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Date[/en][ja]日付[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Simulator Type[/en][ja]シミュレータータイプ[/ja]', value: }, + { label: '[en]Developer[/en][ja]開発者[/ja]', value: }, + { label: '[en]Preview[/en][ja]プレビュー[/ja]', value: }, + { label: '[en]Simulator File[/en][ja]ファイル[/ja]', value: }, + { label: 'Readme', value: }, + { label: 'Rights', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id); + if (simpfLinkUrl !== '') { + const field = { label: 'Online Simulation', value: }; + fields.splice(14, 0, field); + } + return fields; + } +} + +export default SimulatorDetail; \ No newline at end of file diff --git a/src/database/item-type/simulator/SimulatorList.tsx b/src/database/item-type/simulator/SimulatorList.tsx new file mode 100644 index 0000000..3b91629 --- /dev/null +++ b/src/database/item-type/simulator/SimulatorList.tsx @@ -0,0 +1,31 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_simulator.gif'; +import { ItemSimulator } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class SimulatorList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Simulator'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemSimulator; + const authors = item.developer.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {authors} + + ); + } +} + +export default SimulatorList; \ No newline at end of file diff --git a/src/database/item-type/simulator/SimulatorTop.tsx b/src/database/item-type/simulator/SimulatorTop.tsx new file mode 100644 index 0000000..af84099 --- /dev/null +++ b/src/database/item-type/simulator/SimulatorTop.tsx @@ -0,0 +1,19 @@ +import { ItemSimulatorSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_simulator.gif'; + +class SimulatorTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'simulator'; + this.label = 'Simulator'; + this.icon = iconFile; + // DBPF: + // this.description = '[en]Programs/scripts for simulation.[/en][ja]シミュレーション用プログラム/スクリプト[/ja]'; + this.description = '[en]Programs for specific simulations.[/en][ja]特定のシミュレーション用プログラム[/ja]'; + this.subTypes = ItemSimulatorSubTypes; + } +} + +export default SimulatorTop; \ No newline at end of file diff --git a/src/database/item-type/simulator/SimulatorUtil.tsx b/src/database/item-type/simulator/SimulatorUtil.tsx new file mode 100644 index 0000000..adc52f5 --- /dev/null +++ b/src/database/item-type/simulator/SimulatorUtil.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemSimulatorSubType, ItemSimulatorSubTypes } from '../../lib/ItemUtil'; + +interface SimulatorTypeProps { + lang: MultiLang; + type: ItemSimulatorSubType; +} + +const SimulatorType = (props: SimulatorTypeProps) => { + const { type } = props; + const subtype = ItemSimulatorSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +const SimulatorUtil = { + SimulatorType, +} + +export default SimulatorUtil; \ No newline at end of file diff --git a/src/database/item-type/simulator/index.tsx b/src/database/item-type/simulator/index.tsx new file mode 100644 index 0000000..06c082d --- /dev/null +++ b/src/database/item-type/simulator/index.tsx @@ -0,0 +1,13 @@ +import SimulatorTop from './SimulatorTop'; +import SimulatorList from './SimulatorList'; +import SimulatorDetail from './SimulatorDetail'; +import SimulatorAdvancedSearch from './SimulatorAdvancedSearch'; + +const ItemTypeSimulator = { + Top: SimulatorTop, + List: SimulatorList, + Detail: SimulatorDetail, + AdvancedSearch: SimulatorAdvancedSearch, +}; + +export default ItemTypeSimulator; \ No newline at end of file diff --git a/src/database/item-type/stimulus/StimulusAdvancedSearch.tsx b/src/database/item-type/stimulus/StimulusAdvancedSearch.tsx new file mode 100644 index 0000000..d2a0bff --- /dev/null +++ b/src/database/item-type/stimulus/StimulusAdvancedSearch.tsx @@ -0,0 +1,44 @@ +import { ItemStimulusSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class StimulusAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'stimulus'; + this.title = 'Stimulus'; + const now = new Date(); + const year = String(now.getFullYear()); + const month = String(now.getMonth() + 1); + const mday = String(now.getDate()); + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['stimulus_type'] = ''; + this.state.values['developer'] = ''; + this.state.values['publication_year'] = year; + this.state.values['publication_month'] = month; + this.state.values['publication_mday'] = mday; + this.state.values['file.preview.caption'] = ''; + this.setIgnoreKey('publication_year'); + this.setIgnoreKey('publication_month'); + this.setIgnoreKey('publication_mday'); + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Stimulus Type[/en][ja]刺激タイプ[/ja]', value: this.renderFieldSelect('stimulus_type', ItemStimulusSubTypes) }, + { label: '[en]Developer[/en][ja]開発者[/ja]', value: this.renderFieldInputText('developer', 50) }, + { label: '[en]Date[/en][ja]日付[/ja]', value: this.renderFieldDate('', 'publication_year', 'publication_month', 'publication_mday') }, + { label: '[en]Caption[/en][ja]キャプション[/ja]', value: this.renderFieldInputText('file.preview.caption', 50) }, + ]; + return rows; + } +} + +export default StimulusAdvancedSearch; diff --git a/src/database/item-type/stimulus/StimulusDetail.tsx b/src/database/item-type/stimulus/StimulusDetail.tsx new file mode 100644 index 0000000..2f16ad4 --- /dev/null +++ b/src/database/item-type/stimulus/StimulusDetail.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import Functions from '../../../functions'; +import ItemUtil, { ItemStimulus } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import SimPFLinkIcon from '../lib/field/SimPFLinkIcon'; +import StimulusUtil from './StimulusUtil'; + +class StimulusDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemStimulus; + const fields = [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Date[/en][ja]日付[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Stimulus Type[/en][ja]刺激タイプ[/ja]', value: }, + { label: '[en]Developer[/en][ja]開発者[/ja]', value: }, + { label: '[en]Preview[/en][ja]プレビュー[/ja]', value: }, + { label: '[en]Stimulus File[/en][ja]ファイル[/ja]', value: }, + { label: 'Readme', value: }, + { label: 'Rights', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id); + if (simpfLinkUrl !== '') { + const field = { label: 'Online Simulation', value: }; + fields.splice(14, 0, field); + } + return fields; + } +} + +export default StimulusDetail; diff --git a/src/database/item-type/stimulus/StimulusList.tsx b/src/database/item-type/stimulus/StimulusList.tsx new file mode 100644 index 0000000..baae6b7 --- /dev/null +++ b/src/database/item-type/stimulus/StimulusList.tsx @@ -0,0 +1,31 @@ +import React, { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_stimulus.gif'; +import { ItemStimulus } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class StimulusList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Stimulus'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemStimulus; + const authors = item.developer.map((author, i) => { + return {i > 0 && ', '}{Functions.mlang(author, lang)} + }); + return ( + <> + {Functions.mlang(item.title, lang)}
    + {authors} + + ); + } +} + +export default StimulusList; \ No newline at end of file diff --git a/src/database/item-type/stimulus/StimulusTop.tsx b/src/database/item-type/stimulus/StimulusTop.tsx new file mode 100644 index 0000000..84be35d --- /dev/null +++ b/src/database/item-type/stimulus/StimulusTop.tsx @@ -0,0 +1,19 @@ +import { ItemStimulusSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_stimulus.gif'; + +class StimulusTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'stimulus'; + this.label = 'Stimulus'; + this.icon = iconFile; + // DBPF: + // this.description = '[en]Picture, movie and program files for experimental stimuli.[/en][ja]実験用刺激プログラム/スクリプト[/ja]'; + this.description = '[en]Experimental stimuli.[/en][ja]実験用刺激[/ja]'; + this.subTypes = ItemStimulusSubTypes; + } +} + +export default StimulusTop; \ No newline at end of file diff --git a/src/database/item-type/stimulus/StimulusUtil.tsx b/src/database/item-type/stimulus/StimulusUtil.tsx new file mode 100644 index 0000000..3a0f8c8 --- /dev/null +++ b/src/database/item-type/stimulus/StimulusUtil.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemStimulusSubType, ItemStimulusSubTypes } from '../../lib/ItemUtil'; + +interface StimulusTypeProps { + lang: MultiLang; + type: ItemStimulusSubType; +} + +const StimulusType = (props: StimulusTypeProps) => { + const { type } = props; + const subtype = ItemStimulusSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +const StimulusUtil = { + StimulusType, +} + +export default StimulusUtil; \ No newline at end of file diff --git a/src/database/item-type/stimulus/index.tsx b/src/database/item-type/stimulus/index.tsx new file mode 100644 index 0000000..b01ff6c --- /dev/null +++ b/src/database/item-type/stimulus/index.tsx @@ -0,0 +1,13 @@ +import StimulusTop from './StimulusTop'; +import StimulusList from './StimulusList'; +import StimulusDetail from './StimulusDetail'; +import StimulusAdvancedSearch from './StimulusAdvancedSearch'; + +const ItemTypeStimulus = { + Top: StimulusTop, + List: StimulusList, + Detail: StimulusDetail, + AdvancedSearch: StimulusAdvancedSearch, +}; + +export default ItemTypeStimulus; \ No newline at end of file diff --git a/src/database/item-type/tool/ToolAdvancedSearch.tsx b/src/database/item-type/tool/ToolAdvancedSearch.tsx new file mode 100644 index 0000000..6c9a8d3 --- /dev/null +++ b/src/database/item-type/tool/ToolAdvancedSearch.tsx @@ -0,0 +1,46 @@ +import { ItemToolSubTypes } from '../../lib/ItemUtil'; +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class ToolAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'tool'; + this.title = 'Tool'; + const now = new Date(); + const year = String(now.getFullYear()); + const month = String(now.getMonth() + 1); + const mday = String(now.getDate()); + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['tool_type'] = ''; + this.state.values['developer'] = ''; + this.state.values['publication_year'] = year; + this.state.values['publication_month'] = month; + this.state.values['publication_mday'] = mday; + this.state.values['file.preview.caption'] = ''; + this.state.values['file.tool_data.original_file_name'] = ''; + this.setIgnoreKey('publication_year'); + this.setIgnoreKey('publication_month'); + this.setIgnoreKey('publication_mday'); + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: '[en]Tool Type[/en][ja]ファイルタイプ[/ja]', value: this.renderFieldSelect('tool_type', ItemToolSubTypes) }, + { label: '[en]Developer[/en][ja]開発者[/ja]', value: this.renderFieldInputText('developer', 50) }, + { label: '[en]Date[/en][ja]日付[/ja]', value: this.renderFieldDate('', 'publication_year', 'publication_month', 'publication_mday') }, + { label: '[en]Caption[/en][ja]キャプション[/ja]', value: this.renderFieldInputText('file.preview.caption', 50) }, + { label: '[en]Tool File[/en][ja]ファイル[/ja]', value: this.renderFieldInputText('file.tool_data.original_file_name', 50) }, + ]; + return rows; + } +} + +export default ToolAdvancedSearch; diff --git a/src/database/item-type/tool/ToolDetail.tsx b/src/database/item-type/tool/ToolDetail.tsx new file mode 100644 index 0000000..aa30c02 --- /dev/null +++ b/src/database/item-type/tool/ToolDetail.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import Functions from '../../../functions'; +import ItemUtil, { ItemTool } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import SimPFLinkIcon from '../lib/field/SimPFLinkIcon'; +import ToolUtil from './ToolUtil'; + +class ToolDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemTool; + const fields = [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: '[en]Tool Type[/en][ja]ファイルタイプ[/ja]', value: }, + { label: '[en]Developer[/en][ja]開発者[/ja]', value: }, + { label: '[en]Preview[/en][ja]プレビュー[/ja]', value: }, + { label: '[en]Tool File[/en][ja]ファイル[/ja]', value: }, + { label: 'Readme', value: }, + { label: 'Rights', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id); + if (simpfLinkUrl !== '') { + const field = { label: 'Online Simulation', value: }; + fields.splice(13, 0, field); + } + return fields; + } +} + +export default ToolDetail; \ No newline at end of file diff --git a/src/database/item-type/tool/ToolList.tsx b/src/database/item-type/tool/ToolList.tsx new file mode 100644 index 0000000..27ee027 --- /dev/null +++ b/src/database/item-type/tool/ToolList.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_tool.gif'; +import { ItemTool } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; +import ToolUtil from './ToolUtil'; + +class ToolList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Tool'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemTool; + return ( + <> + {Functions.mlang(item.title, lang)}
    + + + ); + } +} + +export default ToolList; \ No newline at end of file diff --git a/src/database/item-type/tool/ToolTop.tsx b/src/database/item-type/tool/ToolTop.tsx new file mode 100644 index 0000000..1ef6290 --- /dev/null +++ b/src/database/item-type/tool/ToolTop.tsx @@ -0,0 +1,19 @@ +import { ItemToolSubTypes } from '../../lib/ItemUtil'; +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_tool.gif'; + +class ToolTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'tool'; + this.label = 'Tool'; + this.icon = iconFile; + // DBPF: + // this.description = '[en]Tool programs/scripts.[/en][ja]データ解析用プログラム/スクリプト[/ja]'; + this.description = '[en]Tools for non-specific models or data.[/en][ja]特定のモデルやデータに限定しない汎用ツール[/ja]'; + this.subTypes = ItemToolSubTypes; + } +} + +export default ToolTop; \ No newline at end of file diff --git a/src/database/item-type/tool/ToolUtil.tsx b/src/database/item-type/tool/ToolUtil.tsx new file mode 100644 index 0000000..3b3864c --- /dev/null +++ b/src/database/item-type/tool/ToolUtil.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import { ItemToolSubType, ItemToolSubTypes } from '../../lib/ItemUtil'; + +interface ToolTypeProps { + lang: MultiLang; + type: ItemToolSubType; +} + +const ToolType = (props: ToolTypeProps) => { + const { type } = props; + const subtype = ItemToolSubTypes.find((value) => { return value.type === type; }); + if (typeof subtype === 'undefined') { + return null; + } + return ({subtype.label}); +} + +const ToolUtil = { + ToolType, +} + +export default ToolUtil; \ No newline at end of file diff --git a/src/database/item-type/tool/index.tsx b/src/database/item-type/tool/index.tsx new file mode 100644 index 0000000..23a334c --- /dev/null +++ b/src/database/item-type/tool/index.tsx @@ -0,0 +1,13 @@ +import ToolTop from './ToolTop'; +import ToolList from './ToolList'; +import ToolDetail from './ToolDetail'; +import ToolAdvancedSearch from './ToolAdvancedSearch'; + +const ItemTypeTool = { + Top: ToolTop, + List: ToolList, + Detail: ToolDetail, + AdvancedSearch: ToolAdvancedSearch, +}; + +export default ItemTypeTool; \ No newline at end of file diff --git a/src/database/item-type/url/UrlAdvancedSearch.tsx b/src/database/item-type/url/UrlAdvancedSearch.tsx new file mode 100644 index 0000000..2062516 --- /dev/null +++ b/src/database/item-type/url/UrlAdvancedSearch.tsx @@ -0,0 +1,28 @@ +import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase'; + +class UrlAdvancedSearch extends AdvancedSearchBase { + + constructor(props: AdvancedSearchBaseProps) { + super(props); + this.type = 'url'; + this.title = 'Url'; + this.state.values['title'] = ''; + this.state.values['keyword'] = ''; + this.state.values['description'] = ''; + this.state.values['doi'] = ''; + this.state.values['url'] = ''; + } + + getRows() { + const rows = [ + { label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: this.renderFieldInputText('keyword', 50) }, + { label: '[en]Description[/en][ja]概要[/ja]', value: this.renderFieldInputText('description', 50) }, + { label: 'ID', value: this.renderFieldInputText('doi', 50) }, + { label: 'URL', value: this.renderFieldInputText('url', 50) }, + ]; + return rows; + } +} + +export default UrlAdvancedSearch; diff --git a/src/database/item-type/url/UrlDetail.tsx b/src/database/item-type/url/UrlDetail.tsx new file mode 100644 index 0000000..7637fc6 --- /dev/null +++ b/src/database/item-type/url/UrlDetail.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import Functions from '../../../functions'; +import { ItemUrl } from '../../lib/ItemUtil'; +import DetailBase from '../lib/DetailBase'; +import ItemTypeField from '../lib/field'; +import UrlUtil from './UrlUtil'; + +class UrlDetail extends DetailBase { + + getFields() { + const { lang } = this.props; + const item = this.props.item as ItemUrl; + return [ + { label: 'ID', value: item.doi }, + { label: '[en]Language[/en][ja]言語[/ja]', value: }, + { label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) }, + { label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]', value: }, + { label: '[en]Description[/en][ja]概要[/ja]', value: }, + { label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]', value: }, + { label: '[en]Created Date[/en][ja]作成日[/ja]', value: }, + { label: '[en]Contributor[/en][ja]登録者[/ja]', value: }, + { label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name }, + { label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]', value: }, + { label: 'URL', value: {item.url} }, + { label: '[en]Banner File[/en][ja]バナー[/ja]', value: }, + { label: 'Index', value: }, + { label: '[en]Related to[/en][ja]関連アイテム[/ja]', value: }, + ]; + } +} + +export default UrlDetail; \ No newline at end of file diff --git a/src/database/item-type/url/UrlList.tsx b/src/database/item-type/url/UrlList.tsx new file mode 100644 index 0000000..16905b1 --- /dev/null +++ b/src/database/item-type/url/UrlList.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import Functions from '../../../functions'; +import iconFile from '../../assets/images/icon_url.gif'; +import { ItemUrl } from '../../lib/ItemUtil'; +import ListBase, { ListBaseProps } from '../lib/ListBase'; + +class UrlList extends ListBase { + + constructor(props: ListBaseProps) { + super(props); + this.label = 'Url'; + this.icon = iconFile; + } + + renderBody() { + const { lang } = this.props; + const item = this.props.item as ItemUrl; + return ( + <> + {Functions.mlang(item.title, lang)}
    + Link to {item.url} + + ); + } +} + +export default UrlList; \ No newline at end of file diff --git a/src/database/item-type/url/UrlTop.tsx b/src/database/item-type/url/UrlTop.tsx new file mode 100644 index 0000000..a811323 --- /dev/null +++ b/src/database/item-type/url/UrlTop.tsx @@ -0,0 +1,17 @@ +import TopBase, { TopBaseProps } from '../lib/TopBase'; +import iconFile from '../../assets/images/icon_url.gif'; + +class UrlTop extends TopBase { + + constructor(props: TopBaseProps) { + super(props); + this.type = 'url'; + this.label = 'Url'; + this.icon = iconFile; + // DBPF: + // this.description = '[en]Link information.[/en][ja]関連リンク[/ja]'; + this.description = '[en]Related web pages.[/en][ja]関連Webページ[/ja]'; + } +} + +export default UrlTop; \ No newline at end of file diff --git a/src/database/item-type/url/UrlUtil.tsx b/src/database/item-type/url/UrlUtil.tsx new file mode 100644 index 0000000..1dbbfd2 --- /dev/null +++ b/src/database/item-type/url/UrlUtil.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { MultiLang } from '../../../config'; +import ItemUtil, { ItemBasicFile } from '../../lib/ItemUtil'; + +interface BannerFileProps { + lang: MultiLang; + file: ItemBasicFile[]; +} + +const BannerFile = (props: BannerFileProps) => { + const { file } = props; + const data = file.find((value) => { + return value.file_type_name === 'url_banner_file'; + }); + if (typeof data === 'undefined') { + return null; + } + const url = ItemUtil.getFileUrl(data); + return ( + banner + ); +} + +const UrlUtil = { + BannerFile, +} + +export default UrlUtil; diff --git a/src/database/item-type/url/index.tsx b/src/database/item-type/url/index.tsx new file mode 100644 index 0000000..b359df2 --- /dev/null +++ b/src/database/item-type/url/index.tsx @@ -0,0 +1,13 @@ +import UrlTop from './UrlTop'; +import UrlList from './UrlList'; +import UrlDetail from './UrlDetail'; +import UrlAdvancedSearch from './UrlAdvancedSearch'; + +const ItemTypeUrl = { + Top: UrlTop, + List: UrlList, + Detail: UrlDetail, + AdvancedSearch: UrlAdvancedSearch, +}; + +export default ItemTypeUrl; diff --git a/src/database/lib/AdvancedSearchQuery.ts b/src/database/lib/AdvancedSearchQuery.ts new file mode 100644 index 0000000..2b528f8 --- /dev/null +++ b/src/database/lib/AdvancedSearchQuery.ts @@ -0,0 +1,95 @@ +type AdvancedSearchQueryData = Map; + +class AdvancedSearchQuery { + + private dataset: AdvancedSearchQueryData = new Map(); + + empty() { + let ret = true; + this.dataset.forEach((data) => { + data.forEach((value) => { + value = value.trim(); + if (value.length !== 0) { + ret = false; + } + }); + }); + return ret; + } + + set(type: string, key: string, value: string) { + type = type.trim(); + key = key.trim(); + const data: URLSearchParams = this.dataset.has(type) ? this.dataset.get(type) as URLSearchParams : new URLSearchParams(); + data.set(key, value); + this.dataset.set(type, data); + } + + delete(type: string, key: string) { + type = type.trim(); + key = key.trim(); + const data: URLSearchParams = this.dataset.has(type) ? this.dataset.get(type) as URLSearchParams : new URLSearchParams(); + data.delete(key); + this.dataset.set(type, data); + } + + deleteType(type: string) { + type = type.trim(); + this.dataset.delete(type.trim()); + } + + getQueryParams() { + let ret: URLSearchParams = new URLSearchParams(); + this.dataset.forEach((data, type) => { + data.forEach((value, key) => { + value = value.trim(); + value.length > 0 && ret.set(type + '.' + key, value); + }); + }); + return ret; + } + + setByQueryString(queryString: string) { + const query = new URLSearchParams(queryString); + query.forEach((v, k) => { + const [type, ...key] = k.split('.'); + if (typeof key === 'undefined') { + return; + } + this.set(type, key.join('.'), v); + }); + } + + getSearchFilter() { + let filter: any = []; + this.dataset.forEach((data, type) => { + let filter2: any = []; + filter2.push({ + item_type_name: 'xnp' + type, + }); + data.forEach((value, key) => { + const regex = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const file = key.match(/^file\.([^.]+)\.([^.]+)$/); + if (file !== null) { + const fileType = file[1]; + const subKey = file[2]; + // TODO: wait to support $elemMatch operation on lokijs + // - see: https://github.com/techfort/LokiJS/issues/736 + // const filter3: any = { + // file_type_name: fileType, + // [subKey]: { '$regex': regex } + // }; + // filter2.push({ file: { '$elemMatch': filter3 } }); + filter2.push({ 'file.file_type_name': fileType }); + filter2.push({ ['file.' + subKey]: { '$regex': [regex, 'i'] } }); + } else { + filter2.push({ [key]: { '$regex': [regex, 'i'] } }); + } + }); + filter.push({ '$and': filter2 }); + }); + return { '$or': filter }; + } +} + +export default AdvancedSearchQuery; \ No newline at end of file diff --git a/src/database/lib/DatabaseListIndex.tsx b/src/database/lib/DatabaseListIndex.tsx new file mode 100644 index 0000000..de500f7 --- /dev/null +++ b/src/database/lib/DatabaseListIndex.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import IndexUtil, { Index } from './IndexUtil'; +import iconFile from '../assets/images/icon_folder.gif'; +import { MultiLang } from '../../config'; + +interface Props { + lang: MultiLang; + index: Index; +} + +const ListIndexItem = (props: Props) => { + const url = IndexUtil.getUrl(props.index.id); + const numOfIndexes = IndexUtil.countChildren(props.index.id); + return ( + + + + + + + +
    + {props.index.title} + + {props.index.title} +
    + {numOfIndexes} indexes / {props.index.numOfItems} items +
    + ); +} + +const DatabaseListIndex = (props: Props) => { + const { lang } = props; + const children = IndexUtil.getChildren(props.index.id); + if (children.length === 0) { + return null; + } + const treeList = children.map((value: Index, idx) => { + const evenodd = idx % 2 === 0 ? 'even' : 'odd'; + return ( + + + + + + ); + }); + return ( + + + {treeList} + +
    + ); +} + +export default DatabaseListIndex; diff --git a/src/database/lib/DatabaseListItem.module.css b/src/database/lib/DatabaseListItem.module.css new file mode 100644 index 0000000..a2f6d4f --- /dev/null +++ b/src/database/lib/DatabaseListItem.module.css @@ -0,0 +1,11 @@ +.sortCriteria { + text-align: center; +} + +.pageNavi { + text-align: right; +} + +.pageNaviItem { + margin: 0 5px; +} \ No newline at end of file diff --git a/src/database/lib/DatabaseListItem.tsx b/src/database/lib/DatabaseListItem.tsx new file mode 100644 index 0000000..00c7844 --- /dev/null +++ b/src/database/lib/DatabaseListItem.tsx @@ -0,0 +1,241 @@ +import React, { ChangeEvent, Component } from 'react'; +import { RouteComponentProps } from 'react-router'; +import { Link, withRouter } from 'react-router-dom'; +import Loading from '../../common/lib/Loading'; +import { MultiLang } from '../../config'; +import Functions from '../../functions'; +import ItemType from '../item-type'; +import styles from './DatabaseListItem.module.css'; +import { Item, SearchFunc, SearchResult, SortCondition, SortConditionLimit, SortConditionOrderBy, SortConditionOrderDir } from './ItemUtil'; + +const SORT_CONDITION_DEFAULT: SortCondition = { + limit: 20, + page: 1, + orderBy: 'title', + orderDir: 1 +}; +const SORT_CONDITION_RANGE_ORDER_BY = ['title', 'doi', 'last_update_date', 'creation_date', 'publication_date']; +const SORT_CONDITION_RANGE_ORDER_DIR = ['0', '1']; +const SORT_CONDITION_RANGE_LIMIT = ['20', '50', '100']; + +interface Props extends RouteComponentProps { + lang: MultiLang; + url: string; + search: SearchFunc +} + +interface State { + loading: boolean; + condition: SortCondition; + result: SearchResult; +} + +class DatabaseListItem extends Component { + + private isActive = false; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + condition: this.getSortConditionByQuery(this.props.location.search), + result: { total: 0, data: [] } + }; + this.handleSelectOrderby = this.handleSelectOrderby.bind(this); + this.handleSelectItemcount = this.handleSelectItemcount.bind(this); + } + + componentDidMount() { + this.isActive = true; + this.props.search(this.state.condition, (result) => { + if (this.isActive) { + this.setState({ loading: false, result }); + } + }); + } + + componentDidUpdate(prevProps: Props, prevState: State) { + const condition = this.getSortConditionByQuery(this.props.location.search); + if (prevProps.url !== this.props.url || this.isConditionChanged(prevState.condition, condition)) { + this.props.search(condition, (result) => { + if (this.isActive) { + this.setState({ loading: false, result, condition }); + } + }); + } + } + + componentWillUnmount() { + this.isActive = false; + } + + handleSelectOrderby(event: ChangeEvent) { + const value = event.target.value; + const url = this.getListUrl({ orderby: value }); + this.props.history.push(url); + } + + handleSelectItemcount(event: ChangeEvent) { + const value = parseInt(event.target.value, 10); + const url = this.getListUrl({ limit: value }); + this.props.history.push(url); + } + + isConditionChanged(prev: SortCondition, next: SortCondition) { + return prev.limit !== next.limit || prev.orderBy !== next.orderBy || prev.orderDir !== next.orderDir || prev.page !== next.page; + } + + getListUrl(query: { orderby?: string, order_dir?: number, limit?: number, page?: number }) { + const newOrderBy: string = typeof query.orderby !== 'undefined' ? query.orderby : this.state.condition.orderBy; + const newOrderDir: number = typeof query.order_dir !== 'undefined' ? query.order_dir : this.state.condition.orderDir; + const newLimit: number = typeof query.limit !== 'undefined' ? query.limit : this.state.condition.limit; + let newPage: number = typeof query.page !== 'undefined' ? query.page : this.state.condition.page; + if (newLimit !== this.state.condition.limit || newOrderBy !== this.state.condition.orderBy) { + newPage = SORT_CONDITION_DEFAULT.page; + } + const params = new URLSearchParams({ + orderby: newOrderBy, + order_dir: String(newOrderDir), + itemcount: String(newLimit), + page: String(newPage), + }); + const join = this.props.url.indexOf('?') < 0 ? '?' : '&' + return this.props.url + join + params.toString(); + } + + getDefaultSortCondition() { + return Object.assign({}, SORT_CONDITION_DEFAULT); + }; + + getSortConditionByQuery(queryString: string) { + const query = new URLSearchParams(queryString); + const condition = this.getDefaultSortCondition(); + const orderby = query.get('orderby'); + if (orderby !== null && SORT_CONDITION_RANGE_ORDER_BY.includes(orderby)) { + condition.orderBy = orderby as SortConditionOrderBy; + } + const order_dir = query.get('order_dir'); + if (order_dir !== null && SORT_CONDITION_RANGE_ORDER_DIR.includes(order_dir)) { + condition.orderDir = parseInt(order_dir, 10) as SortConditionOrderDir; + } + const itemcount = query.get('itemcount'); + if (itemcount !== null && SORT_CONDITION_RANGE_LIMIT.includes(itemcount)) { + condition.limit = parseInt(itemcount, 10) as SortConditionLimit; + } + const page = query.get('page'); + if (page !== null && page.match(/^\d+$/) !== null) { + condition.page = parseInt(page, 10); + } + return condition; + } + + renderSortCriteria() { + const { lang } = this.props; + let orderDir; + if (this.state.condition.orderDir !== SortConditionOrderDir.ASC) { + const url = this.getListUrl({ order_dir: SortConditionOrderDir.ASC }); + orderDir = ( + ▼ ▲ + ); + } else { + const url = this.getListUrl({ order_dir: SortConditionOrderDir.DESC }); + orderDir = ( + ▼ ▲ + ); + } + return ( +
    + + + + + + + +
    + Order by  + +  {orderDir} + + No.Item per page  + +
    +
    + ); + }; + + renderPageNavi(result: SearchResult) { + const maxPage = Math.floor(result.total / this.state.condition.limit) + (result.total % this.state.condition.limit !== 0 ? 1 : 0); + const link = (title: string, page: number, id: string) => { + if (page === 0 || page === this.state.condition.page) { + return ({title}); + } + const url: string = this.getListUrl({ page: page }); + return ({title}); + } + let startPage = (this.state.condition.page - 4) > 1 ? this.state.condition.page - 4 : 1; + const endPage = (startPage + 9) > maxPage ? maxPage : startPage + 9; + if ((endPage - startPage) < 9) { + startPage = (endPage - 9) > 0 ? endPage - 9 : 1; + } + let pageLinks: JSX.Element[] = []; + pageLinks.push(link('PREV', this.state.condition.page - 1, 'p')); + for (let i = startPage; i <= endPage; i++) { + pageLinks.push(link(String(i), i, String(i))); + } + pageLinks.push(link('NEXT', this.state.condition.page >= maxPage ? 0 : this.state.condition.page + 1, 'n')); + return ( +
    + {pageLinks} +
    + ); + } + + render() { + const { lang } = this.props; + if (this.state.loading) { + return ; + } + const result = this.state.result; + if (result.data.length === 0) { + return ( +

    No items found.

    + ); + } + const startNum = 1 + this.state.condition.limit * (this.state.condition.page - 1); + let endNum = this.state.condition.limit * this.state.condition.page; + if (endNum > result.total) { + endNum = result.total; + } + const pageNavi = this.renderPageNavi(result); + const items = result.data.map((item: Item, idx) => { + const evenodd = idx % 2 === 0 ? 'even' : 'odd'; + return (); + }); + return ( + <> + {this.renderSortCriteria()} +

    {startNum} - {endNum} of {result.total} Items

    + {pageNavi} + + + {items} + +
    + {pageNavi} + + ); + } +} + +export default withRouter(DatabaseListItem); \ No newline at end of file diff --git a/src/database/lib/IndexUtil.ts b/src/database/lib/IndexUtil.ts new file mode 100644 index 0000000..5664ead --- /dev/null +++ b/src/database/lib/IndexUtil.ts @@ -0,0 +1,95 @@ +import loki from 'lokijs'; +import indexesJson from '../assets/tree.json'; + +export interface Index { + id: number; + title: string; + numOfItems: number; + parentId: number; + weight: number; +} + +export const INDEX_ID_ROOT = 1; +export const INDEX_ID_PUBLIC = 3; + +interface IndexData { + id: number; + title: string; + num_of_items: number; + children: IndexData[]; +} +type IndexesData = IndexData[]; + +class IndexUtil { + + private database: loki; + private indexes: Collection; + + constructor(json: IndexesData) { + this.database = new loki('database'); + this.indexes = this.database.addCollection('indexes'); + this.load(json); + } + + load(json: IndexesData): void { + const store = (indexesData: IndexesData, parentId: number) => { + indexesData.forEach((indexData: IndexData, idx) => { + const entry: Index = { + id: indexData.id, + title: indexData.title, + numOfItems: indexData.num_of_items, + parentId: parentId, + weight: idx, + }; + this.indexes.insert(entry); + store(indexData.children, indexData.id) + }); + } + store(json, INDEX_ID_ROOT); + } + + getUrl(id: number): string { + return '/database/list/' + String(id); + } + + get(indexId: number): Index | null { + const filter = { + 'id': indexId, + } + const res = this.indexes.findOne(filter); + return res; + } + + getChildren(indexId: number): Index[] { + const filter = { + 'parentId': indexId, + } + const res = this.indexes.chain().find(filter).simplesort('weight').data(); + return res; + } + + countChildren(indexId: number): number { + const filter = { + 'parentId': indexId, + } + const res = this.indexes.count(filter); + return res; + } + + getParents(parentId: number): Index[] { + let parents: Index[] = []; + const loop = (parentId: number) => { + if (parentId !== INDEX_ID_ROOT) { + const parent = this.get(parentId); + if (parent !== null) { + loop(parent.parentId); + parents.push(parent); + } + } + } + loop(parentId); + return parents; + } +} + +export default new IndexUtil(indexesJson); \ No newline at end of file diff --git a/src/database/lib/ItemUtil.ts b/src/database/lib/ItemUtil.ts new file mode 100644 index 0000000..1ecf8f6 --- /dev/null +++ b/src/database/lib/ItemUtil.ts @@ -0,0 +1,702 @@ +import AsyncLock from 'async-lock'; +import axios from 'axios'; +import loki from 'lokijs'; +import funcs from '../../functions'; +import simpfLinksJson from '../assets/simpf-links.json'; +import AdvancedSearchQuery from './AdvancedSearchQuery'; + +interface SimPFLink { + id: number; + url: string; +} + +interface ItemSubType { + type: T; + label: string; +} + +export type ItemSubTypes = readonly ItemSubType[]; + +export type ItemBasicLang = 'eng' | 'jpn' | 'fra' | 'deu' | 'esl' | 'ita' | 'dut' | 'sve' | 'nor' | 'dan' | 'fin' | 'por' | 'chi' | 'kor'; +export interface ItemBasicIndex { + index_id: number; + title: string; +} +export interface ItemBasicChangeLog { + log_date: number; + log: string; +} +export interface ItemBasicFile { + file_id: number; + original_file_name: string; + mime_type: string; + file_size: number; + caption: string; + timestamp: string; + file_type_name: string; + file_type_display_name: string; +} +export interface ItemCore { + item_id: number; + doi: string; +} +export interface ItemBasic extends ItemCore { + uid: number; + description: string; + last_update_date: number; + creation_date: number; + publication_year: number; + publication_month: number; + publication_mday: number; + lang: ItemBasicLang; + title: string; + item_type_display_name: string; + item_type_name: string; + uname: string; + name: string; + item_url: string; + index: ItemBasicIndex[]; + changelog: ItemBasicChangeLog[]; + related_to: number[]; + keyword: string[]; + file: ItemBasicFile[]; +} + +export interface ItemBinder extends ItemBasic { + extra: string; + item_link: number[]; +} + +export interface ItemBook extends ItemBasic { + classfication: string; + editor: string; + publisher: string; + isbn: string; + url: string; + attachment_dl_limit: number; + attachment_dl_notify: number; + author: string[]; +} + +// DBPF: +// export type ItemConferenceSubType = 'powerpoint' | 'pdf' | 'illustrator' | 'other'; +export type ItemConferenceSubType = 'powerpoint' | 'pdf' | 'other'; +export const ItemConferenceSubTypes: ItemSubTypes = [ + { type: 'powerpoint', label: 'PowerPoint' }, + { type: 'pdf', label: 'PDF' }, + // { type: 'illustrator', label: 'Illustrator' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemConference extends ItemBasic { + presentation_type: ItemConferenceSubType; + conference_title: string; + place: string; + abstract: string; + conference_from_year: number; + conference_from_month: number; + conference_from_mday: number; + conference_to_year: number; + conference_to_month: number; + conference_to_mday: number; + attachment_dl_limit: number; + attachment_dl_notify: number; + author: string[]; +} + +export type ItemDataSubType = 'excel' | 'movie' | 'text' | 'picture' | 'other'; +export const ItemDataSubTypes: ItemSubTypes = [ + { type: 'excel', label: 'Excel' }, + { type: 'movie', label: 'Movie' }, + { type: 'text', label: 'Text' }, + { type: 'picture', label: 'Picture' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemData extends ItemBasic { + data_type: ItemDataSubType; + rights: string; + readme: string; + use_cc: number; + cc_commercial_use: number; + cc_modification: number; + attachment_dl_limit: number; + attachment_dl_notify: number; + experimenter: string[]; +} + +// DBPF: +// export type ItemFilesSubType = 'pdf' | 'doc' | 'xls' | 'ppt' | 'docx' | 'xlsx' | 'pptx' | 'zip' | 'lzh' | 'mov' // CBSN extended +export type ItemFilesSubType = 'pdf' | 'doc' | 'xlsx' | 'pptx' | 'zip' | 'asf' | 'avi' | 'mov' | 'mp4' | 'wmv' | 'jpg'; +export const ItemFilesSubTypes: ItemSubTypes = [ + { type: 'pdf', label: 'pdf' }, + { type: 'doc', label: 'doc' }, + // { type: 'xls', label: 'xls' }, + // { type: 'ppt', label: 'ppt' }, + // { type: 'docx', label: 'docx' }, + { type: 'xlsx', label: 'xlsx' }, + { type: 'pptx', label: 'pptx' }, + { type: 'zip', label: 'zip' }, + // { type: 'lzh', label: 'lzh' }, + { type: 'asf', label: 'asf' }, + { type: 'avi', label: 'avi' }, + { type: 'mov', label: 'mov' }, + { type: 'mp4', label: 'mp4' }, + { type: 'wmv', label: 'wmv' }, + // { type: 'c', label: 'c' }, + // { type: 'txt', label: 'txt' }, + { type: 'jpg', label: 'jpg' }, +]; +export interface ItemFiles extends ItemBasic { + data_file_name: string; + data_file_mimetype: string; + data_file_filetype: string; +} + +export interface ItemMemo extends ItemBasic { + item_link: string; +} + +// DBPF: +// export type ItemModelSubType = 'matlab' | 'neuron' | 'original_program' | 'satellite' | 'genesis' | 'a_cell' | 'other'; +export type ItemModelSubType = 'isml' | 'neuron' | 'genesis' | 'other'; +export const ItemModelSubTypes: ItemSubTypes = [ + // { type: 'matlab', label: 'Matlab' }, + { type: 'isml', label: 'inSilicoML' }, + { type: 'neuron', label: 'Neuron' }, + // { type: 'original_program', label: 'Original Program' }, + // { type: 'satellite', label: 'Satellite' }, + { type: 'genesis', label: 'Genesis' }, + // { type: 'a_cell', label: 'A-Cell' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemModel extends ItemBasic { + model_type: ItemModelSubType; + readme: string; + rights: string; + use_cc: number; + cc_commercial_use: number; + cc_modification: number; + attachment_dl_limit: number; + attachment_dl_notify: number; + creator: string[]; +} + +export interface ItemPaper extends ItemBasic { + journal: string; + volume: number; + number: number | null; + page: string; + abstract: string; + pubmed_id: string; + author: string[]; +} + +// DBPF: +// export type ItemPresentationSubType = 'powerpoint' | 'lotus' | 'justsystem' | 'html' | 'pdf' | 'other'; +export type ItemPresentationSubType = 'powerpoint' | 'pdf' | 'other'; +export const ItemPresentationSubTypes: ItemSubTypes = [ + { type: 'powerpoint', label: 'PowerPoint' }, + // { type: 'lotus', label: 'Lotus' }, + // { type: 'justsystem', label: 'JustSystem' }, + // { type: 'html', label: 'HTML' }, + { type: 'pdf', label: 'PDF' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemPresentation extends ItemBasic { + presentation_type: ItemPresentationSubType; + use_cc: number; + cc_commercial_use: number; + cc_modification: number; + rights: string; + readme: string; + attachment_dl_limit: number; + attachment_dl_notify: number; + creator: string[]; +} + +// DBPF: +// export type ItemSimulatorSubType = 'matlab' | 'mathematica' | 'program' | 'other'; +export type ItemSimulatorSubType = 'matlab' | 'mathematica' | 'other'; +export const ItemSimulatorSubTypes: ItemSubTypes = [ + { type: 'matlab', label: 'Matlab' }, + { type: 'mathematica', label: 'Mathematica' }, + // { type: 'program', label: 'Program' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemSimulator extends ItemBasic { + simulator_type: ItemSimulatorSubType; + readme: string; + rights: string; + use_cc: number; + cc_commercial_use: number; + cc_modification: number; + attachment_dl_limit: number; + attachment_dl_notify: number; + developer: string[]; +} + +// DBPF: +// export type ItemStimulusSubType = 'picture' | 'movie' | 'program' | 'other'; +export type ItemStimulusSubType = 'image' | 'movie' | 'sound' | 'program' | 'other'; +export const ItemStimulusSubTypes: ItemSubTypes = [ + // { type: 'picture', label: 'Picture' }, + { type: 'image', label: 'Image' }, + { type: 'movie', label: 'Movie' }, + { type: 'sound', label: 'Sound' }, + { type: 'program', label: 'Program' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemStimulus extends ItemBasic { + stimulus_type: ItemStimulusSubType; + readme: string; + rights: string; + use_cc: number; + cc_commercial_use: number; + cc_modification: number; + attachment_dl_limit: number; + attachment_dl_notify: number; + developer: string[]; +} + +// DBPF: +// export type ItemToolSubType = 'matlab' | 'mathematica' | 'program' | 'other'; +export type ItemToolSubType = 'matlab' | 'mathematica' | 'other'; +export const ItemToolSubTypes: ItemSubTypes = [ + { type: 'matlab', label: 'Matlab' }, + { type: 'mathematica', label: 'Mathematica' }, + // { type: 'program', label: 'Program' }, + { type: 'other', label: 'Other' }, +]; +export interface ItemTool extends ItemBasic { + tool_type: ItemToolSubType; + readme: string; + rights: string; + use_cc: number; + cc_commercial_use: number; + cc_modification: number; + attachment_dl_limit: number; + attachment_dl_notify: number; + developer: string[]; +} + +export interface ItemUrl extends ItemBasic { + url: string; + url_count: number; +} + +export type Item = ItemBinder | ItemBook | ItemConference | ItemData | ItemFiles | ItemMemo | ItemModel | ItemPaper | ItemPresentation | ItemSimulator | ItemStimulus | ItemTool | ItemUrl; + +export type KeywordSearchType = 'all' | 'basic' | 'binder' | 'book' | 'conference' | 'data' | 'files' | 'memo' | 'model' | 'paper' | 'presentation' | 'simulator' | 'stimulus' | 'tool' | 'url'; +export interface KeywordSearchQuery { + type: KeywordSearchType; + keyword: string; +} +const KEYWORD_SEARCH_TYPE_RANGE = ['all', 'basic', 'binder', 'book', 'conference', 'files', 'data', 'memo', 'model', 'paper', 'presentation', 'simulator', 'stimulus', 'tool', 'url']; + +export type SortConditionLimit = 20 | 50 | 100; +export type SortConditionOrderBy = 'title' | 'doi' | 'last_update_date' | 'creation_date' | 'publication_date'; +export enum SortConditionOrderDir { ASC, DESC } + +export interface SortCondition { + limit: SortConditionLimit; + orderBy: SortConditionOrderBy; + orderDir: SortConditionOrderDir; + page: number; +} + +class ItemSorter { + + public orderBy: SortConditionOrderBy; + public orderDir: SortConditionOrderDir; + + constructor(condition: SortCondition) { + this.orderBy = condition.orderBy; + this.orderDir = condition.orderDir; + this.sort = this.sort.bind(this); + } + + sort(a: Item, b: Item) { + let av: string = ''; + let bv: string = ''; + switch (this.orderBy) { + case 'title': + av = a.title.toLocaleUpperCase(); + bv = b.title.toLocaleUpperCase(); + break; + case 'doi': + av = a.doi.toLocaleUpperCase(); + bv = b.doi.toLocaleUpperCase(); + break; + case 'last_update_date': + av = String(a.last_update_date); + bv = String(b.last_update_date); + break; + case 'creation_date': + av = String(a.creation_date); + bv = String(b.creation_date); + break; + case 'publication_date': + av = String(a.publication_year * 10000 + a.publication_month * 100 + a.publication_mday); + bv = String(b.publication_year * 10000 + b.publication_month * 100 + b.publication_mday); + break; + default: + break; + } + if (this.orderDir === SortConditionOrderDir.ASC) { + if (av > bv) return -1; + else if (av < bv) return 1; + } else { + if (av > bv) return 1; + else if (av < bv) return -1; + } + return 0; + } +} + +type GetResult = Item | null; +export interface GetCallbackFunc { (item: GetResult): void } +export interface SearchResult { + total: number; + data: Item[]; +} +export interface SearchCallbackFunc { (results: SearchResult): void } +export interface SearchFunc { (condition: SortCondition, func: SearchCallbackFunc): void } + +interface ItemLoadCallbackFunc { (items: Collection): void } + +class ItemUtil { + + private database: loki; + private items: Collection; + private simpfLinks: Collection; + private loading: boolean; + private callbacks: ItemLoadCallbackFunc[]; + + constructor() { + this.database = new loki('database'); + this.items = this.database.addCollection('items'); + this.simpfLinks = this.database.addCollection('simpf-links'); + this.loading = true; + this.callbacks = []; + this.load(); + } + + load(): void { + axios.get(process.env.PUBLIC_URL + '/database/items.json', { responseType: 'json' }).then((response) => { + const itemsJson = response.data as Item[]; + itemsJson.forEach((json: Item) => { + this.items.insert(json); + }); + const lock = new AsyncLock(); + lock.acquire('items', () => { + this.loading = false; + this.callbacks.forEach((callback) => { + callback(this.items); + }); + this.callbacks = []; + }); + }); + const simpfLinks = simpfLinksJson as SimPFLink[]; + simpfLinks.forEach((simpfLink: SimPFLink) => { + this.simpfLinks.insert(simpfLink); + }); + } + + registerItemLoadCallback(func: ItemLoadCallbackFunc): void { + const lock = new AsyncLock(); + lock.acquire('items', () => { + if (this.loading) { + this.callbacks.push(func); + } else { + func(this.items); + } + }); + } + + getUrl(item: ItemCore): string { + if (item.doi !== '') { + return '/database/item/id/' + funcs.escape(item.doi); + } + return '/database/item/' + String(item.item_id); + } + + getFileUrl(file: ItemBasicFile): string { + return process.env.PUBLIC_URL + '/database/file/' + String(file.file_id) + '/' + funcs.escape(file.original_file_name); + } + + getPreviewFileUrl(file: ItemBasicFile): string { + return process.env.PUBLIC_URL + '/database/file/' + String(file.file_id) + '.png'; + } + + getSearchByKeywordUrl(type: KeywordSearchType, keyword: string): string { + const params = new URLSearchParams({ type, keyword }); + return '/database/search?' + params.toString(); + } + + getItemTypeSearchUrl(type: string): string { + return '/database/search/itemtype/' + funcs.escape(type); + } + + getSearchByAdvancedKeywordsUrl(query: AdvancedSearchQuery): string { + const paramString = query.getQueryParams().toString(); + return '/database/search/advanced' + (paramString.length > 0 ? '?' + paramString : ''); + } + + getSearchKeywordByQuery(queryString: string): KeywordSearchQuery { + const query = new URLSearchParams(queryString); + const qtype = query.get('type'); + const type = qtype !== null && KEYWORD_SEARCH_TYPE_RANGE.includes(qtype) ? qtype as KeywordSearchType : 'all'; + const qkeyword = query.get('keyword'); + const keyword = qkeyword === null ? '' : qkeyword; + return ({ type, keyword }); + } + + getAdvancedSearchQueryByQuery(queryString: string): AdvancedSearchQuery { + const query: AdvancedSearchQuery = new AdvancedSearchQuery(); + query.setByQueryString(queryString); + return query; + } + + get(itemId: number, func: GetCallbackFunc): void { + this.registerItemLoadCallback((items) => { + const filter = { + item_id: itemId + } + const item = items.findOne(filter); + func(item); + }); + } + + getByDoi(doi: string, func: GetCallbackFunc): void { + this.registerItemLoadCallback((items) => { + const filter = { + doi: doi + } + const item = items.findOne(filter); + func(item); + }); + } + + getList(itemIds: number[], func: SearchCallbackFunc): void { + this.registerItemLoadCallback((items) => { + const filter = { + item_id: { + '$in': itemIds, + } + } + const sort = (a: Item, b: Item) => { + const aIdx = itemIds.findIndex((itemId) => { return a.item_id === itemId; }); + const bIdx = itemIds.findIndex((itemId) => { return b.item_id === itemId; }); + if (aIdx > bIdx) { + return 1; + } else if (aIdx < bIdx) { + return -1; + } + return 0; + } + const data = items.chain().find(filter).sort(sort).data(); + const res = { + total: data.length, + data: data, + } + func(res); + }); + } + + getListByIndexId(indexId: number, condition: SortCondition, func: SearchCallbackFunc): void { + this.registerItemLoadCallback((items) => { + const filter: any = { + 'index.index_id': indexId + }; + const offset = condition.limit * (condition.page - 1); + const result = items.chain().find(filter); + const itemSorter = new ItemSorter(condition); + const ret = { + total: result.count(), + data: result.sort(itemSorter.sort).offset(offset).limit(condition.limit).data() + }; + func(ret); + }); + } + + getListByItemType(itemType: string, subItemType: string, condition: SortCondition, func: SearchCallbackFunc): void { + this.registerItemLoadCallback((items) => { + let filter: any = { + item_type_name: 'xnp' + itemType, + } + if (subItemType !== '') { + switch (itemType) { + case 'conference': + filter.presentation_type = subItemType; + break; + case 'data': + filter.data_type = subItemType; + break; + case 'files': + filter.data_file_filetype = subItemType; + break; + case 'model': + filter.model_type = subItemType; + break; + case 'presentation': + filter.presentation_type = subItemType; + break; + case 'simulator': + filter.simulator_type = subItemType; + break; + case 'stimulus': + filter.stimulus_type = subItemType; + break; + case 'tool': + filter.tool_type = subItemType; + break; + default: + break; + } + } + const offset = condition.limit * (condition.page - 1); + const result = items.chain().find(filter); + const itemSorter = new ItemSorter(condition); + const ret = { + total: result.count(), + data: result.sort(itemSorter.sort).offset(offset).limit(condition.limit).data() + }; + func(ret); + }); + } + + getListByKeyword(type: KeywordSearchType, keyword: string, condition: SortCondition, func: SearchCallbackFunc): void { + this.registerItemLoadCallback((items) => { + const regex = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const num = keyword.match(/^[0-9]+$/) ? parseInt(keyword, 10) : null; + let filter: any = { '$or': [] }; + const appendToFilter = (type: string, strKeys: string[], numKeys: string[]) => { + const basicStrKeys: string[] = ['title', 'keyword', 'doi', 'description', 'uname', 'name', 'index.title']; + const basicNumKeys: string[] = []; + let filterItemType: any = { + item_type_name: 'xnp' + type, + '$or': [] + }; + let sKeys: string[] = basicStrKeys.concat(strKeys); + let nKeys: string[] = basicNumKeys.concat(numKeys); + sKeys.forEach((key) => { + let criteria: any = {}; + criteria[key] = { '$regex': [regex, 'i'] }; + filterItemType['$or'].push(criteria); + }); + if (num !== null) { + nKeys.forEach((key) => { + let criteria: any = {}; + criteria[key] = { '$eq': num }; + filterItemType['$or'].push(criteria); + }); + } + filter['$or'].push(filterItemType); + } + if (type === 'basic') { + filter['$or'].push({ 'title': { '$regex': [regex, 'i'] } }); + filter['$or'].push({ 'keyword': { '$regex': [regex, 'i'] } }); + } else { + if (type === 'all' || type === 'binder') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description']; + const numKeys: string[] = []; + appendToFilter('binder', strKeys, numKeys); + } + if (type === 'all' || type === 'book') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'classification', 'editor', 'publisher', 'isbn', 'url', 'author', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = []; + appendToFilter('book', strKeys, numKeys); + } + if (type === 'all' || type === 'conference') { + const strKeys: string[] = ['doi', 'title', 'conference_title', 'place', 'abstract', 'author', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = ['conference_from_year', 'conference_from_month', 'conference_from_mday', 'conference_to_year', 'conference_to_month', 'conference_to_mday']; + appendToFilter('conference', strKeys, numKeys); + } + if (type === 'all' || type === 'data') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'readme', 'rights', 'experimenter', 'data_type', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = ['publication_year', 'publication_month', 'publication_mday']; + appendToFilter('data', strKeys, numKeys); + } + if (type === 'all' || type === 'files') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'data_file_name', 'data_file_mimetype', 'data_file_filetype']; + const numKeys: string[] = []; + appendToFilter('files', strKeys, numKeys); + } + if (type === 'all' || type === 'memo') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'item_link', 'file.original_file_name']; + const numKeys: string[] = []; + appendToFilter('memo', strKeys, numKeys); + } + if (type === 'all' || type === 'model') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'readme', 'rights', 'creator', 'model_type', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = []; + appendToFilter('model', strKeys, numKeys); + } + if (type === 'all' || type === 'paper') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'journal', 'page', 'pubmed_id', 'author']; + const numKeys: string[] = ['publication_year', 'volume', 'number']; + appendToFilter('paper', strKeys, numKeys); + } + if (type === 'all' || type === 'presentation') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'readme', 'rights', 'creator', 'presentation_type', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = ['publication_year', 'publication_month', 'publication_mday']; + appendToFilter('presentation', strKeys, numKeys); + } + if (type === 'all' || type === 'simulator') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'readme', 'rights', 'developer', 'simulator_type', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = ['publication_year', 'publication_month', 'publication_mday']; + appendToFilter('simulator', strKeys, numKeys); + } + if (type === 'all' || type === 'stimulus') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'readme', 'rights', 'developer', 'stimulus_type', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = ['publication_year', 'publication_month', 'publication_mday']; + appendToFilter('stimulus', strKeys, numKeys); + } + if (type === 'all' || type === 'tool') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'description', 'readme', 'rights', 'developer', 'tool_type', 'file.caption', 'file.original_file_name']; + const numKeys: string[] = []; + appendToFilter('tool', strKeys, numKeys); + } + if (type === 'all' || type === 'url') { + const strKeys: string[] = ['doi', 'title', 'keyword', 'url', 'file.original_file_name']; + const numKeys: string[] = []; + appendToFilter('url', strKeys, numKeys); + } + if (type !== 'all') { + filter['item_type_name'] = 'xnp' + type; + } + } + const offset = condition.limit * (condition.page - 1); + const result = items.chain().find(filter); + const itemSorter = new ItemSorter(condition); + const ret = { + total: result.count(), + data: result.sort(itemSorter.sort).offset(offset).limit(condition.limit).data() + }; + func(ret); + }); + } + + getListByAdvancedSearchQuery(query: AdvancedSearchQuery, condition: SortCondition, func: SearchCallbackFunc): void { + this.registerItemLoadCallback((items) => { + const filter: any = query.getSearchFilter(); + const offset = condition.limit * (condition.page - 1); + const result = items.chain().find(filter); + const itemSorter = new ItemSorter(condition); + const ret = { + total: result.count(), + data: result.sort(itemSorter.sort).offset(offset).limit(condition.limit).data() + }; + func(ret); + }); + } + + getSimPFLinkUrl(itemId: number) { + const simpfLink = this.simpfLinks.findOne({ id: itemId }); + if (simpfLink === null) { + return ''; + } + return simpfLink.url; + } +} + +export default new ItemUtil(); \ No newline at end of file diff --git a/src/functions.ts b/src/functions.ts new file mode 100644 index 0000000..72a1c0c --- /dev/null +++ b/src/functions.ts @@ -0,0 +1,130 @@ +import XRegExp from 'xregexp'; +import Config, { MultiLang } from './config'; + +const escape = (str: string) => { + return encodeURIComponent(str).replace(/[!'()*]/g, (c) => { + return '%' + c.charCodeAt(0).toString(16); + }); +} + +const unescape = (str: string) => { + return decodeURIComponent(str); +} + +const htmlspecialchars = (str: string) => { + return str.replace(/(<|>|&|'|")/g, (match) => { + switch (match) { + case '<': + return '<'; + case '>': + return '>'; + case '&': + return '&'; + case '\'': + return '''; + case '"': + return '"'; + } + return ''; + }); +} + +const camelCase = (str: string) => { + return str.replace(/[-_](.)/g, (...matches) => { + return matches[1].toUpperCase(); + }); +} + +const snakeCase = (str: string) => { + var camel = camelCase(str); + return camel.replace(/[A-Z]/g, (...matches) => { + return "_" + matches[0].charAt(0).toLowerCase(); + }); +} + +const pascalCase = (str: string) => { + var camel = camelCase(str); + return camel.charAt(0).toUpperCase() + camel.slice(1); +} + +const base64Encode = (str: string) => { + return btoa(unescape(encodeURIComponent(str))); +} + +const base64Decode = (str: string) => { + return decodeURIComponent(escape(atob(str))); +} + +const ordinal = (num: number) => { + const hundred = num % 100; + if (hundred >= 10 && hundred <= 20) { + return 'th'; + } + const ten = num % 10; + const suffix = ['st', 'nd', 'rd']; + return ten > 0 && ten < 4 ? suffix[ten - 1] : 'th'; +} + +const mlang = (str: string, lang: MultiLang) => { + const mlLangs = ['en', 'ja']; + // escape brackets inside of + let text = str.replace(/(]*)(>)/isg, (whole, m1, m2, m3) => { + if (m2.match(/type=["']?(?:text|hidden)["']?/is)) { + return m1 + m2.replace(/\[/g, '__ml[ml__') + m3; + } + return whole; + }); + // escape brackets inside of + text = text.replace(/(]*>)(.*)(<\/textarea>)/isg, (whole, m1, m2, m3) => { + return m1 + m2.replace(/\[/g, '__ml[ml__') + m3; + }); + // simple pattern to strip selected lang_tags + const re = new RegExp('\\[/?(?:[^\\]]+\\|)?' + lang + '(?:\\|[^\\]]+)?\\](?:
    )?', 'g'); + text = text.replace(re, ''); + // eliminate description between the other language tags. + mlLangs.forEach((mlLang) => { + if (mlLang !== lang) { + const re = XRegExp('\\[(?:[^/][^\\]]+\\|)?' + mlLang + '(?:\\|[^\\]]+)?\\].*?\\[/(?:[^\\]]+\\|)?' + mlLang + '(?:\\|[^\\]]+)?\\](?:
    )?', 'isg'); + text = text.replace(re, (whole) => { + return whole.match(/<\/table>/) ? whole : ''; + }); + } + }); + // unescape brackets inside of + text = text.replace(/(]*>)(.*)(<\/textarea>)/isg, (whole, m1, m2, m3) => { + return m1 + m2.replace(/__ml\[ml__/g, '[') + m3; + }); + // unescape brackets inside of + text = text.replace(/(]*)(>)/isg, (whole, m1, m2, m3) => { + if (m2.match(/type=["']?(?:text|hidden)["']?/is)) { + return m1 + m2.replace(/__ml\[ml__/g, '[') + m3; + } + return whole; + }); + return text; +} + +const siteTitle = (lang: MultiLang) => { + return mlang(Config.SITE_TITLE, lang); +} + +const siteSlogan = (lang: MultiLang) => { + return mlang(Config.SITE_SLOGAN, lang); +} + +const Functions = { + escape, + unescape, + htmlspecialchars, + camelCase, + snakeCase, + pascalCase, + base64Encode, + base64Decode, + ordinal, + mlang, + siteTitle, + siteSlogan, +}; + +export default Functions; \ No newline at end of file diff --git a/src/index.css b/src/index.css index ec2585e..2daa7e9 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} +@import-normalize; diff --git a/src/index.tsx b/src/index.tsx index 87d1be5..aef507a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,5 @@ +import 'react-app-polyfill/ie11'; +import 'react-app-polyfill/stable'; import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 6b60c10..0000000 --- a/src/logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/mediawiki/MediaWiki.tsx b/src/mediawiki/MediaWiki.tsx new file mode 100644 index 0000000..acd8308 --- /dev/null +++ b/src/mediawiki/MediaWiki.tsx @@ -0,0 +1,100 @@ +import React, { Component } from 'react'; +import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; +import Loading from '../common/lib/Loading'; +import PageNotFound from '../common/lib/PageNotFound'; +import XoopsCode from '../common/lib/XoopsCode'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import MediaWikiUtils, { MediaWikiPageData } from './lib/MediaWikiUtils'; +import './assets/style.css'; +import NoticeSiteHasBeenArchived from '../common/lib/NoticeSiteHasBeenArchived'; + +interface Props { + lang: MultiLang; + name: string; +} + +interface State { + loading: boolean; + page: MediaWikiPageData | null; +} + +class MediaWiki extends Component { + + private isActive: boolean; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + page: null, + }; + this.isActive = false; + } + + componentDidMount() { + const { name } = this.props; + this.isActive = true; + this.updatePage(name); + } + + componentDidUpdate(prevProps: Props, prevState: State) { + const { name } = this.props; + const prevName = prevProps.name; + if (name !== prevName) { + this.setState({ loading: true, page: null }); + this.updatePage(name); + } + } + + componentWillUnmount() { + this.isActive = false; + } + + updatePage(name: string) { + this.isActive = true; + MediaWikiUtils.getPage(name, (page: MediaWikiPageData | null) => { + if (this.isActive) { + this.setState({ loading: false, page }); + } + }) + } + + render() { + const { lang } = this.props; + const { loading, page } = this.state; + if (loading) { + return ; + } + if (page === null) { + return ; + } + return ( +
    + + {Functions.mlang(page.title, lang)} - {Functions.siteTitle(lang)} + + +
    +
    + メインページ (Japanese) + | + Main Page (English) +
    +
    +
    +
    +

    {Functions.mlang(page.title, lang)}

    +
    +
    + +
    +
    +
    +
    + ); + } +} + +export default MediaWiki; diff --git a/src/mediawiki/MediaWikiXoopsPathRedirect.tsx b/src/mediawiki/MediaWikiXoopsPathRedirect.tsx new file mode 100644 index 0000000..6a345db --- /dev/null +++ b/src/mediawiki/MediaWikiXoopsPathRedirect.tsx @@ -0,0 +1,35 @@ +import React, { Component } from 'react'; +import { Redirect, RouteComponentProps, withRouter } from 'react-router'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; + +interface Props extends RouteComponentProps { + lang: MultiLang; +} + +class MediaWikiXoopsPathRedirect extends Component { + + getRedirectUrl(): string { + const { location } = this.props; + const name = 'mediawiki'; + const pathname = location.pathname || ''; + const search = new RegExp(`^/modules/${name}/(?:index.php/)?([^/]*)$`); + const matches = pathname.match(search); + if (matches === null) { + return ''; + } + const path = matches[1] || ''; + return '/' + name + '/' + path; + } + + render() { + const { lang } = this.props; + const url = this.getRedirectUrl(); + if (url === '') { + return ; + } + return ; + } +} + +export default withRouter(MediaWikiXoopsPathRedirect); diff --git a/src/mediawiki/assets/style.css b/src/mediawiki/assets/style.css new file mode 100644 index 0000000..4294fd6 --- /dev/null +++ b/src/mediawiki/assets/style.css @@ -0,0 +1,261 @@ +.mediawiki { + font-size: 0.875em; + line-height: 1.6; +} +.mediawiki .mw-content-text { + margin: 15px 0; +} +.mediawiki * { + box-sizing: content-box; +} +.mediawiki h1, +.mediawiki h2, +.mediawiki h3, +.mediawiki h4, +.mediawiki h5, +.mediawiki h6 { + color: black !important; + font-weight: bold; + page-break-after: avoid; + background: none; + margin: 0; + overflow: hidden; + padding-top: 0.5em; + padding-bottom: 0.17em; + border-bottom: 1px solid #aaa; +} +.mediawiki ul { + line-height: 1.5em; + margin: 0.3em 0 0 1.6em; + padding: 0; + list-style-type: disc; + list-style-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAANAQMAAABb8jbLAAAABlBMVEX///8AUow5QSOjAAAAAXRSTlMAQObYZgAAABNJREFUCB1jYEABBQw/wLCAgQEAGpIDyT0IVcsAAAAASUVORK5CYII=); +} +.mediawiki ol { + line-height: 1.5em; + margin: 0.3em 0 0 3.2em; + padding: 0; + list-style-image: none; +} +.mediawiki li { + margin-bottom: 0.1em; +} +.mediawiki dt { + font-weight: bold; + margin-bottom: 0.1em; +} +.mediawiki dl { + margin-top: 0.2em; + margin-bottom: 0.5em; +} +.mediawiki dd { + line-height: 1.5em; + margin-left: 1.6em; + margin-bottom: 0.1em; +} +.mediawiki q { + font-style: italic; +} +.mediawiki pre, +.mediawiki code, +.mediawiki tt, +.mediawiki kbd, +.mediawiki samp, +.mediawiki .mw-code { + font-family: monospace, Courier; + padding: 1em 0; + color: black; + background-color: #f9f9f9; + border: 1pt dashed black; + white-space: pre; + font-size: 8pt; + overflow: auto; +} +.mediawiki table { + font-size: 100%; +} +.mediawiki fieldset { + border: 1px solid #2f6fab; + margin: 1em 0 1em 0; + padding: 0 1em 1em; + line-height: 1.5em; +} +.mediawiki fieldset.nested { + margin: 0 0 0.5em 0; + padding: 0 0.5em 0.5em; +} +.mediawiki legend { + padding: 0.5em; + font-size: 95%; +} +.mediawiki p { + margin: 1em 0; + line-height: 1.2em; +} +.mediawiki pre, +.mediawiki .mw-code { + border: 1pt dashed black; + white-space: pre; + font-size: 8pt; + overflow: auto; + padding: 1em 0; + background: white; + color: black; +} +.mediawiki table.small { + font-size: 100%; +} +.mediawiki table.listing, +.mediawiki table.listing td { + border: 1pt solid black; + border-collapse: collapse; +} +.mediawiki mark { + background-color: yellow; + color: black; +} +.mediawiki .mw-content hr { + height: 1px; + color: #aaa; + background-color: #aaa; + border: 0; + margin: 0.2em 0; +} +.mediawiki abbr[title], +.mediawiki .explain[title] { + border-bottom: 1px dotted; + cursor: help; +} +.mediawiki img.tex { + vertical-align: middle; +} +.mediawiki span.texhtml { + font-family: serif; +} +.mediawiki .center { + width: 100%; + text-align: center; +} +.mediawiki .center * { + margin-left: auto; + margin-right: auto; +} +.mediawiki .small { + font-size: 94%; +} + +.mediawiki .mw-content .thumbcaption { + text-align: left; +} +.mediawiki .mw-infobox { + border: 2px solid #ff7f00; + margin: 0.5em; + clear: left; + overflow: hidden; +} +.mediawiki .mw-infobox-left { + margin: 7px; + float: left; + width: 35px; +} +.mediawiki .mw-infobox-right { + margin: 0.5em 0.5em 0.5em 49px; +} +.mediawiki .mw-datatable { + border-collapse: collapse; +} +.mediawiki .mw-datatable, +.mediawiki .mw-datatable td, +.mediawiki .mw-datatable th { + border: 1px solid #aaaaaa; + padding: 0 0.15em 0 0.15em; +} +.mediawiki .mw-datatable th { + background-color: #ddddff; +} +.mediawiki .mw-datatable td { + background-color: #ffffff; +} +.mediawiki .mw-datatable tr:hover td { + background-color: #eeeeff; +} + +.mediawiki .mw-header .navigation a { + margin: 0 5px; +} + +.mediawiki .mw-content .toc { + display: table; + padding: 7px; + border: 1px solid #aaa; + background-color: #f9f9f9; + font-size: 90%; +} +.mediawiki .mw-content .toc ul { + margin: 0.3em 0; + text-align: left; + list-style-type: none; + list-style-image: none; + margin-left: 0; + padding: 0; + text-align: left; +} +.mediawiki .mw-content .toc ul ul { + margin: 0 0 0 2em; +} +.mediawiki .mw-content .toc ul ul { + margin: 0 0 0 2em; +} +.mediawiki .mw-content .toc .toctoggle { + font-size: 94%; +} +.mediawiki .mw-content .toc h2 { + display: inline; + border: none; + padding: 0; + font-size: 100%; + font-weight: bold; +} +.mediawiki .mw-content .toc #toctitle { + text-align: center; +} +.mediawiki div.tright { + margin: 0.5em 0 1.3em 1.4em; +} +.mediawiki div.thumb { + margin-bottom: 0.5em; + width: auto; + background-color: transparent; +} + +.mediawiki div.tleft { + margin: 0.5em 1.4em 1.3em 0; +} +.mediawiki div.tright, +.mediawiki div.floatright, +.mediawiki table.floatright { + clear: right; + float: right; +} +.mediawiki div.thumb { + margin-bottom: 0.5em; + width: auto; + background-color: transparent; +} +.mediawiki div.thumbinner { + border: 1px solid #ccc; + padding: 3px !important; + background-color: #f9f9f9; + font-size: 94%; + text-align: center; + overflow: hidden; +} +.mediawiki .thumbcaption { + border: none; + line-height: 1.4em; + padding: 3px !important; + font-size: 94%; +} +.mediawiki .thumbimage { + border: 1px solid #ccc; +} diff --git a/src/mediawiki/lib/MediaWikiUtils.ts b/src/mediawiki/lib/MediaWikiUtils.ts new file mode 100644 index 0000000..e4d2808 --- /dev/null +++ b/src/mediawiki/lib/MediaWikiUtils.ts @@ -0,0 +1,47 @@ +import axios from 'axios'; +import loki from 'lokijs'; +import contentsJson from '../assets/contents.json'; +import Functions from '../../functions'; + +export interface MediaWikiPageData { + title: string; + text: string; +} + +export interface MediaWikiContentData { + id: number; + title: string; +} + +export type GetContentCallback = (page: MediaWikiPageData | null) => void; + +class MediaWikiUtils { + + private database: loki; + private contents: Collection; + + constructor(json: MediaWikiContentData[]) { + this.database = new loki('mediawiki'); + this.contents = this.database.addCollection('contents'); + json.forEach((data) => { + this.contents.insert(data); + }); + } + + getPage(name: string, callback: GetContentCallback): void { + const title = Functions.unescape(name).replace(/_/g, ' '); + const content = this.contents.findOne({ title }); + if (content === null) { + callback(null); + } else { + axios.get('/mediawiki/contents/' + content.id + '.json').then((response) => { + const page = response.data as MediaWikiPageData; + callback(page); + }).catch(e => { + callback(null); + }); + } + } +} + +export default new MediaWikiUtils(contentsJson); \ No newline at end of file diff --git a/src/pico/Pico.tsx b/src/pico/Pico.tsx new file mode 100644 index 0000000..6ce402d --- /dev/null +++ b/src/pico/Pico.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Redirect, Route, RouteComponentProps, Switch } from 'react-router-dom'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import './assets/pico_main.css'; +import PicoUtils from './lib/PicoUtils'; +import PicoCategory from './PicoCategory'; +import PicoContent from './PicoContent'; +import PicoIndex from './PicoIndex'; +import PicoMenu from './PicoMenu'; + +interface Props { + lang: MultiLang; + name: string; +} + +const Pico = (props: Props) => { + const { lang, name } = props; + return ( + <> + + } /> + ) => { + const { location } = props; + const { pathname, search } = location; + const path = pathname.replace('/' + name + '/', ''); + if (path === '' || path === 'index.php') { + const params = new URLSearchParams(search); + const paramCatId = params.get('cat_id'); + if (paramCatId !== null && paramCatId.match(/^\d+$/)) { + const catId = parseInt(paramCatId, 10); + return ; + } + const paramContentId = params.get('content_id'); + if (paramContentId !== null && paramContentId.match(/^\d+$/)) { + const contentId = parseInt(paramContentId, 10); + return ; + } + const paramPage = params.get('page'); + if (paramPage !== null && paramPage === 'menu') { + return ; + } + return ; + } + const category = PicoUtils.getCategoryByPath(name, path); + if (category !== null) { + return ; + } + const content = PicoUtils.getContentByPath(name, path); + if (content !== null) { + return ; + } + return ; + }} /> + + + + ); +} + +export default Pico; diff --git a/src/pico/PicoCategory.tsx b/src/pico/PicoCategory.tsx new file mode 100644 index 0000000..224fd0b --- /dev/null +++ b/src/pico/PicoCategory.tsx @@ -0,0 +1,84 @@ +import React, { Fragment } from 'react'; +import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import PicoUtils, { PicoCategoryData, PicoContentData } from './lib/PicoUtils'; + +interface Props { + lang: MultiLang; + name: string; + catId: number; +} + +const PicoCategory = (props: Props) => { + const { lang, name, catId } = props; + const pico = PicoUtils.getModule(name); + if (pico === null) { + return ; + } + const category = PicoUtils.getCategory(name, catId); + if (category === null) { + return ; + } + const parentCategories = PicoUtils.getParentCategories(name, category.pid); + const subCategories = PicoUtils.getSubCategories(name, catId); + const contents = PicoUtils.getCategoryContents(name, catId); + return ( +
    + + {Functions.mlang(category.title, lang)} - {Functions.mlang(pico.name, lang)} - {Functions.siteTitle(lang)} + + {pico.show_breadcrumbs !== 0 && ( +
    + {parentCategories.map((parentCategory: PicoCategoryData, idx: number) => { + const link = '/' + name + '/' + parentCategory.link; + return ( + + {idx > 0 && <> > } + {Functions.mlang(parentCategory.title, lang)} + + ); + })} + {parentCategories.length > 0 && <> > } + {Functions.mlang(category.title, lang)} +
    + )} + {catId === 0 && pico.message !== '' && ( +

    {Functions.mlang(pico.message, lang)}

    + )} +

    {Functions.mlang(category.title, lang)}

    + {category.desc !== '' && ( +

    {Functions.mlang(category.desc, lang)}

    + )} + {subCategories.length > 0 && ( + <> +

    {Functions.mlang('[en]Subcageroies[/en][ja]サブカテゴリー[/ja]', lang)}

    + {subCategories.map((subCategory: PicoCategoryData) => { + const url = '/' + name + '/' + subCategory.link; + return ( +
    +
    {Functions.mlang(subCategory.title, lang)}
    +
    {Functions.mlang(subCategory.desc, lang)}
    +
    + ); + })} + + )} + {contents.length > 0 && ( + <> +

    {Functions.mlang('[en]Contents[/en][ja]コンテンツ[/ja]', lang)}

    +
      + {contents.map((content: PicoContentData) => { + const url = '/' + name + '/' + content.link; + return
    • {Functions.mlang(content.title, lang)}
    • ; + })} +
    + + )} +
    + ); +}; + +export default PicoCategory; \ No newline at end of file diff --git a/src/pico/PicoContent.tsx b/src/pico/PicoContent.tsx new file mode 100644 index 0000000..522bbba --- /dev/null +++ b/src/pico/PicoContent.tsx @@ -0,0 +1,109 @@ +import React, { Component, Fragment } from 'react'; +import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; +import { HashLink } from 'react-router-hash-link'; +import Loading from '../common/lib/Loading'; +import PageNotFound from '../common/lib/PageNotFound'; +import XoopsCode from '../common/lib/XoopsCode'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import PicoUtils, { PicoCategoryData, PicoPageData } from './lib/PicoUtils'; + +interface Props { + lang: MultiLang; + name: string; + contentId: number; +} + +interface State { + loading: boolean; + page: PicoPageData | null; +} + +class PicoContent extends Component { + + private isActive: boolean; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + page: null, + }; + this.isActive = false; + } + + componentDidMount() { + const { name, contentId } = this.props; + this.isActive = true; + this.updatePage(name, contentId); + } + + componentDidUpdate(prevProps: Props, prevState: State) { + const { name, contentId } = this.props; + const prevName = prevProps.name; + const prevContentId = prevProps.contentId; + if (name !== prevName || contentId !== prevContentId) { + this.setState({ loading: true, page: null }); + this.updatePage(name, contentId); + } + } + + componentWillUnmount() { + this.isActive = false; + } + + updatePage(name: string, contentId: number) { + this.isActive = true; + PicoUtils.getPage(name, contentId, (page: PicoPageData | null) => { + if (this.isActive) { + this.setState({ loading: false, page }); + } + }) + } + + render() { + const { lang, name, contentId } = this.props; + const { loading, page } = this.state; + if (loading) { + return ; + } + if (page === null) { + return ; + } + const pico = PicoUtils.getModule(name); + if (pico === null) { + return ; + } + const categories = PicoUtils.getContentCategery(name, contentId); + return ( +
    + + {Functions.mlang(page.title, lang)} - {Functions.mlang(pico.name, lang)} - {Functions.siteTitle(lang)} + + {pico.show_breadcrumbs !== 0 && ( +
    + {categories.map((category: PicoCategoryData, idx: number) => { + const link = '/' + name + '/' + category.link; + return ( + + {idx > 0 && <> > } + {Functions.mlang(category.title, lang)} + + ); + })} +  > {Functions.mlang(page.title, lang)} +
    + )} +
    + +
    +
    + {Functions.mlang('[en]Jump to the top[/en][ja]この記事の1行目に飛ぶ[/ja]', lang)} +
    +
    + ); + } +} + +export default PicoContent; diff --git a/src/pico/PicoIndex.tsx b/src/pico/PicoIndex.tsx new file mode 100644 index 0000000..2f8578d --- /dev/null +++ b/src/pico/PicoIndex.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import PicoUtils from './lib/PicoUtils'; +import PicoCategory from './PicoCategory'; +import PicoContent from './PicoContent'; +import PicoMenu from './PicoMenu'; + +interface Props { + lang: MultiLang; + name: string; +} + +const PicoIndex = (props: Props) => { + const { lang, name } = props; + const pico = PicoUtils.getModule(name); + if (pico === null) { + return ; + } + if (pico.show_menuinmoduletop !== 0) { + return + } + if (pico.show_listasindex !== 0) { + return + } + const content = PicoUtils.getFirstContent(name, 0); + if (content === null) { + return ; + } + return ; + +} + +export default PicoIndex; diff --git a/src/pico/PicoMenu.tsx b/src/pico/PicoMenu.tsx new file mode 100644 index 0000000..05afc0c --- /dev/null +++ b/src/pico/PicoMenu.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { Link } from 'react-router-dom'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; +import Functions from '../functions'; +import PicoUtils, { PicoCategoryData, PicoContentData } from './lib/PicoUtils'; + +interface Props { + lang: MultiLang; + name: string; +} + +interface PicoMenuCategoryProps { + lang: MultiLang; + name: string; + category: PicoCategoryData; + depth: number; +} + +const PicoMenuCategory = (props: PicoMenuCategoryProps) => { + const { lang, name, category, depth } = props; + const subCategories = PicoUtils.getSubCategories(name, category.id); + const contents = PicoUtils.getCategoryContents(name, category.id); + const level = 'level' + depth; + const link = {Functions.mlang(category.title, lang)}; + let title =
    {link}
    ; + switch (depth) { + case 1: + title =

    {link}

    ; + break; + case 2: + title =

    {link}

    ; + break; + case 3: + title =

    {link}

    ; + break; + case 4: + title =

    {link}

    ; + break; + case 5: + title =
    {link}
    ; + break; + } + return ( + <> + {title} + {contents.length > 0 && ( +
    +
      + {contents.map((content: PicoContentData) => { + const url = '/' + name + '/' + content.link; + return
    • {Functions.mlang(content.title, lang)}
    • ; + })} +
    +
    + )} + {subCategories.length > 0 && ( + <> + {subCategories.map((subCategory: PicoCategoryData) => { + return ; + })} + + )} + + ); +} + +const PicoMenu = (props: Props) => { + const { lang, name } = props; + const pico = PicoUtils.getModule(name); + if (pico === null) { + return ; + } + const category = PicoUtils.getCategory(name, 0); + if (category === null) { + return ; + } + return ( +
    + + {Functions.mlang('[en]Menu[/en][ja]メニュー[/ja]', lang)} - {Functions.mlang(pico.name, lang)} - {Functions.siteTitle(lang)} + + {pico.message !== '' && ( +

    {Functions.mlang(pico.message, lang)}

    + )} + +
    + ); +}; + +export default PicoMenu; \ No newline at end of file diff --git a/src/pico/PicoXoopsPathRedirect.tsx b/src/pico/PicoXoopsPathRedirect.tsx new file mode 100644 index 0000000..e39d888 --- /dev/null +++ b/src/pico/PicoXoopsPathRedirect.tsx @@ -0,0 +1,43 @@ +import React, { Component } from 'react'; +import { Redirect, RouteComponentProps, withRouter } from 'react-router'; +import PageNotFound from '../common/lib/PageNotFound'; +import { MultiLang } from '../config'; + +interface Props extends RouteComponentProps { + lang: MultiLang; + name: string; +} + +class PicoXoopsPathRedirect extends Component { + + getRedirectUrl(): string { + const { name, location } = this.props; + const pathname = location.pathname || ''; + const search = new RegExp(`^/modules/${name}(?:/+(.*))?$`); + const matches = pathname.match(search); + if (matches === null) { + return ''; + } + const path = matches[1] || ''; + switch (path) { + case '': + case 'index.php': { + const params = new URLSearchParams(location.search); + const paramString = params.toString(); + return '/' + name + '/' + (paramString !== '' ? '?' + paramString : ''); + } + } + return '/' + name + '/' + path; + } + + render() { + const { lang } = this.props; + const url = this.getRedirectUrl(); + if (url === '') { + return ; + } + return ; + } +} + +export default withRouter(PicoXoopsPathRedirect); diff --git a/src/pico/assets/pico_main.css b/src/pico/assets/pico_main.css new file mode 100644 index 0000000..9413c22 --- /dev/null +++ b/src/pico/assets/pico_main.css @@ -0,0 +1,140 @@ +div.pico_breadcrumbs { + font-size: 95%; + padding: 0 0 3px; + border-bottom: 1px #aaa solid; +} + +.pico_body { + margin: 0 -2px; + padding: 15px 8px; +} + +div.pico_menu h1 { + margin: 18px 0 0 0; + padding: 3px; + background-color: #eee; +} +div.pico_menu h2 { + margin: 18px 0 0 10px; + padding: 3px; + background-color: #eee; +} +div.pico_menu h3 { + margin: 18px 0 0 20px; + padding: 3px; + background-color: #eee; +} +div.pico_menu h4 { + margin: 18px 0 0 30px; + padding: 3px; + background-color: #eee; +} +div.pico_menu h5 { + margin: 18px 0 0 40px; + padding: 3px; + background-color: #eee; +} +div.pico_menu div.level1 { + margin-left: 0; +} +div.pico_menu div.level2 { + margin-left: 10px; +} +div.pico_menu div.level3 { + margin-left: 20px; +} +div.pico_menu div.level4 { + margin-left: 30px; +} +div.pico_menu div.level5 { + margin-left: 40px; +} + +em.pico_notice { + font-weight: bold; + font-style: normal; + color: #ff0000; +} + +div.pico_controllers_in_menu { + float: right; + position: relative; + top: -1.5em; +} + +div.bottom_of_content_body { + clear: right; +} + +ul.pico_list_contents li { + list-style: none outside; +} +ul.pico_list_contents_in_menu li { + list-style: none outside; +} + +div.pico_print_icon { + float: right; + width: 40px; + height: 40px; +} +div.pico_tellafriend_icon { + float: right; + width: 40px; + height: 40px; +} +div.pico_vote form { + display: inline; +} + +table.pico_pagenavigation { + border-top: 1px #aaa solid; + margin-top: 20px; +} + +table.pico_form_table th.pico_waiting { + color: red; +} +table.pico_form_table td.pico_waiting { + color: red; + background-color: white; +} + +table.pico_form_table td, +table.pico_form_table th { + color: black; + vertical-align: top !important; + text-align: left; +} +p.pico_submit { + text-align: center; + margin: 0; + padding: 10px; +} + +input.pico_ascii_only { + ime-mode: disabled; +} +input.pico_number_only { + ime-mode: disabled; + text-align: right; +} + +pre.pico_history_diff del { + color: red; +} +pre.pico_history_diff ins { + color: blue; +} + +div.pico_pagebreak { + margin: 10px; +} +div.pico_pagebreak span { + border: 1px solid black; + padding: 2px; + margin: 2px; +} +div.pico_pagebreak span.selected { + border: 0px; +} diff --git a/src/pico/lib/PicoUtils.ts b/src/pico/lib/PicoUtils.ts new file mode 100644 index 0000000..c33f876 --- /dev/null +++ b/src/pico/lib/PicoUtils.ts @@ -0,0 +1,180 @@ +import axios from 'axios'; +import loki from 'lokijs'; +import configJson from '../assets/config.json'; + +export interface PicoModuleData { + name: string; + dirname: string; + message: string; + show_menuinmoduletop: number; + show_listasindex: number; + show_breadcrumbs: number; + show_pagenavi: number; +} + +export interface PicoCategoryData { + id: number; + title: string; + desc: string; + pid: number; + weight: number; + link: string; +} + +export interface PicoContentData { + id: number; + title: string; + cat_id: number; + weight: number; + link: string; +} + +interface PicoConfigData { + module: PicoModuleData; + categories: PicoCategoryData[]; + contents: PicoContentData[]; +} + +interface PicoData { + module: PicoModuleData; + categories: Collection; + contents: Collection; +} + +export interface PicoPageData { + id: number; + title: string; + content: string; +} + +export const PICO_CATEGORY_ID_ROOT = 65535; +export type GetPageCallback = (page: PicoPageData | null) => void; + +class PicoUtils { + + private database: loki; + private modules: Map; + + constructor(json: PicoConfigData[]) { + this.database = new loki('pico'); + this.modules = new Map(); + json.forEach((data) => { + const name = data.module.dirname; + const pico = { + module: data.module, + categories: this.database.addCollection(name + '_categories'), + contents: this.database.addCollection(name + '_contents'), + }; + data.categories.forEach(category => { + pico.categories.insert(category); + }); + data.contents.forEach(content => { + pico.contents.insert(content); + }); + this.modules.set(name, pico); + }) + } + + getModule(name: string): PicoModuleData | null { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return null; + } + return pico.module; + } + + getCategoryByPath(name: string, link: string): PicoCategoryData | null { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return null; + } + const content = pico.categories.findOne({ link: link }); + return content; + } + + getCategory(name: string, catId: number): PicoCategoryData | null { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return null; + } + const category = pico.categories.findOne({ id: catId }); + return category; + } + + getParentCategories(name: string, catId: number): PicoCategoryData[] { + const categories: PicoCategoryData[] = []; + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return categories; + } + while (catId !== PICO_CATEGORY_ID_ROOT) { + const category = pico.categories.findOne({ id: catId }); + if (category === null) { + break; + } + categories.unshift(category); + catId = category.pid; + } + return categories; + } + + getSubCategories(name: string, catId: number): PicoCategoryData[] { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return []; + } + return pico.categories.chain().find({ pid: catId }).simplesort('weight').data(); + } + + getCategoryContents(name: string, catId: number): PicoContentData[] { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return []; + } + return pico.contents.chain().find({ cat_id: catId }).simplesort('weight').data(); + } + + getContentCategery(name: string, contentId: number): PicoCategoryData[] { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return []; + } + const content = pico.contents.findOne({ id: contentId }); + if (content === null) { + return []; + } + return this.getParentCategories(name, content.cat_id); + } + + getFirstContent(name: string, catId: number): PicoContentData | null { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return null; + } + const contents = pico.contents.chain().find({ cat_id: catId }).simplesort('weight').limit(1).data(); + if (contents.length !== 1) { + return null; + } + return contents[0]; + } + + getContentByPath(name: string, link: string): PicoContentData | null { + const pico = this.modules.get(name); + if (typeof pico === 'undefined') { + return null; + } + const content = pico.contents.findOne({ link: link }); + return content as PicoContentData | null; + } + + getPage(name: string, contentId: number, callback: GetPageCallback): void { + axios.get('/' + name + '/' + contentId + '.json').then((response) => { + const page = response.data as PicoPageData; + callback(page); + }).catch(e => { + callback(null); + }); + } +} + +export default new PicoUtils(configJson); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0a348e3..dce2903 100644 --- a/yarn.lock +++ b/yarn.lock @@ -756,7 +756,15 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typescript" "^7.3.2" -"@babel/runtime@7.5.5", "@babel/runtime@^7.0.0", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5": +"@babel/runtime-corejs2@^7.2.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.5.5.tgz#c3214c08ef20341af4187f1c9fbdc357fbec96b2" + integrity sha512-FYATQVR00NSNi7mUfpPDp7E8RYMXDuO8gaix7u/w3GekfUinKgX1AcTxs7SoiEmoEW9mbpjrwqWSW6zCmw5h8A== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.2" + +"@babel/runtime@7.5.5", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== @@ -819,10 +827,10 @@ resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a" integrity sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw== -"@hapi/hoek@6.x.x": - version "6.2.4" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-6.2.4.tgz#4b95fbaccbfba90185690890bdf1a2fbbda10595" - integrity sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A== +"@hapi/bourne@1.x.x": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" + integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== "@hapi/hoek@8.x.x": version "8.2.1" @@ -830,20 +838,15 @@ integrity sha512-JPiBy+oSmsq3St7XlipfN5pNA6bDJ1kpa73PrK/zR29CVClDVqy04AanM/M/qx5bSF+I61DdCfAvRrujau+zRg== "@hapi/joi@^15.0.0": - version "15.1.0" - resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.0.tgz#940cb749b5c55c26ab3b34ce362e82b6162c8e7a" - integrity sha512-n6kaRQO8S+kepUTbXL9O/UOL788Odqs38/VOfoCrATDtTvyfiO3fgjlSRaNkHabpTLgM7qru9ifqXlXbXk8SeQ== + version "15.1.1" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" + integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== dependencies: "@hapi/address" "2.x.x" - "@hapi/hoek" "6.x.x" - "@hapi/marker" "1.x.x" + "@hapi/bourne" "1.x.x" + "@hapi/hoek" "8.x.x" "@hapi/topo" "3.x.x" -"@hapi/marker@1.x.x": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@hapi/marker/-/marker-1.0.0.tgz#65b0b2b01d1be06304886ce9b4b77b1bfb21a769" - integrity sha512-JOfdekTXnJexfE8PyhZFyHvHjt81rBFSAbTIRAhF2vv/2Y1JzoKsGqxH/GpZJoF7aEfYok8JVcAHmSz1gkBieA== - "@hapi/topo@3.x.x": version "3.1.3" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.3.tgz#c7a02e0d936596d29f184e6d7fdc07e8b5efce11" @@ -851,76 +854,77 @@ dependencies: "@hapi/hoek" "8.x.x" -"@jest/console@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" - integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg== +"@jest/console@^24.7.1", "@jest/console@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" + integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== dependencies: - "@jest/source-map" "^24.3.0" + "@jest/source-map" "^24.9.0" chalk "^2.0.1" slash "^2.0.0" -"@jest/core@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.8.0.tgz#fbbdcd42a41d0d39cddbc9f520c8bab0c33eed5b" - integrity sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A== +"@jest/core@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4" + integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A== dependencies: "@jest/console" "^24.7.1" - "@jest/reporters" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/reporters" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" ansi-escapes "^3.0.0" chalk "^2.0.1" exit "^0.1.2" graceful-fs "^4.1.15" - jest-changed-files "^24.8.0" - jest-config "^24.8.0" - jest-haste-map "^24.8.0" - jest-message-util "^24.8.0" + jest-changed-files "^24.9.0" + jest-config "^24.9.0" + jest-haste-map "^24.9.0" + jest-message-util "^24.9.0" jest-regex-util "^24.3.0" - jest-resolve-dependencies "^24.8.0" - jest-runner "^24.8.0" - jest-runtime "^24.8.0" - jest-snapshot "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" - jest-watcher "^24.8.0" + jest-resolve "^24.9.0" + jest-resolve-dependencies "^24.9.0" + jest-runner "^24.9.0" + jest-runtime "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" + jest-watcher "^24.9.0" micromatch "^3.1.10" p-each-series "^1.0.0" - pirates "^4.0.1" realpath-native "^1.1.0" rimraf "^2.5.4" + slash "^2.0.0" strip-ansi "^5.0.0" -"@jest/environment@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.8.0.tgz#0342261383c776bdd652168f68065ef144af0eac" - integrity sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw== +"@jest/environment@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18" + integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ== dependencies: - "@jest/fake-timers" "^24.8.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" - jest-mock "^24.8.0" + "@jest/fake-timers" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" -"@jest/fake-timers@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1" - integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw== +"@jest/fake-timers@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" + integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== dependencies: - "@jest/types" "^24.8.0" - jest-message-util "^24.8.0" - jest-mock "^24.8.0" + "@jest/types" "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" -"@jest/reporters@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.8.0.tgz#075169cd029bddec54b8f2c0fc489fd0b9e05729" - integrity sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw== +"@jest/reporters@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43" + integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw== dependencies: - "@jest/environment" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.2" @@ -928,74 +932,75 @@ istanbul-lib-instrument "^3.0.1" istanbul-lib-report "^2.0.4" istanbul-lib-source-maps "^3.0.1" - istanbul-reports "^2.1.1" - jest-haste-map "^24.8.0" - jest-resolve "^24.8.0" - jest-runtime "^24.8.0" - jest-util "^24.8.0" + istanbul-reports "^2.2.6" + jest-haste-map "^24.9.0" + jest-resolve "^24.9.0" + jest-runtime "^24.9.0" + jest-util "^24.9.0" jest-worker "^24.6.0" - node-notifier "^5.2.1" + node-notifier "^5.4.2" slash "^2.0.0" source-map "^0.6.0" string-length "^2.0.0" -"@jest/source-map@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.3.0.tgz#563be3aa4d224caf65ff77edc95cd1ca4da67f28" - integrity sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag== +"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" + integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== dependencies: callsites "^3.0.0" graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/test-result@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3" - integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng== +"@jest/test-result@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" + integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== dependencies: - "@jest/console" "^24.7.1" - "@jest/types" "^24.8.0" + "@jest/console" "^24.9.0" + "@jest/types" "^24.9.0" "@types/istanbul-lib-coverage" "^2.0.0" -"@jest/test-sequencer@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz#2f993bcf6ef5eb4e65e8233a95a3320248cf994b" - integrity sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg== +"@jest/test-sequencer@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31" + integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A== dependencies: - "@jest/test-result" "^24.8.0" - jest-haste-map "^24.8.0" - jest-runner "^24.8.0" - jest-runtime "^24.8.0" + "@jest/test-result" "^24.9.0" + jest-haste-map "^24.9.0" + jest-runner "^24.9.0" + jest-runtime "^24.9.0" -"@jest/transform@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5" - integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA== +"@jest/transform@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56" + integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" babel-plugin-istanbul "^5.1.0" chalk "^2.0.1" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.1.15" - jest-haste-map "^24.8.0" - jest-regex-util "^24.3.0" - jest-util "^24.8.0" + jest-haste-map "^24.9.0" + jest-regex-util "^24.9.0" + jest-util "^24.9.0" micromatch "^3.1.10" + pirates "^4.0.1" realpath-native "^1.1.0" slash "^2.0.0" source-map "^0.6.1" write-file-atomic "2.4.1" -"@jest/types@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad" - integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg== +"@jest/types@^24.8.0", "@jest/types@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" + integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" - "@types/yargs" "^12.0.9" + "@types/yargs" "^13.0.0" "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" @@ -1113,6 +1118,11 @@ "@svgr/plugin-svgo" "^4.3.1" loader-utils "^1.2.3" +"@types/async-lock@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/async-lock/-/async-lock-1.1.1.tgz#81f218213bebcc5f740efe9648272c774a2e4b4b" + integrity sha512-TU1X8jmAU2BjwKryBFV/GDezz7Ge0xu9ZuYC7dy6wKj4hnL0JcxeseCOr/G2JkGylff6hdUBrR+Ee5ApAQeU5g== + "@types/babel__core@^7.1.0": version "7.1.2" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f" @@ -1146,11 +1156,50 @@ dependencies: "@babel/types" "^7.3.0" +"@types/cookie@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" + integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== + +"@types/domhandler@*": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/domhandler/-/domhandler-2.4.1.tgz#7b3b347f7762180fbcb1ece1ce3dd0ebbb8c64cf" + integrity sha512-cfBw6q6tT5sa1gSPFSRKzF/xxYrrmeiut7E0TxNBObiLSBTuFEHibcfEe3waQPEDbqBsq+ql/TOniw65EyDFMA== + +"@types/domutils@*": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@types/domutils/-/domutils-1.7.2.tgz#89422e579c165994ad5c09ce90325da596cc105d" + integrity sha512-Nnwy1Ztwq42SSNSZSh9EXBJGrOZPR+PQ2sRT4VZy8hnsFXfCil7YlKO2hd2360HyrtFz2qwnKQ13ENrgXNxJbw== + dependencies: + "@types/domhandler" "*" + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== +"@types/history@*": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.3.tgz#856c99cdc1551d22c22b18b5402719affec9839a" + integrity sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw== + +"@types/hoist-non-react-statics@^3.0.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + +"@types/htmlparser2@*": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@types/htmlparser2/-/htmlparser2-3.10.1.tgz#1e65ba81401d53f425c1e2ba5a3d05c90ab742c7" + integrity sha512-fCxmHS4ryCUCfV9+CJZY1UjkbR+6Al/EQdX5Jh03qBj9gdlPG5q+7uNoDgE/ZNXb3XNWSAQgqKIWnbRCbOyyWA== + dependencies: + "@types/domhandler" "*" + "@types/domutils" "*" + "@types/node" "*" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -1176,10 +1225,10 @@ resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA== -"@types/jest@24.0.17": - version "24.0.17" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.17.tgz#b66ea026efb746eb5db1356ee28518aaff7af416" - integrity sha512-1cy3xkOAfSYn78dsBWy4M3h/QF/HeWPchNFDjysVtp3GHeTdSmtluNnELfCmfNRRHo0OWEcpf+NsEJQvwQfdqQ== +"@types/jest@24.0.18": + version "24.0.18" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.18.tgz#9c7858d450c59e2164a8a9df0905fc5091944498" + integrity sha512-jcDDXdjTcrQzdN06+TSVsPPqxvsZA/5QkYfIZlq1JMw7FdP5AZylbOc+6B/cuDurctRe+MziUMtQ3xQdrbjqyQ== dependencies: "@types/jest-diff" "*" @@ -1188,11 +1237,21 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== -"@types/node@12.7.2": +"@types/lokijs@^1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/lokijs/-/lokijs-1.5.2.tgz#ed228f080033ce1fb16eff4acde65cb9ae0f1bf2" + integrity sha512-ZF14v1P1Bjbw8VJRu+p4WS9V926CAOjWF4yq23QmSBWRPe0/GXlUKzSxjP1fi/xi8nrq6zr9ECo8Z/8KsRqroQ== + +"@types/node@*", "@types/node@12.7.2": version "12.7.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== +"@types/object-assign@^4.0.30": + version "4.0.30" + resolved "https://registry.yarnpkg.com/@types/object-assign/-/object-assign-4.0.30.tgz#8949371d5a99f4381ee0f1df0a9b7a187e07e652" + integrity sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI= + "@types/prop-types@*": version "15.7.1" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6" @@ -1203,10 +1262,65 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== -"@types/react-dom@16.8.5": - version "16.8.5" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.5.tgz#3e3f4d99199391a7fb40aa3a155c8dd99b899cbd" - integrity sha512-idCEjROZ2cqh29+trmTmZhsBAUNQuYrF92JHKzZ5+aiFM1mlSk3bb23CK7HhYuOY75Apgap5y2jTyHzaM2AJGA== +"@types/react-dom@16.9.0": + version "16.9.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.0.tgz#ba6ddb00bf5de700b0eb91daa452081ffccbfdea" + integrity sha512-OL2lk7LYGjxn4b0efW3Pvf2KBVP0y1v3wip1Bp7nA79NkOpElH98q3WdCEdDj93b2b0zaeBG9DvriuKjIK5xDA== + dependencies: + "@types/react" "*" + +"@types/react-helmet@^5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-5.0.9.tgz#60ab5accce74b168ca1d274671522f6b2cf2c98f" + integrity sha512-0UVaMQk/Xvq6rFaGyepSBnRApy5RE+YH0XAXlbOBhtez5D9y1/jxKaKODofPzNnJLoLQ+sATTsWQIvrw1Dtiag== + dependencies: + "@types/react" "*" + +"@types/react-html-parser@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/react-html-parser/-/react-html-parser-2.0.1.tgz#2d9002ac5bf1adf9aff8eae77ace5488bd78c98d" + integrity sha512-Lyw0AtG3gahw78CX2pzmzhKaoZCfJNzzuhhPsFVhzFrylMv8NaCmzYaPKglMv3RRHpwBbHuMOkVx0HiwGZKgSA== + dependencies: + "@types/htmlparser2" "*" + "@types/react" "*" + +"@types/react-overlays@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@types/react-overlays/-/react-overlays-1.1.3.tgz#fb97081cbf506917e358f0523b34fed14e2de2f7" + integrity sha512-oOq5NWbyfNz2w2sKvjkHdvGQSMA+VDVfI5UOfGPR0wkik2welad1RDVnVgH15jKf58jrZNBa1Ee4SVBgCGFxCg== + dependencies: + "@types/react" "*" + "@types/react-transition-group" "*" + +"@types/react-router-dom@*", "@types/react-router-dom@^4.3.5": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.5.tgz#72f229967690c890d00f96e6b85e9ee5780db31f" + integrity sha512-eFajSUASYbPHg2BDM1G8Btx+YqGgvROPIg6sBhl3O4kbDdYXdFdfrgQFf/pcBuQVObjfT9AL/dd15jilR5DIEA== + dependencies: + "@types/history" "*" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router-hash-link@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/react-router-hash-link/-/react-router-hash-link-1.2.1.tgz#fba7dc351cef2985791023018b7a5dbd0653c843" + integrity sha512-jdzPGE8jFGq7fHUpPaKrJvLW1Yhoe5MQCrmgeesC+eSLseMj3cGCTYMDA4BNWG8JQmwO8NTYt/oT3uBZ77pmBA== + dependencies: + "@types/react" "*" + "@types/react-router-dom" "*" + +"@types/react-router@*": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.0.3.tgz#855a1606e62de3f4d69ea34fb3c0e50e98e964d5" + integrity sha512-j2Gge5cvxca+5lK9wxovmGPgpVJMwjyu5lTA/Cd6fLGoPq7FXcUE1jFkEdxeyqGGz8VfHYSHCn5Lcn24BzaNKA== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-transition-group@*": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.2.2.tgz#8c851c4598a23a3a34173069fb4c5c9e41c02e3f" + integrity sha512-YfoaTNqBwbIqpiJ5NNfxfgg5kyFP1Hqf/jqBtSWNv0E+EkkxmN+3VD6U2fu86tlQvdAc1o0SdWhnWFwcRMTn9A== dependencies: "@types/react" "*" @@ -1223,10 +1337,22 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== -"@types/yargs@^12.0.2", "@types/yargs@^12.0.9": - version "12.0.12" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" - integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw== +"@types/xregexp@^3.0.30": + version "3.0.30" + resolved "https://registry.yarnpkg.com/@types/xregexp/-/xregexp-3.0.30.tgz#333d550467dd27ef989f375629f8f279a97cee39" + integrity sha512-u1dpabg81Rd660bYebOqMXO0+E63H1hxunPAWGebNb7TpxqZYe9YaVLgkkj6ZnzLs3yLumtVB956o8u8OZdhXw== + +"@types/yargs-parser@*": + version "13.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.0.0.tgz#453743c5bbf9f1bed61d959baab5b06be029b2d0" + integrity sha512-wBlsw+8n21e6eTd4yVv8YD/E3xq0O6nNnJIquutAsFGE7EyMKz7W6RNT6BRu1SmdgmlCZ9tb0X+j+D6HGr8pZw== + +"@types/yargs@^13.0.0": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.2.tgz#a64674fc0149574ecd90ba746e932b5a5f7b3653" + integrity sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ== + dependencies: + "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@1.13.0": version "1.13.0" @@ -1448,10 +1574,10 @@ acorn-globals@^4.1.0, acorn-globals@^4.3.0: acorn "^6.0.1" acorn-walk "^6.0.1" -acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn-jsx@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" + integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== acorn-walk@^6.0.1: version "6.2.0" @@ -1463,16 +1589,33 @@ acorn@^5.5.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.7, acorn@^6.2.1: +acorn@^6.0.1, acorn@^6.0.4, acorn@^6.2.1: version "6.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== -address@1.1.0, address@^1.0.1: +acorn@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" + integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ== + +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.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/address/-/address-1.1.0.tgz#ef8e047847fcd2c5b6f50c16965f924fd99fe709" integrity sha512-4diPfzWbLEIElVG4AnqP+00SULlPzNuyJFNnmMrLgyaxG6tZXJ1sn7mjBu4fHrJE+Yp/jgylOweJn2xsLMFggQ== +address@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + adjust-sourcemap-loader@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz#6471143af75ec02334b219f54bc7970c52fb29a4" @@ -1519,13 +1662,6 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228" - integrity sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q== - dependencies: - type-fest "^0.5.2" - ansi-html@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -1674,7 +1810,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@~2.0.6: +asap@~2.0.3, asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -1740,6 +1876,11 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async-lock@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.2.2.tgz#480bd51e4b7ffd4debbd4973763718ec9acb9a9e" + integrity sha512-uczz62z2fMWOFbyo6rG4NlV2SdxugJT6sZA2QcfB1XaSjEiOh8CuOb/TttyMnYQCda6nkWecJe465tGQDPJiKw== + async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -1778,6 +1919,14 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +axios@^0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + axobject-query@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" @@ -1813,16 +1962,16 @@ babel-extract-comments@^1.0.0: dependencies: babylon "^6.18.0" -babel-jest@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589" - integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw== +babel-jest@^24.8.0, babel-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" + integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== dependencies: - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" "@types/babel__core" "^7.1.0" babel-plugin-istanbul "^5.1.0" - babel-preset-jest "^24.6.0" + babel-preset-jest "^24.9.0" chalk "^2.4.2" slash "^2.0.0" @@ -1853,10 +2002,10 @@ babel-plugin-istanbul@^5.1.0: istanbul-lib-instrument "^3.3.0" test-exclude "^5.2.3" -babel-plugin-jest-hoist@^24.6.0: - version "24.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz#f7f7f7ad150ee96d7a5e8e2c5da8319579e78019" - integrity sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w== +babel-plugin-jest-hoist@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756" + integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw== dependencies: "@types/babel__traverse" "^7.0.6" @@ -1892,13 +2041,13 @@ babel-plugin-transform-react-remove-prop-types@0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== -babel-preset-jest@^24.6.0: - version "24.6.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz#66f06136eefce87797539c0d63f1769cc3915984" - integrity sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw== +babel-preset-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" + integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg== dependencies: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^24.6.0" + babel-plugin-jest-hoist "^24.9.0" babel-preset-react-app@^9.0.1: version "9.0.1" @@ -1922,7 +2071,7 @@ babel-preset-react-app@^9.0.1: babel-plugin-macros "2.6.1" babel-plugin-transform-react-remove-prop-types "0.4.24" -babel-runtime@^6.26.0: +babel-runtime@6.x, 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= @@ -2179,9 +2328,9 @@ bytes@3.1.0: integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== cacache@^12.0.2: - version "12.0.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.2.tgz#8db03205e36089a3df6954c66ce92541441ac46c" - integrity sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg== + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== dependencies: bluebird "^3.5.5" chownr "^1.1.1" @@ -2324,9 +2473,9 @@ chardet@^0.7.0: integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4: - version "2.1.6" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" - integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -2377,6 +2526,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@2.x, classnames@^2.2.6: + 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" @@ -2391,13 +2545,6 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -2412,6 +2559,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -2432,6 +2588,11 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -2524,11 +2685,23 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +component-classes@^1.2.5: + 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.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== +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= + compose-function@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f" @@ -2632,7 +2805,7 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.0: +cookie@0.4.0, cookie@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== @@ -2667,7 +2840,7 @@ core-js@3.1.4: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07" integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ== -core-js@^2.4.0: +core-js@^2.4.0, core-js@^2.6.5: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== @@ -2718,6 +2891,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-react-context@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c" + integrity sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw== + dependencies: + gud "^1.0.0" + warning "^4.0.3" + cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -2746,6 +2927,14 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +css-animation@^1.3.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/css-animation/-/css-animation-1.6.1.tgz#162064a3b0d51f958b7ff37b3d6d4de18e17039e" + integrity sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog== + dependencies: + babel-runtime "6.x" + component-classes "^1.2.5" + css-blank-pseudo@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" @@ -3012,6 +3201,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6. dependencies: ms "2.0.0" +debug@=3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -3158,10 +3354,10 @@ detect-port-alt@1.1.6: address "^1.0.1" debug "^2.6.0" -diff-sequences@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975" - integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw== +diff-sequences@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" + integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== diffie-hellman@^5.0.0: version "5.0.3" @@ -3229,6 +3425,13 @@ dom-converter@^0.2: dependencies: utila "~0.4" +dom-helpers@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" + integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== + dependencies: + "@babel/runtime" "^7.1.2" + dom-serializer@0: version "0.2.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" @@ -3328,9 +3531,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.191: - version "1.3.225" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.225.tgz#c6786475b5eb5f491ade01a78b82ba2c5bfdf72b" - integrity sha512-7W/L3jw7HYE+tUPbcVOGBmnSrlUmyZ/Uyg24QS7Vx0a9KodtNrN0r0Q/LyGHrcYMtw2rv7E49F/vTXwlV/fuaA== + version "1.3.241" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.241.tgz#859dc49ab7f90773ed698767372d384190f60cb1" + integrity sha512-Gb9E6nWZlbgjDDNe5cAvMJixtn79krNJ70EDpq/M10lkGo7PGtBUe7Y0CYVHsBScRwi6ybCS+YetXAN9ysAHDg== elliptic@^6.0.0: version "6.5.0" @@ -3350,11 +3553,6 @@ emoji-regex@^7.0.1, emoji-regex@^7.0.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -3391,7 +3589,7 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== -errno@^0.1.3, errno@~0.1.7: +errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== @@ -3591,22 +3789,22 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c" - integrity sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ== +eslint-utils@^1.3.1, eslint-utils@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" + integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== dependencies: eslint-visitor-keys "^1.0.0" -eslint-visitor-keys@^1.0.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== eslint@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.1.0.tgz#06438a4a278b1d84fb107d24eaaa35471986e646" - integrity sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ== + version "6.2.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.2.tgz#03298280e7750d81fcd31431f3d333e43d93f24f" + integrity sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -3615,9 +3813,9 @@ eslint@^6.1.0: debug "^4.0.1" doctrine "^3.0.0" eslint-scope "^5.0.0" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^6.0.0" + eslint-utils "^1.4.2" + eslint-visitor-keys "^1.1.0" + espree "^6.1.1" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -3646,14 +3844,14 @@ eslint@^6.1.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.0.0.tgz#716fc1f5a245ef5b9a7fdb1d7b0d3f02322e75f6" - integrity sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q== +espree@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de" + integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ== dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" + acorn "^7.0.0" + acorn-jsx "^5.0.2" + eslint-visitor-keys "^1.1.0" esprima@^3.1.3: version "3.1.3" @@ -3680,9 +3878,9 @@ esrecurse@^4.1.0: estraverse "^4.1.0" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" @@ -3737,6 +3935,11 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +exenv@^1.2.0, exenv@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50= + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -3755,17 +3958,17 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.8.0.tgz#471f8ec256b7b6129ca2524b2a62f030df38718d" - integrity sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA== +expect@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" + integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" ansi-styles "^3.2.0" - jest-get-type "^24.8.0" - jest-matcher-utils "^24.8.0" - jest-message-util "^24.8.0" - jest-regex-util "^24.3.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-regex-util "^24.9.0" express@^4.16.2: version "4.17.1" @@ -3916,13 +4119,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" - integrity sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -4033,6 +4229,13 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + follow-redirects@^1.0.0: version "1.7.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" @@ -4192,6 +4395,11 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-own-enumerable-property-symbols@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" @@ -4294,15 +4502,20 @@ globby@^6.1.0: pinkie-promise "^2.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.1" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.1.tgz#1c1f0c364882c868f5bff6512146328336a11b1d" - integrity sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== + gzip-size@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" @@ -4431,6 +4644,18 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== +history@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca" + integrity sha512-H2DkjCjXf0Op9OAr6nJ56fcRkTSNrUiv41vNJ6IswJjif6wlpZK0BTfFbi7qK9dXLSYZxkq5lBsj3vUjlYBYZA== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^2.2.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^0.4.0" + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4440,6 +4665,13 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" + integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.4" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" @@ -4507,7 +4739,7 @@ html-webpack-plugin@4.0.0-beta.5: tapable "^1.1.0" util.promisify "1.0.0" -htmlparser2@^3.3.0: +htmlparser2@^3.3.0, htmlparser2@^3.9.0: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== @@ -4647,6 +4879,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +image-size@~0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= + immer@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" @@ -4753,21 +4990,21 @@ inquirer@6.5.0: through "^2.3.6" inquirer@^6.4.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.1.tgz#8bfb7a5ac02dac6ff641ac4c5ff17da112fcdb42" - integrity sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw== + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== dependencies: - ansi-escapes "^4.2.1" + ansi-escapes "^3.2.0" chalk "^2.4.2" - cli-cursor "^3.1.0" + cli-cursor "^2.1.0" cli-width "^2.0.0" external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" run-async "^2.2.0" rxjs "^6.4.0" - string-width "^4.1.0" + string-width "^2.1.0" strip-ansi "^5.1.0" through "^2.3.6" @@ -4852,6 +5089,11 @@ is-buffer@^1.0.2, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -4947,11 +5189,6 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - is-generator-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" @@ -5070,6 +5307,11 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -5135,91 +5377,91 @@ istanbul-lib-source-maps@^3.0.1: rimraf "^2.6.3" source-map "^0.6.1" -istanbul-reports@^2.1.1: +istanbul-reports@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== dependencies: handlebars "^4.1.2" -jest-changed-files@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b" - integrity sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug== +jest-changed-files@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" + integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" execa "^1.0.0" throat "^4.0.0" jest-cli@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.8.0.tgz#b075ac914492ed114fa338ade7362a301693e989" - integrity sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA== + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af" + integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg== dependencies: - "@jest/core" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/core" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" exit "^0.1.2" import-local "^2.0.0" is-ci "^2.0.0" - jest-config "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" + jest-config "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" prompts "^2.0.1" realpath-native "^1.1.0" - yargs "^12.0.2" + yargs "^13.3.0" -jest-config@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.8.0.tgz#77db3d265a6f726294687cbbccc36f8a76ee0f4f" - integrity sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw== +jest-config@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5" + integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^24.8.0" - "@jest/types" "^24.8.0" - babel-jest "^24.8.0" + "@jest/test-sequencer" "^24.9.0" + "@jest/types" "^24.9.0" + babel-jest "^24.9.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.8.0" - jest-environment-node "^24.8.0" - jest-get-type "^24.8.0" - jest-jasmine2 "^24.8.0" + jest-environment-jsdom "^24.9.0" + jest-environment-node "^24.9.0" + jest-get-type "^24.9.0" + jest-jasmine2 "^24.9.0" jest-regex-util "^24.3.0" - jest-resolve "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" + jest-resolve "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" micromatch "^3.1.10" - pretty-format "^24.8.0" + pretty-format "^24.9.0" realpath-native "^1.1.0" -jest-diff@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172" - integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g== +jest-diff@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" + integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== dependencies: chalk "^2.0.1" - diff-sequences "^24.3.0" - jest-get-type "^24.8.0" - pretty-format "^24.8.0" + diff-sequences "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" jest-docblock@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.3.0.tgz#b9c32dac70f72e4464520d2ba4aec02ab14db5dd" - integrity sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg== + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" + integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA== dependencies: detect-newline "^2.1.0" -jest-each@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775" - integrity sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA== +jest-each@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05" + integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" - jest-get-type "^24.8.0" - jest-util "^24.8.0" - pretty-format "^24.8.0" + jest-get-type "^24.9.0" + jest-util "^24.9.0" + pretty-format "^24.9.0" jest-environment-jsdom-fourteen@0.1.0: version "0.1.0" @@ -5230,133 +5472,134 @@ jest-environment-jsdom-fourteen@0.1.0: jest-util "^24.5.0" jsdom "^14.0.0" -jest-environment-jsdom@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz#300f6949a146cabe1c9357ad9e9ecf9f43f38857" - integrity sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ== +jest-environment-jsdom@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b" + integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA== dependencies: - "@jest/environment" "^24.8.0" - "@jest/fake-timers" "^24.8.0" - "@jest/types" "^24.8.0" - jest-mock "^24.8.0" - jest-util "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + jest-util "^24.9.0" jsdom "^11.5.1" -jest-environment-node@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.8.0.tgz#d3f726ba8bc53087a60e7a84ca08883a4c892231" - integrity sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q== +jest-environment-node@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3" + integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA== dependencies: - "@jest/environment" "^24.8.0" - "@jest/fake-timers" "^24.8.0" - "@jest/types" "^24.8.0" - jest-mock "^24.8.0" - jest-util "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + jest-util "^24.9.0" -jest-get-type@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc" - integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ== +jest-get-type@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" + integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== -jest-haste-map@^24.8.0: - version "24.8.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.1.tgz#f39cc1d2b1d907e014165b4bd5a957afcb992982" - integrity sha512-SwaxMGVdAZk3ernAx2Uv2sorA7jm3Kx+lR0grp6rMmnY06Kn/urtKx1LPN2mGTea4fCT38impYT28FfcLUhX0g== +jest-haste-map@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" + integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" anymatch "^2.0.0" fb-watchman "^2.0.0" graceful-fs "^4.1.15" invariant "^2.2.4" - jest-serializer "^24.4.0" - jest-util "^24.8.0" - jest-worker "^24.6.0" + jest-serializer "^24.9.0" + jest-util "^24.9.0" + jest-worker "^24.9.0" micromatch "^3.1.10" sane "^4.0.3" walker "^1.0.7" optionalDependencies: fsevents "^1.2.7" -jest-jasmine2@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz#a9c7e14c83dd77d8b15e820549ce8987cc8cd898" - integrity sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong== +jest-jasmine2@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0" + integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.8.0" + expect "^24.9.0" is-generator-fn "^2.0.0" - jest-each "^24.8.0" - jest-matcher-utils "^24.8.0" - jest-message-util "^24.8.0" - jest-runtime "^24.8.0" - jest-snapshot "^24.8.0" - jest-util "^24.8.0" - pretty-format "^24.8.0" + jest-each "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-runtime "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + pretty-format "^24.9.0" throat "^4.0.0" -jest-leak-detector@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz#c0086384e1f650c2d8348095df769f29b48e6980" - integrity sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g== +jest-leak-detector@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a" + integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA== dependencies: - pretty-format "^24.8.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" -jest-matcher-utils@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495" - integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw== +jest-matcher-utils@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" + integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== dependencies: chalk "^2.0.1" - jest-diff "^24.8.0" - jest-get-type "^24.8.0" - pretty-format "^24.8.0" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" -jest-message-util@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b" - integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g== +jest-message-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" + integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" "@types/stack-utils" "^1.0.1" chalk "^2.0.1" micromatch "^3.1.10" slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.5.0, jest-mock@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56" - integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A== +jest-mock@^24.5.0, jest-mock@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" + integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" jest-pnp-resolver@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== -jest-regex-util@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36" - integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== +jest-regex-util@^24.3.0, jest-regex-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" + integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== -jest-resolve-dependencies@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz#19eec3241f2045d3f990dba331d0d7526acff8e0" - integrity sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw== +jest-resolve-dependencies@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab" + integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" jest-regex-util "^24.3.0" - jest-snapshot "^24.8.0" + jest-snapshot "^24.9.0" -jest-resolve@24.8.0, jest-resolve@^24.8.0: +jest-resolve@24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.8.0.tgz#84b8e5408c1f6a11539793e2b5feb1b6e722439f" integrity sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw== @@ -5367,93 +5610,105 @@ jest-resolve@24.8.0, jest-resolve@^24.8.0: jest-pnp-resolver "^1.2.1" realpath-native "^1.1.0" -jest-runner@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.8.0.tgz#4f9ae07b767db27b740d7deffad0cf67ccb4c5bb" - integrity sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow== +jest-resolve@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321" + integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ== + dependencies: + "@jest/types" "^24.9.0" + browser-resolve "^1.11.3" + chalk "^2.0.1" + jest-pnp-resolver "^1.2.1" + realpath-native "^1.1.0" + +jest-runner@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42" + integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg== dependencies: "@jest/console" "^24.7.1" - "@jest/environment" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.4.2" exit "^0.1.2" graceful-fs "^4.1.15" - jest-config "^24.8.0" + jest-config "^24.9.0" jest-docblock "^24.3.0" - jest-haste-map "^24.8.0" - jest-jasmine2 "^24.8.0" - jest-leak-detector "^24.8.0" - jest-message-util "^24.8.0" - jest-resolve "^24.8.0" - jest-runtime "^24.8.0" - jest-util "^24.8.0" + jest-haste-map "^24.9.0" + jest-jasmine2 "^24.9.0" + jest-leak-detector "^24.9.0" + jest-message-util "^24.9.0" + jest-resolve "^24.9.0" + jest-runtime "^24.9.0" + jest-util "^24.9.0" jest-worker "^24.6.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.8.0.tgz#05f94d5b05c21f6dc54e427cd2e4980923350620" - integrity sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA== +jest-runtime@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac" + integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw== dependencies: "@jest/console" "^24.7.1" - "@jest/environment" "^24.8.0" + "@jest/environment" "^24.9.0" "@jest/source-map" "^24.3.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" - "@types/yargs" "^12.0.2" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/yargs" "^13.0.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.1.15" - jest-config "^24.8.0" - jest-haste-map "^24.8.0" - jest-message-util "^24.8.0" - jest-mock "^24.8.0" + jest-config "^24.9.0" + jest-haste-map "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" jest-regex-util "^24.3.0" - jest-resolve "^24.8.0" - jest-snapshot "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" + jest-resolve "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" realpath-native "^1.1.0" slash "^2.0.0" strip-bom "^3.0.0" - yargs "^12.0.2" + yargs "^13.3.0" -jest-serializer@^24.4.0: - version "24.4.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" - integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== +jest-serializer@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" + integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== -jest-snapshot@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.8.0.tgz#3bec6a59da2ff7bc7d097a853fb67f9d415cb7c6" - integrity sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg== +jest-snapshot@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba" + integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" - expect "^24.8.0" - jest-diff "^24.8.0" - jest-matcher-utils "^24.8.0" - jest-message-util "^24.8.0" - jest-resolve "^24.8.0" + expect "^24.9.0" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-resolve "^24.9.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.8.0" - semver "^5.5.0" + pretty-format "^24.9.0" + semver "^6.2.0" -jest-util@^24.5.0, jest-util@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1" - integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA== +jest-util@^24.5.0, jest-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" + integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== dependencies: - "@jest/console" "^24.7.1" - "@jest/fake-timers" "^24.8.0" - "@jest/source-map" "^24.3.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/console" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/source-map" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" callsites "^3.0.0" chalk "^2.0.1" graceful-fs "^4.1.15" @@ -5462,17 +5717,17 @@ jest-util@^24.5.0, jest-util@^24.8.0: slash "^2.0.0" source-map "^0.6.0" -jest-validate@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.8.0.tgz#624c41533e6dfe356ffadc6e2423a35c2d3b4849" - integrity sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA== +jest-validate@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab" + integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ== dependencies: - "@jest/types" "^24.8.0" - camelcase "^5.0.0" + "@jest/types" "^24.9.0" + camelcase "^5.3.1" chalk "^2.0.1" - jest-get-type "^24.8.0" - leven "^2.1.0" - pretty-format "^24.8.0" + jest-get-type "^24.9.0" + leven "^3.1.0" + pretty-format "^24.9.0" jest-watch-typeahead@0.3.1: version "0.3.1" @@ -5486,25 +5741,25 @@ jest-watch-typeahead@0.3.1: string-length "^2.0.0" strip-ansi "^5.0.0" -jest-watcher@^24.3.0, jest-watcher@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.8.0.tgz#58d49915ceddd2de85e238f6213cef1c93715de4" - integrity sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw== +jest-watcher@^24.3.0, jest-watcher@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b" + integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw== dependencies: - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" - "@types/yargs" "^12.0.9" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/yargs" "^13.0.0" ansi-escapes "^3.0.0" chalk "^2.0.1" - jest-util "^24.8.0" + jest-util "^24.9.0" string-length "^2.0.0" -jest-worker@^24.6.0: - version "24.6.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3" - integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ== +jest-worker@^24.6.0, jest-worker@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" + integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== dependencies: - merge-stream "^1.0.1" + merge-stream "^2.0.0" supports-color "^6.1.0" jest@24.8.0: @@ -5769,10 +6024,26 @@ left-pad@^1.3.0: resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== -leven@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= +less@^3.10.3: + version "3.10.3" + resolved "https://registry.yarnpkg.com/less/-/less-3.10.3.tgz#417a0975d5eeecc52cff4bcfa3c09d35781e6792" + integrity sha512-vz32vqfgmoxF1h3K4J+yKCtajH0PWmjkIFgbs5d78E/c/e+UQTnI+lWK+1eQRE95PXM2mC3rJlLSSP9VQHnaow== + dependencies: + clone "^2.1.2" + optionalDependencies: + errno "^0.1.1" + graceful-fs "^4.1.2" + image-size "~0.5.0" + mime "^1.4.1" + mkdirp "^0.5.0" + promise "^7.1.1" + request "^2.83.0" + source-map "~0.6.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.3.0, levn@~0.3.0: version "0.3.0" @@ -5840,11 +6111,35 @@ 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" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +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" @@ -5880,7 +6175,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5: +"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -5890,7 +6185,12 @@ loglevel@^1.4.1: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.3.tgz#77f2eb64be55a404c9fd04ad16d57c1d6d6b1280" integrity sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +lokijs@^1.5.7: + version "1.5.7" + resolved "https://registry.yarnpkg.com/lokijs/-/lokijs-1.5.7.tgz#3bbeb5c2dbffebd78d035bac82c7c4e6055870f0" + integrity sha512-2SqUV6JH4f15Z5/7LVsyadSUwHhZppxhujgy/VhVqiRYMGt5oaocb7fV/3JGjHJ6rTuEIajnpTLGRz9cJW/c3g== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -6003,12 +6303,10 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= -merge-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.2.3: version "1.2.4" @@ -6064,7 +6362,7 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: dependencies: mime-db "1.40.0" -mime@1.6.0: +mime@1.6.0, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -6079,11 +6377,20 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-fn@^2.0.0, mimic-fn@^2.1.0: +mimic-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mini-create-react-context@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189" + integrity sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw== + dependencies: + "@babel/runtime" "^7.4.0" + gud "^1.0.0" + tiny-warning "^1.0.2" + mini-css-extract-plugin@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz#ac0059b02b9692515a637115b0cc9fed3a35c7b0" @@ -6126,9 +6433,9 @@ minimist@~0.0.1: integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.4.0.tgz#38f0af94f42fb6f34d3d7d82a90e2c99cd3ff485" + integrity sha512-6PmOuSP4NnZXzs2z6rbwzLJu/c5gdzYg1mRI/WIYdx45iiX7T+a4esOzavD6V/KmBzAaopFSTZPZcUx73bqKWA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -6179,6 +6486,11 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +moment@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" + integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -6224,11 +6536,6 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nan@^2.12.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -6336,10 +6643,10 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^5.2.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.1.tgz#7c0192cc63aedb25cd99619174daa27902b10903" - integrity sha512-p52B+onAEHKW1OF9MGO/S7k/ahGEHfhP5/tvwYzog/5XLYOd8ZuD6vdNZdUuWMONRnKPneXV43v3s6Snx1wsCQ== +node-notifier@^5.4.2: + version "5.4.3" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" + integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== dependencies: growly "^1.3.0" is-wsl "^1.1.0" @@ -6364,9 +6671,9 @@ node-pre-gyp@^0.12.0: tar "^4" node-releases@^1.1.25: - version "1.1.27" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.27.tgz#b19ec8add2afe9a826a99dceccc516104c1edaf4" - integrity sha512-9iXUqHKSGo6ph/tdXVbHFbhRVQln4ZDTIBJCzsa90HimnBYc5jw8RWYt4wBYFHehGyC3koIz5O4mb2fHrbPOuA== + version "1.1.28" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.28.tgz#503c3c70d0e4732b84e7aaa2925fbdde10482d4a" + integrity sha512-AQw4emh6iSXnCpDiFe0phYcThiccmkNWMZnFZ+lDJjAP8J0m2fVd59duvUUyuTirQOhIAajTFkzG6FHCLBO59g== dependencies: semver "^5.3.0" @@ -6467,7 +6774,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= @@ -6589,13 +6896,6 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - open@^6.3.0: version "6.4.0" resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" @@ -6707,9 +7007,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" - integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== dependencies: p-try "^2.0.0" @@ -6869,6 +7169,13 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + integrity sha1-Wf3g9DW62suhA6hOnTvGTpa5k30= + dependencies: + isarray "0.0.1" + path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" @@ -6973,10 +7280,15 @@ pnp-webpack-plugin@1.5.0: dependencies: ts-pnp "^1.1.2" +popper.js@^1.14.4: + version "1.15.0" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2" + integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA== + portfinder@^1.0.9: - version "1.0.21" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.21.tgz#60e1397b95ac170749db70034ece306b9a27e324" - integrity sha512-ESabpDCzmBS3ekHbmpAIiESq3udRsCBGiBZLsC+HgBKv2ezb0R4oG+7RnYEVZ/ZCfhel5Tx3UzdNWA0Lox2QCA== + version "1.0.23" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.23.tgz#894db4bcc5daf02b6614517ce89cd21a38226b82" + integrity sha512-B729mL/uLklxtxuiJKfQ84WPxNw5a7Yhx3geQZdcA4GjNjZSTSSMMWyoennMVnTWSmAR0lMdzWYN0JLnHrg1KQ== dependencies: async "^1.5.2" debug "^2.2.0" @@ -7665,12 +7977,12 @@ pretty-error@^2.1.1: renderkid "^2.0.1" utila "~0.4" -pretty-format@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" - integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw== +pretty-format@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" + integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" react-is "^16.8.4" @@ -7707,6 +8019,13 @@ promise@8.0.3: dependencies: asap "~2.0.6" +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + prompts@^2.0.1: version "2.2.1" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.2.1.tgz#f901dd2a2dfee080359c0e20059b24188d75ad35" @@ -7715,7 +8034,15 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.3" -prop-types@^15.6.2, prop-types@^15.7.2: +prop-types-extra@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.0.tgz#32609910ea2dcf190366bacd3490d5a6412a605f" + integrity sha512-QFyuDxvMipmIVKD2TwxLVPzMnO4e5oOf1vr3tJIomL8E7d0lr6phTHd5nkPhFIzTD1idBLLEPeylL9g+rrTzRg== + dependencies: + react-is "^16.3.2" + warning "^3.0.0" + +prop-types@15.x, prop-types@^15.3.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7824,7 +8151,7 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== -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== @@ -7861,6 +8188,51 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc-animate@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/rc-animate/-/rc-animate-2.9.2.tgz#5964767805c886f1bdc7563d3935a74912a0b78f" + integrity sha512-rkJjeJgfbDqVjVX1/QTRfS7PiCq3AnmeYo840cVcuC4pXq4k4yAQMsC2v5BPXXdawC04vnyO4/qHQdbx9ANaiw== + dependencies: + babel-runtime "6.x" + classnames "^2.2.6" + css-animation "^1.3.2" + prop-types "15.x" + raf "^3.4.0" + rc-util "^4.8.0" + react-lifecycles-compat "^3.0.4" + +rc-tree@^3.0.0-alpha.15: + version "3.0.0-alpha.15" + resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-3.0.0-alpha.15.tgz#ffb662e46e510aa40e128cef00fa6a14964eef9a" + integrity sha512-/xHvMQdvwpze0Qs0wOKjD8ZJRyn9mm/CFuIFr56jD90ZCBmzyJ8pFfM2MIq3qrneVNNI9kLU3XSk1J0Ku+4MYw== + dependencies: + classnames "2.x" + prop-types "^15.5.8" + rc-animate "^2.9.2" + rc-util "^4.9.0" + rc-virtual-list "^0.0.0-alpha.18" + react-lifecycles-compat "^3.0.4" + warning "^4.0.3" + +rc-util@^4.8.0, rc-util@^4.9.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.11.0.tgz#cf437dcff74ca08a8565ae14f0368acb3a650796" + integrity sha512-nB29kXOXsSVjBkWfH+Z1GVh6tRg7XGZtZ0Yfie+OI0stCDixGQ1cPrS6iYxlg+AV2St6COCK5MFrCmpTgghh0w== + dependencies: + add-dom-event-listener "^1.1.0" + babel-runtime "6.x" + prop-types "^15.5.10" + react-lifecycles-compat "^3.0.4" + shallowequal "^0.2.2" + +rc-virtual-list@^0.0.0-alpha.18: + version "0.0.0-alpha.23" + resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-0.0.0-alpha.23.tgz#d22fbcba9a4b359f4e099b5d2d0557c6c15531a0" + integrity sha512-s4pjXAarPvGlWxyKc+UKdsy25Ocfkx/OU9ds84KMB5D//aq+AFKpIhNvZd7iylCk/Zh3wxvoScntuh0wWV+h9g== + dependencies: + classnames "^2.2.6" + rc-util "^4.8.0" + rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -7883,6 +8255,20 @@ react-app-polyfill@^1.0.2: regenerator-runtime "0.13.3" whatwg-fetch "3.0.0" +react-context-toolbox@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/react-context-toolbox/-/react-context-toolbox-2.0.2.tgz#35637287cb23f801e6ed802c2bb7a97e1f04e3fb" + integrity sha512-tY4j0imkYC3n5ZlYSgFkaw7fmlCp3IoQQ6DxpqeNHzcD0hf+6V+/HeJxviLUZ1Rv1Yn3N3xyO2EhkkZwHn0m1A== + +react-cookie@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/react-cookie/-/react-cookie-4.0.1.tgz#c21b2c30a5cacf320b45338fa3dcaf76d9fe9c2c" + integrity sha512-h61qAtSXvfjNa81h3XCFdFoyFaF+nb7gjK0cxQuTiCPMPAe50D950FjLCFhaIfSpAesQFAmkxf5XFpWoEVBDAA== + dependencies: + "@types/hoist-non-react-statics" "^3.0.1" + hoist-non-react-statics "^3.0.0" + universal-cookie "^4.0.0" + react-dev-utils@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.0.3.tgz#7607455587abb84599451460eb37cef0b684131a" @@ -7914,7 +8300,7 @@ react-dev-utils@^9.0.3: strip-ansi "5.2.0" text-table "0.2.0" -react-dom@16.9.0: +react-dom@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962" integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ== @@ -7929,11 +8315,123 @@ react-error-overlay@^6.0.1: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.1.tgz#b8d3cf9bb991c02883225c48044cb3ee20413e0f" integrity sha512-V9yoTr6MeZXPPd4nV/05eCBvGH9cGzc52FN8fs0O0TVQ3HYYf1n7EgZVtHbldRq5xU9zEzoXIITjYNIfxDDdUw== -react-is@^16.8.1, react-is@^16.8.4: +react-fast-compare@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + +react-ga@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.6.0.tgz#c3fe830ead2ad25117e1d33280d9698de9b28496" + integrity sha512-GWHBWZDFjDGMkIk1LzroIn0mNTygKw3adXuqvGvheFZvlbpqMPbHsQsTdQBIxRRdXGQM/Zq+dQLRPKbwIHMTaw== + +react-helmet@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.1.tgz#16a7192fdd09951f8e0fe22ffccbf9bb3e591ffa" + integrity sha512-CnwD822LU8NDBnjCpZ4ySh8L6HYyngViTZLfBBb3NjtrpN8m49clH8hidHouq20I51Y6TpCTISCBbqiY5GamwA== + dependencies: + object-assign "^4.1.1" + prop-types "^15.5.4" + react-fast-compare "^2.0.2" + react-side-effect "^1.1.0" + +react-html-parser@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/react-html-parser/-/react-html-parser-2.0.2.tgz#6dbe1ddd2cebc1b34ca15215158021db5fc5685e" + integrity sha512-XeerLwCVjTs3njZcgCOeDUqLgNIt/t+6Jgi5/qPsO/krUWl76kWKXMeVs2LhY2gwM6X378DkhLjur0zUQdpz0g== + dependencies: + htmlparser2 "^3.9.0" + +react-image-lightbox@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/react-image-lightbox/-/react-image-lightbox-5.1.0.tgz#b47b904b027c918acdd9efa94dc0a0ddd8125c86" + integrity sha512-R46QvffoDBscLQgTl4s3kFxVbnP7a+nIh7AXJNS0EXVeDaa6zKDKtIT+jFeEvs+F9oUHtZfenG1NHhTkO4hEOA== + dependencies: + prop-types "^15.6.2" + react-modal "^3.6.1" + +react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.9.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== +react-lifecycles-compat@^3.0.0, 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-modal@^3.6.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.10.1.tgz#ba37927871830c798f51404aa6bc71ff7a5e4c16" + integrity sha512-2DKIfdOc8+WY+SYJ/xf/WBwOYMmNAYAyGkYlc4e1TCs9rk1xY4QBz04hB3UHGcrLChh7ce77rHAe6VPNmuLYsQ== + dependencies: + exenv "^1.2.0" + prop-types "^15.5.10" + react-lifecycles-compat "^3.0.0" + warning "^4.0.3" + +react-overlays@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-1.2.0.tgz#205368eeb0a5fb0b7f9b717fa7a12d518500abdb" + integrity sha512-i/FCV8wR6aRaI+Kz/dpJhOdyx+ah2tN1RhT9InPrexyC4uzf3N4bNayFTGtUeQVacj57j1Mqh1CwV60/5153Iw== + dependencies: + classnames "^2.2.6" + dom-helpers "^3.4.0" + prop-types "^15.6.2" + prop-types-extra "^1.1.0" + react-context-toolbox "^2.0.2" + react-popper "^1.3.2" + uncontrollable "^6.0.0" + warning "^4.0.2" + +react-popper@^1.3.2: + version "1.3.4" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.4.tgz#f0cd3b0d30378e1f663b0d79bcc8614221652ced" + integrity sha512-9AcQB29V+WrBKk6X7p0eojd1f25/oJajVdMZkywIoAV6Ag7hzE1Mhyeup2Q1QnvFRtGQFQvtqfhlEoDAPfKAVA== + dependencies: + "@babel/runtime" "^7.1.2" + create-react-context "^0.3.0" + popper.js "^1.14.4" + prop-types "^15.6.1" + typed-styles "^0.0.7" + warning "^4.0.2" + +react-router-dom@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be" + integrity sha512-zaVHSy7NN0G91/Bz9GD4owex5+eop+KvgbxXsP/O+iW1/Ln+BrJ8QiIR5a6xNPtrdTvLkxqlDClx13QO1uB8CA== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.0.1" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router-hash-link@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/react-router-hash-link/-/react-router-hash-link-1.2.2.tgz#7a0ad5e925d49596d19554de8bc6c554ce4f8099" + integrity sha512-LBthLVHdqPeKDVt3+cFRhy15Z7veikOvdKRZRfyBR2vjqIE7rxn+tKLjb6DOmLm6JpoQVemVDnxQ35RVnEHdQA== + dependencies: + prop-types "^15.6.0" + +react-router@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.0.1.tgz#04ee77df1d1ab6cb8939f9f01ad5702dbadb8b0f" + integrity sha512-EM7suCPNKb1NxcTZ2LEOWFtQBQRQXecLxVpdsP4DW4PbbqYWeRiLyV/Tt1SdCrvT2jcyXAXmVTmzvSzrPR63Bg== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.3.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + react-scripts@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.1.1.tgz#1796bc92447f3a2d3072c3b71ca99f88d099c48d" @@ -7995,7 +8493,30 @@ react-scripts@3.1.1: optionalDependencies: fsevents "2.0.7" -react@16.9.0: +react-side-effect@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d" + integrity sha512-Z2ZJE4p/jIfvUpiUMRydEVpQRf2f8GMHczT6qLcARmX7QRb28JDBTpnM2g/i5y/p7ZDEXYGHWg0RbhikE+hJRw== + dependencies: + exenv "^1.2.1" + shallowequal "^1.0.1" + +react-spinner-material@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/react-spinner-material/-/react-spinner-material-1.1.3.tgz#bdf375089f038028250762007323f026de5f57d5" + integrity sha512-sa9ESbt9/V79jzdxYGfd0i84JG5Nuz6q2wmxqS0Jc8M+J/Rk/aHiA/R2X1ewAwRxysMMDhFG7Altf7FEea1vkg== + +react-twitter-widgets@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/react-twitter-widgets/-/react-twitter-widgets-1.7.1.tgz#60061f37a8c4f361c27f3d1d7ceba98d3cd80a40" + integrity sha512-bAcR/NKqRbVRJav981bHrm2+xka7NA2nQJB6Urtj9BARqP7aeGHPC0CrrC7wdYIaluOqiF8MiTtURqIJjFs2ZA== + dependencies: + exenv "^1.2.1" + lodash "^4.17.4" + prop-types "^15.3.0" + scriptjs "^2.5.8" + +react@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa" integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w== @@ -8126,9 +8647,9 @@ regex-parser@2.2.10: integrity sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA== regexp-tree@^0.1.6: - version "0.1.11" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.11.tgz#c9c7f00fcf722e0a56c7390983a7a63dd6c272f3" - integrity sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg== + version "0.1.12" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.12.tgz#28eaaa6e66eeb3527c15108a3ff740d9e574e420" + integrity sha512-TsXZ8+cv2uxMEkLfgwO0E068gsNMLfuYwMMhiUxf0Kw2Vcgzq93vgl6wIlIYuPmfMqMjfQ9zAporiozqCnwLuQ== regexpp@^2.0.1: version "2.0.1" @@ -8206,7 +8727,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.87.0, request@^2.88.0: +request@^2.83.0, request@^2.87.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -8269,6 +8790,11 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-pathname@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" + integrity sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg== + resolve-url-loader@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.0.tgz#54d8181d33cd1b66a59544d05cadf8e4aa7d37cc" @@ -8310,14 +8836,6 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -8346,13 +8864,20 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -8472,6 +8997,11 @@ schema-utils@^2.0.0, schema-utils@^2.0.1: ajv "^6.1.0" ajv-keywords "^3.1.0" +scriptjs@^2.5.8: + version "2.5.9" + resolved "https://registry.yarnpkg.com/scriptjs/-/scriptjs-2.5.9.tgz#343915cd2ec2ed9bfdde2b9875cd28f59394b35f" + integrity sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg== + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -8494,7 +9024,7 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -8519,9 +9049,9 @@ send@0.17.1: statuses "~1.5.0" serialize-javascript@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" - integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== + version "1.8.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.8.0.tgz#9515fc687232e2321aea1ca7a529476eb34bb480" + integrity sha512-3tHgtF4OzDmeKYj6V9nSyceRS0UJ3C7VqyD2Yj28vC/z2j6jG5FmFGahOKMD9CrglxTm3tETr87jEypaYV8DUg== serve-index@^1.7.2: version "1.9.1" @@ -8601,6 +9131,18 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +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" + +shallowequal@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -8921,7 +9463,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -8930,15 +9472,6 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" - integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^5.2.0" - string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -9077,9 +9610,9 @@ symbol-tree@^3.2.2: integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== table@^5.2.3: - version "5.4.5" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.5.tgz#c8f4ea2d8fee08c0027fac27b0ec0a4fe01dfa42" - integrity sha512-oGa2Hl7CQjfoaogtrOHEJroOcYILTx7BZWLGsJIlzoWmB2zmguhNfPJZsWPKYek/MgCxfco54gEi31d1uN2hFA== + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: ajv "^6.10.2" lodash "^4.17.14" @@ -9120,9 +9653,9 @@ terser-webpack-plugin@1.4.1, terser-webpack-plugin@^1.4.1: worker-farm "^1.7.0" terser@^4.1.2: - version "4.1.4" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.1.4.tgz#4478b6a08bb096a61e793fea1a4434408bab936c" - integrity sha512-+ZwXJvdSwbd60jG0Illav0F06GDJF0R4ydZ21Q3wGAFKoBGyJGo34F63vzJHgvYxc1ukOtIjvwEvl9MkjzM6Pg== + version "4.2.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.2.1.tgz#1052cfe17576c66e7bc70fcc7119f22b155bdac1" + integrity sha512-cGbc5utAcX4a9+2GGVX4DsenG6v0x3glnDi5hx8816X1McEAwPlPgRtXPJzSBsbpILxZ8MQMT0KvArLuE0HP5A== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -9178,6 +9711,16 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= +tiny-invariant@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" + integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== + +tiny-warning@^1.0.0, tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9299,11 +9842,6 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-fest@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" - integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== - type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -9317,6 +9855,11 @@ type@^1.0.1: resolved "https://registry.yarnpkg.com/type/-/type-1.0.3.tgz#16f5d39f27a2d28d86e48f8981859e9d3296c179" integrity sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg== +typed-styles@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" + integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -9343,6 +9886,14 @@ uglify-js@^3.1.4: commander "~2.20.0" source-map "~0.6.1" +uncontrollable@^6.0.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-6.2.3.tgz#e7dba0d746e075122ed178f27ad2354d343196c7" + integrity sha512-VgOAoBU2ptCL2bfTG2Mra0I8i1u6Aq84AFonD5tmCAYSfs3hWvr2Rlw0q2ntoxXTHjcQOmZOh3FKaN+UZVyREQ== + dependencies: + "@babel/runtime" "^7.4.5" + invariant "^2.2.4" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -9400,6 +9951,16 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" +universal-cookie@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-4.0.2.tgz#c3398a64c72ff0c31fecb1ac4966c424e8669c6d" + integrity sha512-n14lhA//lQeYRweP9j9uXsshN9Cs4LunVSnvAGmnA69SofwsjpUU03geaCaPC9LlsH2rkBy99o3zxQyVOldGvA== + dependencies: + "@types/cookie" "^0.3.3" + "@types/object-assign" "^4.0.30" + cookie "^0.4.0" + object-assign "^4.1.1" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -9513,9 +10074,9 @@ utils-merge@1.0.1: integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@^3.0.1, uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== v8-compile-cache@^2.0.3: version "2.1.0" @@ -9530,6 +10091,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +value-equal@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" + integrity sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw== + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -9577,6 +10143,20 @@ walker@^1.0.7, 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" + +warning@^4.0.2, warning@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" @@ -9933,6 +10513,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -9983,6 +10572,13 @@ xregexp@4.0.0: resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg== +xregexp@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.2.4.tgz#02a4aea056d65a42632c02f0233eab8e4d7e57ed" + integrity sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA== + dependencies: + "@babel/runtime-corejs2" "^7.2.0" + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -10005,10 +10601,10 @@ yargs-parser@^10.1.0: dependencies: camelcase "^4.1.0" -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== +yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -10031,20 +10627,18 @@ yargs@12.0.2: y18n "^3.2.1 || ^4.0.0" yargs-parser "^10.1.0" -yargs@^12.0.2: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== +yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: - cliui "^4.0.0" - decamelize "^1.2.0" + cliui "^5.0.0" find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" + get-caller-file "^2.0.1" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^2.0.0" + string-width "^3.0.0" which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" + y18n "^4.0.0" + yargs-parser "^13.1.1"