add latst sources of cbsn platform archive.

This commit is contained in:
Yoshihiro OKUMURA
2019-06-17 15:39:52 +09:00
parent 438a529c3a
commit bbaef3d810
274 changed files with 11130 additions and 528 deletions
+8
View File
@@ -21,3 +21,11 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# database contents
/public/database/items.json
/public/database/file
/src/database/assets/tree.json
/src/database/assets/rankings.json
/src/database/assets/recent-contents.json
/src/forum/assets/forum.json
+87
View File
@@ -0,0 +1,87 @@
<?php
require_once __DIR__.'/config.inc.php';
define('PROTECTOR_SKIP_DOS_CHECK', 1);
define('PROTECTOR_SKIP_FILESCHECKER', 1);
// disable query logger
define('XOOPS_LOGGER_ADDQUERY_DISABLED', true);
// ----
if (!file_exists($mainfile)) {
echo 'ERROR : mainfile.php not found'.PHP_EOL;
exit(1);
}
$xoops_path = '';
$xoops_url = '';
foreach (file($mainfile) as $line) {
if (preg_match('/^\s*define\s*\(\s*[\'"]XOOPS_ROOT_PATH[\'"]\s*,\s*[\'"](.+)[\'"]\)\s*;\s*$/', $line, $matches)) {
$xoops_path = $matches[1];
}
if (preg_match('/^\s*define\s*\(\s*[\'"]XOOPS_URL[\'"]\s*,\s*[\'"](.+)[\'"]\)\s*;\s*$/', $line, $matches)) {
$xoops_url = $matches[1];
}
}
if (isset($method) && 'POST' == strtoupper($method)) {
$method = 'POST';
} else {
$method = 'GET';
}
$_SERVER['HTTP_USER_AGENT'] = 'php-cli';
$_SERVER['REQUEST_METHOD'] = $method;
$_ENV['HTTP_REFERER'] = $xoops_url.'/index.php';
$_SERVER['QUERY_STRING'] = '/index.php';
$_SERVER['REMOTE_ADDR'] = '192.168.0.1';
if (file_exists($xoops_path.'/modules/xoonips/include/common.inc.php')) {
require_once $xoops_path.'/modules/xoonips/include/common.inc.php';
} else {
require_once $xoops_path.'/mainfile.php';
require_once $xoops_path.'/modules/xoonips/condefs.php';
require_once $xoops_path.'/modules/xoonips/include/functions.php';
}
if (defined('XOOPS_DB_PROXY') && XOOPS_DB_PROXY == 1 && 'POST' == $method) {
die('Error: not accept POST request'."\n");
}
error_reporting(E_ALL);
define('MYDUMPTOOL_OUTPUTDIR', __DIR__.'/data');
if (!is_dir(MYDUMPTOOL_OUTPUTDIR)) {
if (!@mkdir(MYDUMPTOOL_OUTPUTDIR)) {
exit('Failed to create output directory : '.MYDUMPTOOL_OUTPUTDIR.PHP_EOL);
}
}
function myDumpToolDecode(&$data)
{
$textutil = xoonips_getutility('text');
foreach ($data as $k => $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);
}
}
function myDumpToolConvertToInt(&$data, $keys, $zerofill = false)
{
foreach ($keys as $key) {
if (isset($data[$key])) {
$data[$key] = '' === $data[$key] ? ($zerofill ? 0 : null) : (int) $data[$key];
}
}
}
function myDumpToolDropColumn(&$data, $keys)
{
foreach ($keys as $key) {
if (isset($data[$key])) {
unset($data[$key]);
}
}
}
+3
View File
@@ -0,0 +1,3 @@
<?php
$mainfile = '/data/www/html/mainfile.php';
+131
View File
@@ -0,0 +1,131 @@
<?php
require_once __DIR__.'/common.inc.php';
$prefix = $xoopsDB->prefix();
$d3forum = 'forum';
$gidGuest = XOOPS_GROUP_ANONYMOUS;
// get anonymous readable categories
$categories = [];
$sql = <<< SQL
SELECT
`c`.*
FROM `${prefix}_${d3forum}_categories` AS `c`
INNER JOIN `${prefix}_${d3forum}_category_access` AS `ca` ON `c`.`cat_id`=`ca`.`cat_id`
WHERE `ca`.`groupid`=${gidGuest}
GROUP BY `c`.`cat_id`
ORDER BY `c`.`cat_order_in_tree` ASC, `c`.`cat_weight` ASC
SQL;
if (!($res = $xoopsDB->query($sql))) {
var_dump($xoopsDB);
exit();
}
while ($row = $xoopsDB->fetchArray($res)) {
myDumpToolDecode($row);
myDumpToolConvertToInt($row, ['cat_id', 'pid', 'cat_topics_count', 'cat_posts_count', 'cat_last_post_id', 'cat_last_post_time', 'cat_topics_count_in_tree', 'cat_posts_count_in_tree', 'cat_last_post_id_in_tree', 'cat_last_post_time_in_tree', 'cat_depth_in_tree', 'cat_order_in_tree', 'cat_weight']);
$row['cat_path_in_tree'] = unserialize($row['cat_path_in_tree']);
$row['cat_options'] = unserialize($row['cat_options']);
$categories[] = $row;
}
$xoopsDB->freeRecordSet($res);
//var_dump($categories);
// get anonymous readable forums
$forums = [];
$sql = <<< SQL
SELECT
`f`.*
FROM `${prefix}_${d3forum}_forums` AS `f`
INNER JOIN `${prefix}_${d3forum}_forum_access` AS `fa` ON `f`.`forum_id`=`fa`.`forum_id`
INNER JOIN `${prefix}_${d3forum}_category_access` AS `ca` ON `f`.`cat_id`=`ca`.`cat_id`
WHERE `fa`.`groupid`=${gidGuest}
AND `ca`.`groupid`=${gidGuest}
GROUP BY `f`.`forum_id`
ORDER BY `f`.`cat_id` ASC, `f`.`forum_weight` ASC
SQL;
if (!($res = $xoopsDB->query($sql))) {
var_dump($xoopsDB);
exit();
}
while ($row = $xoopsDB->fetchArray($res)) {
myDumpToolDecode($row);
myDumpToolConvertToInt($row, ['forum_id', 'cat_id', 'forum_topics_count', 'forum_posts_count', 'forum_last_post_id', 'forum_last_post_time', 'forum_weight'], true);
$row['forum_options'] = unserialize($row['forum_options']);
$forums[] = $row;
}
$xoopsDB->freeRecordSet($res);
//var_dump($forums);
// get anonymous readable topics
$topics = [];
$sql = <<< SQL
SELECT
`t`.*,
`uf`.`name` AS `topic_first_uid_name`, `uf`.`uname` AS `topic_first_uid_uname`,
`ul`.`name` AS `topic_last_uid_name`, `ul`.`uname` AS `topic_last_uid_uname`
FROM `${prefix}_${d3forum}_topics` AS `t`
INNER JOIN `${prefix}_${d3forum}_forums` AS `f` ON `t`.`forum_id`=`f`.`forum_id`
INNER JOIN `${prefix}_${d3forum}_forum_access` AS `fa` ON `f`.`forum_id`=`fa`.`forum_id`
INNER JOIN `${prefix}_${d3forum}_category_access` AS `ca` ON `f`.`cat_id`=`ca`.`cat_id`
LEFT JOIN `${prefix}_users` AS `uf` ON `t`.`topic_first_uid`=`uf`.`uid`
LEFT JOIN `${prefix}_users` AS `ul` ON `t`.`topic_last_uid`=`ul`.`uid`
WHERE `fa`.`groupid`=${gidGuest}
AND `ca`.`groupid`=${gidGuest}
GROUP BY `t`.`topic_id`
ORDER BY `t`.`forum_id` ASC, `t`.`topic_id` ASC
SQL;
if (!($res = $xoopsDB->query($sql))) {
var_dump($xoopsDB);
exit();
}
while ($row = $xoopsDB->fetchArray($res)) {
myDumpToolDecode($row);
myDumpToolConvertToInt($row, ['topic_id', 'forum_id', 'topic_first_uid', 'topic_first_post_id', 'topic_first_post_time', 'topic_last_uid', 'topic_last_post_id', 'topic_last_post_time', 'topic_views', 'topic_posts_count', 'topic_locked', 'topic_sticky', 'topic_solved', 'topic_invisible', 'topic_votes_sum', 'topic_votes_count'], true);
$topics[] = $row;
}
$xoopsDB->freeRecordSet($res);
//var_dump($topics);
// get anonymous readable posts
$posts = [];
$sql = <<< SQL
SELECT
`p`.*,
`u`.`name` AS `uid_name`, `u`.`uname` AS `uid_uname`, `u`.`rank` AS `uid_rank`, `u`.`posts` AS `uid_posts`
FROM `${prefix}_${d3forum}_posts` AS `p`
INNER JOIN `${prefix}_${d3forum}_topics` AS `t` ON `p`.`topic_id`=`t`.`topic_id`
INNER JOIN `${prefix}_${d3forum}_forums` AS `f` ON `t`.`forum_id`=`f`.`forum_id`
INNER JOIN `${prefix}_${d3forum}_forum_access` AS `fa` ON `f`.`forum_id`=`fa`.`forum_id`
INNER JOIN `${prefix}_${d3forum}_category_access` AS `ca` ON `f`.`cat_id`=`ca`.`cat_id`
LEFT JOIN `${prefix}_users` AS `u` ON `p`.`uid`=`u`.`uid`
WHERE `fa`.`groupid`=${gidGuest}
AND `ca`.`groupid`=${gidGuest}
GROUP BY `p`.`post_id`
ORDER BY `t`.`topic_id` ASC, `p`.`post_id` ASC
SQL;
if (!($res = $xoopsDB->query($sql))) {
var_dump($xoopsDB);
exit();
}
while ($row = $xoopsDB->fetchArray($res)) {
myDumpToolDecode($row);
myDumpToolConvertToInt($row, ['post_id', 'pid', 'topic_id', 'post_time', 'modified_time', 'uid', 'uid_hidden', 'html', 'smiley', 'xcode', 'br', 'number_entity', 'special_entity', 'icon', 'attachsig', 'invisible', 'approval', 'votes_sum', 'votes_count', 'depth_in_tree', 'order_in_tree', 'uid_rank', 'uid_posts'], true);
myDumpToolDropColumn($row, ['guest_email', 'guest_url', 'guest_pass_md5', 'guest_trip']);
$posts[] = $row;
}
$xoopsDB->freeRecordSet($res);
//var_dump($posts);
var_dump(count($posts));
$data = [
'categories' => $categories,
'forums' => $forums,
'topics' => $topics,
'posts' => $posts,
];
file_put_contents(MYDUMPTOOL_OUTPUTDIR.'/forum.json', json_encode($data, JSON_UNESCAPED_UNICODE));
+1118
View File
File diff suppressed because it is too large Load Diff
+26 -3
View File
@@ -1,15 +1,36 @@
{
"name": "cbsn",
"version": "0.1.0",
"version": "1.0.0",
"private": true,
"dependencies": {
"@types/async-lock": "^1.1.1",
"@types/jest": "24.0.15",
"@types/lokijs": "^1.5.2",
"@types/node": "12.0.8",
"@types/rc-tree": "^1.11.3",
"@types/react": "16.8.20",
"@types/react-dom": "16.8.4",
"@types/react-helmet": "^5.0.8",
"@types/react-overlays": "^1.1.2",
"@types/react-router-dom": "^4.3.4",
"@types/react-router-hash-link": "^1.2.1",
"async-lock": "^1.2.0",
"axios": "^0.19.0",
"lokijs": "^1.5.6",
"moment": "^2.24.0",
"rc-tree": "^2.1.0",
"react": "^16.8.6",
"react-app-polyfill": "^1.0.1",
"react-cookie": "^4.0.0",
"react-dom": "^16.8.6",
"react-ga": "^2.5.7",
"react-helmet": "^5.2.1",
"react-image-lightbox": "^5.1.0",
"react-overlays": "^1.2.0",
"react-router-dom": "^5.0.0",
"react-router-hash-link": "^1.2.1",
"react-scripts": "3.0.1",
"react-spinner-material": "^1.1.1",
"typescript": "3.5.2"
},
"scripts": {
@@ -25,12 +46,14 @@
"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"
]
}
}
+8
View File
@@ -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]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

+5 -24
View File
@@ -5,34 +5,15 @@
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<meta name="robots" content="index,follow" />
<meta name="keywords" content="neuroinformatics, xoonips, database, cbsn platform, Comprehensive Brain Science Network" />
<meta name="author" content="Neuroinformatics Unit, RIKEN Center for Brain Science" />
<meta name="copyright" content="Copyright &copy; 2019" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>CBSN platform - XooNIps for CBSN</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
+3 -3
View File
@@ -1,10 +1,10 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "CBSN Platform",
"name": "Comprehensive Brain Science Network Platform",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"sizes": "16x16",
"type": "image/x-icon"
}
],
+277 -24
View File
@@ -1,33 +1,286 @@
.App {
text-align: center;
/* HTML TAG Re-definition */
body {
background: #fff;
font-family: Verdana, Arial, Helvetica, sans-serif, "MS Pゴシック", Osaka, "ヒラギノ角ゴ Pro W3";
color: #666666;
margin: 0px;
padding: 0px 15px 15px;
font-size: 80%;
min-width: 880px;
max-width: 1280px;
}
a {
color: #6075aa;
}
a:hover {
color: #ff9900;
}
h1,
h2,
h3 {
color: #286367;
}
h4,
h5 {
color: #6075aa;
}
ul {
margin: 2px;
padding: 2px;
list-style: decimal inside;
text-align: left;
}
li {
margin-left: 2px;
list-style: square inside;
}
table {
width: 100%;
margin: 0;
padding: 0;
}
th {
color: #6075aa;
background-color: #e3e7f0;
padding: 4px;
vertical-align: middle;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #c7c7c7;
}
td {
padding: 0;
vertical-align: top;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
legend {
padding: 3px;
color: #990000;
font-size: 120%;
font-weight: bold;
}
form {
margin: 0;
padding: 0;
}
textarea {
width: 400px;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
pointer-events: none;
.clearfix::after {
content: "";
display: block;
clear: both;
}
.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;
/* XOOPS Newbb & tabular work */
.outer {
border: 0px solid #cc0000;
}
.head,
tr.head td {
padding: 5px;
font-weight: bold;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #c7c7c7;
background-color: #f0f2f7;
}
.even {
padding: 2px;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #c7c7c7;
background-color: #f8fafe;
}
.odd {
padding: 2px;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #c7c7c7;
background-color: #ffffff;
}
.App-link {
color: #61dafb;
tr.even td {
padding: 2px;
background-color: #f8fafe;
}
tr.odd td {
padding: 2px;
background-color: #ffffff;
}
.foot {
padding: 5px;
font-weight: bold;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
.comTitle {
font-weight: bold;
margin-bottom: 2px;
}
.comText {
padding: 2px;
}
.comUserStat {
font-size: 90%;
color: #2f5376;
font-weight: bold;
border: 1px solid silver;
background-color: #ffffff;
margin: 2px;
padding: 2px;
}
.comUserStatCaption {
font-weight: normal;
}
.comUserStatus {
margin-left: 2px;
margin-top: 10px;
color: #2f5376;
font-weight: bold;
font-size: 10px;
}
.comUserRank {
margin: 2px;
}
.comUserRankText {
font-size: 90%;
font-weight: bold;
}
.comUserRankImg {
border: 0;
}
.comUserImg {
margin: 2px;
}
.comDate {
font-style: normal;
font-size: 85%;
}
.comDateCaption {
font-weight: bold;
font-style: normal;
}
/* XOOPS News */
.itemHead {
padding: 3px;
}
.itemInfo {
text-align: right;
padding: 3px;
margin-bottom: 5px;
border-bottom: 1px solid silver;
font-style: italic;
}
.itemTitle {
padding: 3px;
font-size: 120%;
font-weight: bold;
color: #6075aa;
}
.itemTitle a {
color: #286367;
text-decoration: none;
}
.itemTitle a:hover {
color: #ff9900;
}
.itemPoster {
font-size: 90%;
font-style: italic;
}
.itemPostDate {
font-size: 90%;
font-style: italic;
}
.itemStats {
font-size: 80%;
}
.itemBody {
padding: 3px;
}
.itemBody img {
padding: 5px;
}
.itemTopicImage {
float: left;
}
.itemText {
margin-top: 5px;
margin-bottom: 5px;
line-height: 1.5em;
}
.itemText:first-letter {
font-size: 133%;
font-weight: bold;
}
.itemFoot {
text-align: right;
padding: 3px;
margin-top: 5px;
background-color: #efefef;
border: 1px solid silver;
}
.itemAdminLink {
font-size: 90%;
}
.itemPermaLink {
font-size: 90%;
}
/* XOOPS Error Msg */
div.errorMsg {
background-color: #ffcccc;
text-align: center;
border-top: 1px solid #ddddff;
border-left: 1px solid #ddddff;
border-right: 1px solid #aaaaaa;
border-bottom: 1px solid #aaaaaa;
font-weight: bold;
padding: 10px;
}
div.confirmMsg {
background-color: #ddffdf;
color: #136c99;
text-align: center;
border-top: 1px solid #ddddff;
border-left: 1px solid #ddddff;
border-right: 1px solid #aaaaaa;
border-bottom: 1px solid #aaaaaa;
font-weight: bold;
padding: 10px;
}
div.resultMsg {
background-color: #cccccc;
color: #333333;
text-align: center;
border-top: 1px solid silver;
border-left: 1px solid silver;
font-weight: bold;
border-right: 1px solid #666666;
border-bottom: 1px solid #666666;
padding: 10px;
}
/* XOOPS Code &Quote */
div.xoopsCode {
background: #ffffff url(./common/assets/images/theme/xoops_quote.jpg) no-repeat right top;
border: 1px inset #000080;
overflow: auto;
max-height: 300px;
max-width: 600px;
}
div.xoopsQuote {
background: #ffffff url(./common/assets/images/theme/xoops_quote.jpg) no-repeat right top;
border: 1px inset #000080;
overflow: auto;
max-height: 300px;
max-width: 600px;
}
/* other */
table.report {
background-color: #ff8;
}
+15 -21
View File
@@ -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 (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
class App extends Component {
render() {
return (
<CookiesProvider>
<BrowserRouter>
<AppRoot />
</BrowserRouter >
</CookiesProvider>
);
}
}
export default App;
+13
View File
@@ -0,0 +1,13 @@
.notice {
color: red;
text-align: center;
margin: 10px 0;
}
.title {
margin-top: 25px;
border-bottom: solid 1px #cccccc;
}
.content {
margin: 10px 0 10px 0;
}
+28
View File
@@ -0,0 +1,28 @@
import React from 'react';
import Helmet from 'react-helmet';
import Config, { MultiLang } from '../config';
import Functions from '../functions';
import styles from './About.module.css';
import Announce from './blocks/Announce';
interface Props {
lang: MultiLang;
}
const About = (props: Props) => {
const {lang} = props;
const title = Functions.mlang('[en]Announce[/en][ja]ご案内[/ja]', lang);
return (
<div>
<Helmet>
<title>{title} - {Functions.mlang(Config.SITE_TITLE, lang)}</title>
</Helmet>
<h1>{title}</h1>
<div className={styles.content}>
<Announce lang={props.lang} />
</div>
</div>
);
}
export default About;
+79
View File
@@ -0,0 +1,79 @@
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 Container from './Container';
import Footer from './Footer';
import Header from './Header';
interface Props extends RouteComponentProps, ReactCookieProps { }
interface State {
lang: MultiLang;
}
class AppRoot extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { lang: 'en' };
}
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 (Config.GOOGLE_ANALYTICS_TRACKING_ID !== '') {
ReactGA.set({ page: pathname });
ReactGA.pageview(pathname);
}
}
componentDidUpdate(prevProps: Props) {
const { pathname, search } = this.props.location;
if (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;
const title = Functions.mlang(Config.SITE_TITLE, lang);
const slogan = Functions.mlang(Config.SITE_SLOGAN, lang);
return (
<>
<Helmet>
<title>{title} - {slogan}</title>
</Helmet>
<Header lang={lang} />
<Container lang={lang} />
<Footer lang={lang} />
</>
);
}
}
export default withCookies(withRouter(AppRoot));
+94
View File
@@ -0,0 +1,94 @@
.centerColumn {
margin: 0;
text-align: left;
line-height: 150%;
padding: 0 10px 0 15px;
}
.centerBlocks {
margin-bottom: 2em;
table-layout: fixed;
}
.centerCenterColumn {
width: 100%;
margin: 0 6px 20px;
}
.centerCenterBlock {
margin-bottom: 20px;
}
.centerCenterBlockTitle {
margin: 0;
padding: 0;
height: 28px;
font-weight: bold;
color: #6075aa;
text-indent: 15px;
font-size: 11pt;
line-height: 28px;
border: 1px solid #b7d0d5;
border-radius: 4px;
box-shadow: 0px -5px 10px -5px #b7d0d5 inset;
white-space: nowrap;
vertical-align: middle;
}
.centerCenterBlockContent {
margin: 10px 5px;
line-height: 150%;
}
.centerLeftColumn {
width: 50%;
}
.centerLeftBlock {
margin: 0 10px 0 0;
}
.centerLeftBlockTitle {
margin: 0;
padding: 0;
text-indent: 24px;
font-size: 11pt;
font-weight: bold;
background-image: url(./assets/images/theme/title_indent2.gif);
background-repeat: no-repeat;
color: #365196;
}
.centerLeftBlockContent {
margin: 10px 5px;
line-height: 120%;
}
.centerRightColumn {
width: 50%;
}
.centerRightBlock {
margin: 0;
}
.centerRightBlockTitle {
margin: 0;
padding: 0;
text-indent: 24px;
font-size: 11pt;
font-weight: bold;
background-image: url(./assets/images/theme/title_indent3.gif);
background-repeat: no-repeat;
color: #984068;
}
.centerRightBlockContent {
margin: 10px 5px;
line-height: 120%;
}
.centerMainContent {
padding: 3px 3px 10px 3px;
line-height: 150%;
}
+85
View File
@@ -0,0 +1,85 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { MultiLang } from '../config';
import Rankings from '../database/blocks/Rankings';
import RecentContents from '../database/blocks/RecentContents';
import DatabaseTop from '../database/DatabaseTop';
import Announce from './blocks/Announce';
import styles from './CenterColumn.module.css';
import MainContent from './MainContent';
interface Props {
lang: MultiLang;
}
const CenterBlocks = (props: Props) => {
const titles = props.lang === 'en' ?
{
announce: 'Announce',
databaseTop: 'Item Types',
ranking: 'Ranking',
recentContents: 'Recent Contents',
} : {
announce: 'ご案内',
databaseTop: 'アイテムタイプ一覧',
ranking: 'ランキング',
recentContents: '新着コンテンツ',
};
return (
<table className={styles.centerBlocks}>
<tbody>
<tr>
<td colSpan={2} className={styles.centerCenterColumn}>
<div className={styles.centerCenterBlock}>
<h2 className={styles.centerCenterBlockTitle}>{titles.announce}</h2>
<div className={styles.centerCenterBlockContent}>
<Announce lang={props.lang} />
</div>
</div>
</td>
</tr>
<tr>
<td colSpan={2} className={styles.centerCenterColumn}>
<div className={styles.centerCenterBlock}>
<h2 className={styles.centerCenterBlockTitle}>{titles.databaseTop}</h2>
<div className={styles.centerCenterBlockContent}>
<DatabaseTop lang={props.lang} />
</div>
</div>
</td>
</tr>
<tr>
<td className={styles.centerLeftColumn}>
<div className={styles.centerLeftBlock}>
<h2 className={styles.centerLeftBlockTitle}>{titles.ranking}</h2>
<div className={styles.centerLeftBlockContent}>
<Rankings lang={props.lang} />
</div>
</div>
</td>
<td className={styles.centerRightColumn}>
<div className={styles.centerRightBlock}>
<h2 className={styles.centerRightBlockTitle}>{titles.recentContents}</h2>
<div className={styles.centerRightBlockContent}>
<RecentContents lang={props.lang} />
</div>
</div>
</td>
</tr>
</tbody>
</table>
);
}
const CenterColumn = (props: Props) => {
return (
<td className={styles.centerColumn}>
<Switch>
<Route exact path="/" render={() => <CenterBlocks lang={props.lang} />} />
</Switch>
<MainContent lang={props.lang} />
</td>
);
}
export default CenterColumn;
+25
View File
@@ -0,0 +1,25 @@
.container {
margin: 15px 5px 30px;
}
.wrapper {
width: 100%;
vertical-align: top;
}
.wrapper td {
vertical-align: top;
}
.centerColumn {
padding: 0;
}
.centerColumn table {
width: 100%;
}
.rightColumn {
width: 200px;
padding-left: 12px;
}
+26
View File
@@ -0,0 +1,26 @@
import React from 'react';
import { MultiLang } from '../config';
import CenterColumn from './CenterColumn';
import styles from './Container.module.css';
import LeftColumn from './LeftColumn';
interface Props {
lang: MultiLang;
}
const Container = (props: Props) => {
return (
<div className={styles.container}>
<table className={styles.wrapper}>
<tbody>
<tr>
<LeftColumn lang={props.lang} />
<CenterColumn lang={props.lang} />
</tr>
</tbody>
</table>
</div>
);
}
export default Container;
+12
View File
@@ -0,0 +1,12 @@
.footer {
margin: 20px 0 30px;
font-size: 87%;
line-height: 150%;
padding-top: 10px;
border-top: 1px dotted #cccccc;
text-align: right;
}
.footer a {
padding-left: 10px;
}
+59
View File
@@ -0,0 +1,59 @@
import React from 'react';
import bannerCBSN from './assets/images/theme/banner_cbsn.gif';
import bannerIBR from './assets/images/theme/banner_ibr.gif';
import bannerJapanNode from './assets/images/theme/banner_incf-japan-node.gif';
import bannerCBS from './assets/images/theme/banner_riken-cbs.gif';
import bannerRIKEN from './assets/images/theme/banner_riken.gif';
import bannerXooNIps from './assets/images/theme/banner_xoonips.gif';
import { MultiLang } from '../config';
import styles from './Footer.module.css';
import Functions from '../functions';
interface Props {
lang: MultiLang;
}
const Footer = (props: Props) => {
const links = [
{
title: '[en]INCF Japan Node[/en][ja]INCF 日本ノード[/ja]',
image: bannerJapanNode,
url: 'https://www.neuroinf.jp/',
},
{
title: '[en]RIKEN[/en][ja]理化学研究所[/ja]',
image: bannerRIKEN,
url: 'http://www.riken.jp/',
},
{
title: '[en]RIKEN Center for Brain Science[/en][ja]理化学研究所 脳神経科学研究センター[/ja]',
image: bannerCBS,
url: 'https://cbs.riken.jp/',
},
{
title: '[en]The XooNIps Project[/en][ja]XooNIps 公式サイト[/ja]',
image: bannerXooNIps,
url: 'https://xoonips.osdn.jp/',
},
{
title: '[en]Integrative Brain Research[/en][ja]統合脳プロジェクト[/ja]',
image: bannerIBR,
url: 'http://www.togo-nou.nips.ac.jp/',
},
{
title: '[en]Comprehensive Brain Science Network[/en][ja]包括脳プロジェクト[/ja]',
image: bannerCBSN,
url: 'https://www.hokatsu-nou.neuroinf.jp/',
},
];
return (
<footer className={styles.footer}>
{links.map((link, idx) => {
const title = Functions.mlang(link.title, props.lang);
return <a key={idx} href={link.url} target="_blank" rel="noopener noreferrer"><img src={link.image} alt={title} title={title} /></a>
})}
</footer>
);
}
export default Footer;
+64
View File
@@ -0,0 +1,64 @@
.header {
width: 100%;
}
.headerLeft {
vertical-align: middle;
padding-left: 15px;
float: left;
height: 128px;
}
.headerRight {
top: 0px;
right: 15px;
text-align: right;
white-space: nowrap;
float: right;
height: 128px;
}
.titleJapanese {
font-size: 40px;
line-height: 120px;
font-weight: bold;
}
.titleEnglish {
font-size: 48px;
line-height: 120px;
}
.titleLink,
.titleLink:hover,
.titleLink:visited {
color: #666666;
text-decoration: none;
}
.menuBar {
border: 1px solid #b7d0d5;
border-radius: 4px;
box-shadow: 0px -5px 10px -5px #b7d0d5 inset;
white-space: nowrap;
vertical-align: middle;
}
.menuLink {
margin: 8px 10px;
}
.menuLink a {
color:#6075aa;
font-weight: bold;
text-decoration: none;
background-image: url(./assets/images/theme/menu_indent.gif);
background-repeat: no-repeat;
background-position: left center;
padding: 0px 10px 0px 16px;
}
.menuLink a:hover {
color:#286367;
background-image:url(./assets/images/theme/menu_indent_h.gif);
}
+52
View File
@@ -0,0 +1,52 @@
import React from 'react';
import { Link } from 'react-router-dom';
import iconHome from './assets/images/theme/icon_home.gif';
import iconHomeHover from './assets/images/theme/icon_home_h.gif';
import iconInquiry from './assets/images/theme/icon_inquiry.gif';
import iconInquiryHover from './assets/images/theme/icon_inquiry_h.gif';
import logo from './assets/images/theme/logo.png';
import mainMenus from './assets/main-menu.json';
import Config, { MultiLang } from '../config';
import styles from './Header.module.css';
import Functions from '../functions';
import LangFlag from './lib/LangFlag';
import LinkImage from './lib/LinkImage';
interface Props {
lang: MultiLang;
}
const Header = (props: Props) => {
const title = Functions.mlang(Config.SITE_TITLE, props.lang);
const titleStyle = props.lang === 'en' ? styles.titleEnglish : styles.titleJapanese;
return (
<header className={styles.header}>
<div className="clearfix">
<div className={styles.headerLeft}>
<Link className={styles.titleLink} to="/"><span className={titleStyle}>{title}</span></Link>
</div>
<div className={styles.headerRight}>
<div>
<img src={logo} alt="Comprehensive Brain Science Network" />
</div>
<div className={styles.shortcut}>
<LangFlag lang={props.lang} />
&nbsp;
<LinkImage url="/" imageNormal={iconHome} imageHover={iconHomeHover} alt="Home" />
&nbsp;
<LinkImage url="/about" imageNormal={iconInquiry} imageHover={iconInquiryHover} alt="Contact Us" />
</div>
</div>
</div>
<div className={styles.menuBar}>
<div className={styles.menuLink}>
{mainMenus.map((item, idx) => {
return <Link key={idx} to={item.link}>{Functions.mlang(item.title, props.lang)}</Link>;
})}
</div>
</div>
</header>
);
}
export default Header;
+28
View File
@@ -0,0 +1,28 @@
.leftColumn {
width: 200px;
border-right-width: 1px;
border-right-style: dotted;
border-right-color: #999999;
padding: 0 15px 0 0;
}
.leftBlock {
margin-bottom: 20px;
}
.leftBlockTitle {
margin: 0;
padding-left: 24px;
font-weight: bold;
background-image: url(./assets/images/theme/title_indent.gif);
background-repeat: no-repeat;
color: #286367;
font-size: 11pt;
line-height: 28px;
height: 24px;
}
.leftBlockContent {
margin: 5px 0 10px 0;
line-height: 120%;
}
+46
View File
@@ -0,0 +1,46 @@
import React from 'react';
import { MultiLang } from '../config';
import IndexTree from '../database/blocks/IndexTree';
import MainMenu from './blocks/MainMenu';
import Search from '../database/blocks/Search';
import styles from './LeftColumn.module.css';
interface Props {
lang: MultiLang;
}
const LeftColumn = (props: Props) => {
const titles = props.lang === 'en' ? {
mainMenu: 'Main Menu',
indexTree: 'Index Tree',
search: 'Search',
} : {
mainMenu: 'メインメニュー',
indexTree: 'インデックスツリー',
search: '検索',
};
return (
<td className={styles.leftColumn}>
<div className={styles.leftBlock}>
<h2 className={styles.leftBlockTitle}>{titles.mainMenu}</h2>
<div className={styles.leftBlockContent}>
<MainMenu lang={props.lang} />
</div>
</div>
<div className={styles.leftBlock}>
<h2 className={styles.leftBlockTitle}>{titles.indexTree}</h2>
<div className={styles.leftBlockContent}>
<IndexTree lang={props.lang} />
</div>
</div>
<div className={styles.leftBlock}>
<h2 className={styles.leftBlockTitle}>{titles.search}</h2>
<div className={styles.leftBlockContent}>
<Search lang={props.lang} />
</div>
</div>
</td>
);
}
export default LeftColumn;
+9
View File
@@ -0,0 +1,9 @@
.mainContent {
padding-top: 8px;
padding-bottom: 15px;
}
.mainContent hr {
color: #996600;
height: 2px;
}
+27
View File
@@ -0,0 +1,27 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { MultiLang } from '../config';
import About from './About';
import Database from '../database/Database';
import Forum from '../forum/Forum';
import styles from './MainContent.module.css';
import XoopsPathRedirect from './XoopsPathRedirect';
interface Props {
lang: MultiLang;
}
const MainContent = (props: Props) => {
return (
<div className={styles.mainContent}>
<Switch>
<Route path="/database" render={() => <Database {...props} />} />
<Route path="/forum" render={() => <Forum {...props} />} />
<Route exact path="/about" render={() => <About {...props} />} />
<Route component={XoopsPathRedirect} />
</Switch>
</div>
);
}
export default MainContent;
+184
View File
@@ -0,0 +1,184 @@
import React, { Component } from 'react';
import { Redirect, RouteComponentProps } from 'react-router';
import { MultiLang } from '../config';
import funcs from '../functions';
import PageNotFound from './lib/PageNotFound';
interface Params {
module: string;
pathname: string;
}
interface Props extends RouteComponentProps<Params> {
lang: MultiLang;
}
class XoopsPathRedirect extends Component<Props> {
getRedirectUrl() {
const { pathname, hash } = this.props.location;
const query = new URLSearchParams(this.props.location.search);
switch (pathname || '') {
case '/index.php': {
return '/';
}
case '/modules/xoonips':
case '/modules/xoonips/index.php': {
return '/database';
}
case '/modules/xoonips/detail.php': {
const id = query.get('id');
if (id !== null) {
return '/database/item/id/' + funcs.escape(id);
}
const itemId = query.get('item_id');
if (itemId !== null && itemId.match(/^\d+$/) !== null) {
return '/database/item/' + funcs.escape(itemId);
}
return '';
}
case '/modules/xoonips/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/' + funcs.escape(indexId) + (paramStr.length > 0 ? '?' + paramStr : '');
}
break;
}
case '/modules/xoonips/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/' + funcs.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/' + funcs.escape(type) + '/' + funcs.escape(subtype);
}
}
return '';
}
case '/modules/xoonips/advanced_search.php': {
return '/database/advanced';
}
case '/modules/forum':
case '/modules/forum/index.php': {
const catId = query.get('cat_id');
if (catId !== null && catId.match(/^\d+$/) !== null) {
return '/forum/category/' + funcs.escape(catId);
}
const forumId = query.get('forum_id');
if (forumId !== null && forumId.match(/^\d+$/) !== null) {
return '/forum/forum/' + funcs.escape(forumId);
}
const topicId = query.get('topic_id');
if (topicId !== null && topicId.match(/^\d+$/) !== null) {
const matches = hash.match(/^#post_id(\d+)$/);
return '/forum/topic/' + funcs.escape(topicId) + (matches === null ? '' : '#postId' + matches[1]);
}
const postId = query.get('post_id');
if (postId !== null && postId.match(/^\d+$/) !== null) {
return '/forum/post/' + funcs.escape(postId);
}
const catIds = query.get('cat_ids');
if (catIds !== null && catIds.match(/^\d+$/) !== null) {
return '/forum/category/' + funcs.escape(catIds);
}
return '/forum/';
}
case '/modules/contact':
case '/modules/mailform':
case '/modules/mailform/index.php': {
return '/about';
}
}
return '';
}
render() {
const { lang } = this.props;
if (this.props.location.pathname === '/') {
return null;
}
const url = this.getRedirectUrl();
if (url === '') {
return <PageNotFound lang={lang} />;
}
return <Redirect to={url} />;
}
}
export default XoopsPathRedirect;
Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

+14
View File
@@ -0,0 +1,14 @@
[
{
"title": "[en]Home[/en][ja]ホーム[/ja]",
"link": "/"
},
{
"title": "[en]Database[/en][ja]データベース[/ja]",
"link": "/database"
},
{
"title": "[en]Forum[/en][ja]フォーラム[/ja]",
"link": "/forum"
}
]
+17
View File
@@ -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;}
+29
View File
@@ -0,0 +1,29 @@
import React from 'react';
import { MultiLang } from '../../config';
interface Props {
lang: MultiLang;
}
const Annuonce = (props: Props) => {
const noticeStyle = {
color: 'red',
}
const announce = {
'en':
<>
<p style={noticeStyle}>This site has been archived since FY2019 and is no longer updated.</p>
<p>This site is supported by a Grant-in-Aid for Scientific Research on Innovative Areas (Comprehensive Brain Science Network) from the Ministry of Education, Science, Sports and Culture of Japan.</p>
</>,
'ja':
<>
<p style={noticeStyle}>2019</p>
<p>
<a href="https://www.hokatsu-nou.neuroinf.jp/" target="_blank" rel="noopener noreferrer"></a>
</p>
</>,
}
return announce[props.lang];
}
export default Annuonce;
+27
View File
@@ -0,0 +1,27 @@
.mainmenu li {
list-style: none;
}
.mainmenu a {
font-size: 95%;
display: block;
margin: 0;
padding: 4px;
border-bottom: 1px dotted #cdcdcd;
text-decoration: none;
}
.menuTop {
padding-left: 0.5em;
border-bottom: 1px dotted #cdcdcd;
}
.menuMain {
padding-left: 0.5em;
border-bottom: 1px dotted #cdcdcd;
}
.menuSub {
padding-left: 15px;
border-bottom: 1px dotted #cdcdcd;
}
+25
View File
@@ -0,0 +1,25 @@
import React from 'react';
import { Link } from 'react-router-dom';
import mainMenus from '../assets/main-menu.json';
import { MultiLang } from '../../config.js';
import Functions from '../../functions';
import styles from './MainMenu.module.css';
interface Props {
lang: MultiLang;
}
const MainMenu = (props: Props) => {
const links = mainMenus.map((item, idx) => {
const title = Functions.mlang(item.title, props.lang);
const style = idx === 0 ? styles.menuTop : styles.menuMain;
return <li key={idx}><Link className={style} to={item.link}>{title}</Link></li>
});
return (
<ul className={styles.mainmenu}>
{links}
</ul>
);
}
export default MainMenu;
+37
View File
@@ -0,0 +1,37 @@
import React, { Component } from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
import { Link } from 'react-router-dom';
import mlangEnglish from '../assets/images/mlang_english.gif';
import mlangJapanese from '../assets/images/mlang_japanese.gif';
interface Props extends RouteComponentProps {
lang: string;
}
class LangFlag extends Component<Props> {
render() {
const styleLink = {
fontSize: '8px',
};
const styleImage = {
verticalAlign: 'middle',
border: '1px solid #000',
};
const params = new URLSearchParams(this.props.location.search);
const lang = params.get('ml_lang') || this.props.lang;
const linkLang = lang !== 'en' ? 'en' : 'ja';
params.set('ml_lang', linkLang);
const url = this.props.location.pathname + '?' + params.toString();
const image = linkLang === 'en' ? mlangEnglish : mlangJapanese;
const alt = linkLang === 'en' ? 'English' : 'Japanese';
return (
<Link style={styleLink} to={url}>
<img style={styleImage} src={image} alt={alt} />
</Link>
);
}
}
export default withRouter(LangFlag);
+48
View File
@@ -0,0 +1,48 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
interface Props {
url: string;
alt: string;
imageNormal: string;
imageHover: string;
}
interface State {
image: string;
}
class LinkImage extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
image: props.imageNormal,
};
this.handleMouseOver = this.handleMouseOver.bind(this);
this.handleMouseOut = this.handleMouseOut.bind(this);
}
handleMouseOver() {
const image = this.props.imageHover;
this.setState({image})
}
handleMouseOut() {
const image = this.props.imageNormal;
this.setState({image})
}
render() {
const imgStyle = {
verticalAlign: 'middle',
}
return (
<Link to={this.props.url} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
<img style={imgStyle} src={this.state.image} alt={this.props.alt} />
</Link>
);
}
}
export default LinkImage;
+6
View File
@@ -0,0 +1,6 @@
.loading {
display: flex;
justify-content: center;
align-content: center;
margin: 100px 0 0 0;
}
+13
View File
@@ -0,0 +1,13 @@
import React from 'react';
import Spinner from 'react-spinner-material';
import styles from './Loading.module.css';
const Loading = () => {
return (
<div className={styles.loading}>
<Spinner size={70} spinnerColor={'#cccccc'} spinnerWidth={8} visible={true} />
</div>
);
}
export default Loading;
+48
View File
@@ -0,0 +1,48 @@
import React, { Component } from 'react';
import Helmet from 'react-helmet';
import { RouteComponentProps, withRouter } from 'react-router';
import Config, { MultiLang } from '../../config';
import Functions from '../../functions';
interface Props extends RouteComponentProps {
lang: MultiLang;
}
class PageNotFound extends Component<Props> {
private url = '/';
private timer: NodeJS.Timer | null = null;
goToTopPage() {
if (this.props.location.pathname !== '/') {
this.timer = setTimeout(() => {
this.props.history.push(this.url);
}, 5000);
}
}
componentWillUnmount() {
if (this.timer) {
clearTimeout(this.timer);
}
}
render() {
const siteTitle = Functions.mlang(Config.SITE_TITLE, this.props.lang);
this.goToTopPage();
return (
<div>
<Helmet>
<title>Page Not Found - {siteTitle}</title>
</Helmet>
<h1>Page Not Found</h1>
<section>
<p>The page you were trying to access doesn't exist.</p>
<p>If the page does not automatically reload, please click <a href={this.url}>here</a></p>
</section>
</div>
);
}
}
export default withRouter(PageNotFound);
+45
View File
@@ -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 <img src={userRank.image} alt={title} title={title} />;
}
export default UserRankStarImage;
+85
View File
@@ -0,0 +1,85 @@
import React from 'react';
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.base64_encode(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.base64_decode(m1)), doimage);
return '<div class="xoopsCode"><pre><code>' + text + '</code></pre></div>';
});
}
return text;
}
const convertClickable = (text: string) => {
text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+))/g, (m0, m1, m2) => {
return m1 + '<a href="' + m2 + '" rel="external">' + m2 + '</a>';
});
text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/:.]+)([a-zA-Z0-9.!#$%&*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+)/g, (m0, m1, m2) => {
return m1 + '<a href="mailto:' + m2 + '">' + m2 + '</a>';
});
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, '<br />');
}
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 <div dangerouslySetInnerHTML={{ __html: text }} />;
}
export default XoopsCode;
+13
View File
@@ -0,0 +1,13 @@
const SITE_TITLE = '[en]CBSN platform[/en][ja]包括脳プラットフォーム[/ja]';
const SITE_SLOGAN = 'XooNIps for CBSN';
const GOOGLE_ANALYTICS_TRACKING_ID = 'UA-2780809-1';
export type MultiLang = 'en' | 'ja';
const Config = {
SITE_TITLE,
SITE_SLOGAN,
GOOGLE_ANALYTICS_TRACKING_ID,
}
export default Config;
+52
View File
@@ -0,0 +1,52 @@
.database {
margin: 0;
}
.database :global(.list) {
width: 100%;
}
.database :global(.list .listTable) {
width: 100%;
border-spacing: 5px;
border: 0;
}
.database :global(.list .listTable .listIcon),
.database :global(.list .listTable .listExtra) {
vertical-align: middle;
text-align: center;
width: 65px;
line-height: 0;
}
.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 .fieldDateLabel) {
display: inline-block;
width: 50px;
}
.database :global(.advancedSearch .fieldDate select),
.database :global(.advancedSearch .fieldDate input) {
margin: 0 5px 0 0;
}
+44
View File
@@ -0,0 +1,44 @@
import React from 'react';
import Helmet from 'react-helmet';
import { Route, Switch, RouteComponentProps } from 'react-router-dom';
import PageNotFound from '../common/lib/PageNotFound';
import Config, { 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 (
<div className={styles.database}>
<Helmet>
<title>{Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} - {Functions.mlang(Config.SITE_TITLE, lang)}</title>
</Helmet>
<Switch>
<Route exact path="/database" render={(props: RouteComponentProps) => <DatabaseTop lang={lang} {...props} />} />
<Route exact path="/database/item/:id" render={(props: RouteComponentProps<{ id: string; doi: string }>) => <DatabaseDetailItem lang={lang} {...props} />} />
<Route exact path="/database/item/id/:doi" render={(props: RouteComponentProps<{ id: string; doi: string }>) => <DatabaseDetailItem lang={lang} {...props} />} />
<Route exact path="/database/advanced" render={(props: RouteComponentProps) => <DatabaseAdvancedSearch lang={lang} {...props} />} />
<Route exact path="/database/list" render={(props: RouteComponentProps<{ id: string }>) => <DatabaseSearchByIndexId lang={lang} {...props} />} />
<Route exact path="/database/list/:id" render={(props: RouteComponentProps<{ id: string }>) => <DatabaseSearchByIndexId lang={lang} {...props} />} />
<Route exact path="/database/search" render={(props: RouteComponentProps) => <DatabaseSearchByKeyword lang={lang} {...props} />} />
<Route exact path="/database/search/advanced" render={(props: RouteComponentProps) => <DatabaseSearchByAdvancedKeyword lang={lang} {...props} />} />
<Route exact path="/database/search/itemtype/:itemType" render={(props: RouteComponentProps<{ itemType: string; subItemType: string }>) => <DatabaseSearchByItemType lang={lang} {...props} />} />
<Route exact path="/database/search/itemtype/:itemType/:subItemType" render={(props: RouteComponentProps<{ itemType: string; subItemType: string }>) => <DatabaseSearchByItemType lang={lang} {...props} />} />
<Route component={PageNotFound} />
</Switch>
</div>
);
}
export default Database;
+49
View File
@@ -0,0 +1,49 @@
import React, { Component } from 'react';
import { RouteComponentProps } from 'react-router';
import { 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<Props> {
private query: AdvancedSearchQuery = new AdvancedSearchQuery();
private itemTypes = ['tool', 'paper', 'presentation', 'book', 'data', 'url', 'files'];
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 (
<div className="advancedSearch">
<h3>{Functions.mlang('[en]Search Items[/en][ja]アイテム検索[/ja]', lang)}</h3>
<div className="search">
<button className="formButton" onClick={this.handleClickSearchButton}>Search</button>
</div>
{this.itemTypes.map((type, i) => {
return <ItemType.AdvancedSearch key={i} type={'xnp' + type} lang={lang} query={this.query} />;
})}
<div className="search">
<button className="formButton" onClick={this.handleClickSearchButton}>Search</button>
</div>
</div>
);
}
}
export default DatabaseAdvancedSearch;
+89
View File
@@ -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 Config, { 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<Params> {
lang: MultiLang;
}
interface State {
loading: boolean;
item: Item | null;
}
class DatabaseDetailItem extends Component<Props, State> {
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 <Loading />;
}
if (this.state.item === null) {
return <PageNotFound lang={lang} />;
}
return (
<>
<Helmet>
<title>{Functions.mlang(this.state.item.title, lang)} - {Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} - {Functions.mlang(Config.SITE_TITLE, lang)}</title>
</Helmet>
<h3>{Functions.mlang('[en]Detail[/en][ja]詳細[/ja]', lang)}</h3>
<br />
<ItemType.Detail lang={lang} item={this.state.item} />
</>
);
}
}
export default DatabaseDetailItem;
@@ -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<Props, State> {
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 (
<div className="list">
<h3>Listing item</h3>
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} />
</div>
);
}
}
export default DatabaseSearchByAdvancedKeyword;
+88
View File
@@ -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 Config, { 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<Params> {
lang: MultiLang;
}
interface State {
indexId: number;
}
class DatabaseSearchByIndexId extends Component<Props, State> {
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 <PageNotFound lang={lang} />;
}
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 <Fragment key={value.id}>/ <Link to={url}>{value.title}</Link> </Fragment>;
});
const title = pIndexes.map((value) => { return '/' + value.title; }).join('');
return (
<div className="list">
<Helmet>
<title>{Functions.mlang(title, lang)} - {Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} - {Functions.mlang(Config.SITE_TITLE, lang)}</title>
</Helmet>
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
<div>{parents}</div>
<DatabaseListIndex lang={lang} index={index} />
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} />
</div>
);
}
}
export default DatabaseSearchByIndexId;
+73
View File
@@ -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<Params> {
lang: MultiLang;
}
interface State {
itemType: string;
subItemType: string;
}
class DatabaseSearchByItemType extends Component<Props, State> {
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 (
<div className="list">
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} />
</div>
);
}
}
export default DatabaseSearchByItemType;

Some files were not shown because too many files have changed in this diff Show More