revised and updated sources.
This commit is contained in:
parent
040eee8240
commit
8f37b9c537
29
.eslintrc.cjs
Normal file
29
.eslintrc.cjs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: { browser: true, es2020: true },
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended-type-checked',
|
||||||
|
'plugin:@typescript-eslint/stylistic-type-checked',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react/jsx-runtime',
|
||||||
|
],
|
||||||
|
ignorePatterns: ['dist', '.eslintrc.cjs', 'vite.config.ts'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
plugins: ['react-refresh'],
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,3 +22,6 @@
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
# customize
|
||||||
|
/public/data
|
||||||
|
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/prettierrc",
|
||||||
|
"semi": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 100,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"jawandarajbir.react-vscode-extension-pack",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"streetsidesoftware.code-spell-checker"
|
||||||
|
]
|
||||||
|
}
|
12
.vscode/launch.json
vendored
Normal file
12
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Vite Debugger",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"url": "http://localhost:3000/",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
71
.vscode/settings.json
vendored
Normal file
71
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": true
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[javascriptreact]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[typescriptreact]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[html]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[css]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[json]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[jsonc]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
// Extensions - Code Spell Checker
|
||||||
|
"cSpell.ignoreWords": ["degu", "Neuroinformatics", "octodon", "RIKEN"],
|
||||||
|
"cSpell.words": [
|
||||||
|
"dobr",
|
||||||
|
"doesn",
|
||||||
|
"dohtml",
|
||||||
|
"doimage",
|
||||||
|
"dosmiley",
|
||||||
|
"doxcode",
|
||||||
|
"htmlspecialchars",
|
||||||
|
"itemcount",
|
||||||
|
"itemselect",
|
||||||
|
"itemsubtypesearch",
|
||||||
|
"itemtype",
|
||||||
|
"itemtypes",
|
||||||
|
"itemtypesearch",
|
||||||
|
"justsystem",
|
||||||
|
"lightbox",
|
||||||
|
"listitem",
|
||||||
|
"lokijs",
|
||||||
|
"mathematica",
|
||||||
|
"mday",
|
||||||
|
"mlang",
|
||||||
|
"navi",
|
||||||
|
"orderdir",
|
||||||
|
"pageview",
|
||||||
|
"pubmed",
|
||||||
|
"quicksearch",
|
||||||
|
"simpf",
|
||||||
|
"simplesort",
|
||||||
|
"subitemtype",
|
||||||
|
"xoonips",
|
||||||
|
"xoops"
|
||||||
|
],
|
||||||
|
// Extensions - HTML
|
||||||
|
"html.format.wrapLineLength": 0,
|
||||||
|
// Extentions - Prettier
|
||||||
|
// - see: .prettierrc.json
|
||||||
|
// Extentions - Typescript
|
||||||
|
"javascript.updateImportsOnFileMove.enabled": "always",
|
||||||
|
"typescript.updateImportsOnFileMove.enabled": "always"
|
||||||
|
}
|
40
.vscode/tasks.json
vendored
Normal file
40
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "npm: dev",
|
||||||
|
"detail": "vite dev",
|
||||||
|
"type": "npm",
|
||||||
|
"script": "dev",
|
||||||
|
"problemMatcher": "$tsc",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"echo": true,
|
||||||
|
"reveal": "silent",
|
||||||
|
"focus": false,
|
||||||
|
"panel": "shared",
|
||||||
|
"showReuseMessage": true,
|
||||||
|
"clear": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "npm: build",
|
||||||
|
"detail": "vite build",
|
||||||
|
"type": "npm",
|
||||||
|
"script": "build",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$tsc",
|
||||||
|
"presentation": {
|
||||||
|
"echo": true,
|
||||||
|
"reveal": "silent",
|
||||||
|
"focus": false,
|
||||||
|
"panel": "shared",
|
||||||
|
"showReuseMessage": true,
|
||||||
|
"clear": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
@ -10,14 +10,21 @@
|
|||||||
content="BSI-NI Brain Atlas - This site provides the 3D atlas and the standard MRI template of Degu, Common Marmoset and Japanese Macaque Monkey."
|
content="BSI-NI Brain Atlas - This site provides the 3D atlas and the standard MRI template of Degu, Common Marmoset and Japanese Macaque Monkey."
|
||||||
/>
|
/>
|
||||||
<meta name="robots" content="index,follow" />
|
<meta name="robots" content="index,follow" />
|
||||||
<meta name="keywords" content="neuroinformatics, bsi-ni, brain science, xoonips, database, brain atlas, degu, japanese macaque monkey, common marmoset" />
|
<meta
|
||||||
<meta name="author" content="BSI-NI and Laboratory for Symbolic Cognitive Development, RIKEN Brain Science Institute" />
|
name="keywords"
|
||||||
|
content="neuroinformatics, bsi-ni, brain science, xoonips, database, brain atlas, degu, japanese macaque monkey, common marmoset"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="author"
|
||||||
|
content="BSI-NI and Laboratory for Symbolic Cognitive Development, RIKEN Brain Science Institute"
|
||||||
|
/>
|
||||||
<meta name="copyright" content="Copyright © 2017" />
|
<meta name="copyright" content="Copyright © 2017" />
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<title>BSI-NI Brain Atlas</title>
|
<title>BSI-NI Brain Atlas</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
5515
package-lock.json
generated
Normal file
5515
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
97
package.json
97
package.json
@ -1,65 +1,58 @@
|
|||||||
{
|
{
|
||||||
"name": "brainatlas",
|
"name": "brainatlas",
|
||||||
"version": "1.0.0",
|
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"version": "2.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"format": "prettier --write src/"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@orrisroot/react-html-parser": "^2.1.0",
|
"@orrisroot/react-html-parser": "^2.1.1",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"async-lock": "^1.4.0",
|
||||||
"@testing-library/react": "^13.3.0",
|
"axios": "^1.4.0",
|
||||||
"@testing-library/user-event": "^14.2.0",
|
|
||||||
"@types/async-lock": "^1.1.5",
|
|
||||||
"@types/jest": "^28.1.1",
|
|
||||||
"@types/lokijs": "^1.5.7",
|
|
||||||
"@types/node": "^17.0.41",
|
|
||||||
"@types/react": "^18.0.12",
|
|
||||||
"@types/react-dom": "^18.0.5",
|
|
||||||
"@types/react-router-dom": "^5.3.3",
|
|
||||||
"@types/react-router-hash-link": "^2.4.5",
|
|
||||||
"async-lock": "^1.3.1",
|
|
||||||
"axios": "^0.27.2",
|
|
||||||
"lokijs": "^1.5.12",
|
"lokijs": "^1.5.12",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.4",
|
||||||
"rc-tree": "^5.6.5",
|
"node-stdlib-browser": "^1.2.0",
|
||||||
"react": "^18.1.0",
|
"rc-tree": "^5.7.9",
|
||||||
|
"react": "^18.2.0",
|
||||||
"react-app-polyfill": "^3.0.0",
|
"react-app-polyfill": "^3.0.0",
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^18.1.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-ga4": "^1.4.1",
|
"react-ga4": "^2.1.0",
|
||||||
"react-helmet-async": "^1.3.0",
|
"react-helmet-async": "^1.3.0",
|
||||||
"react-image-lightbox": "^5.1.4",
|
"react-overlays": "^5.2.1",
|
||||||
"react-overlays": "^5.2.0",
|
"react-router-dom": "^6.14.2",
|
||||||
"react-router-dom": "^6.3.0",
|
|
||||||
"react-router-hash-link": "^2.4.3",
|
"react-router-hash-link": "^2.4.3",
|
||||||
"react-scripts": "^5.0.1",
|
|
||||||
"react-spinner-material": "^1.4.0",
|
"react-spinner-material": "^1.4.0",
|
||||||
"typescript": "^4.7.3",
|
"sanitize.css": "^13.0.0",
|
||||||
"web-vitals": "^2.1.4",
|
"xregexp": "^5.1.1",
|
||||||
"xregexp": "^5.1.1"
|
"yet-another-react-lightbox": "^3.11.4"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"devDependencies": {
|
||||||
"@svgr/webpack": "^6.2.1"
|
"@types/async-lock": "^1.4.0",
|
||||||
},
|
"@types/jest": "^29.5.3",
|
||||||
"scripts": {
|
"@types/lokijs": "^1.5.8",
|
||||||
"start": "react-scripts start",
|
"@types/node": "^18.17.1",
|
||||||
"build": "react-scripts build",
|
"@types/react": "^18.2.17",
|
||||||
"test": "react-scripts test",
|
"@types/react-dom": "^18.2.7",
|
||||||
"eject": "react-scripts eject"
|
"@types/react-router-dom": "^5.3.3",
|
||||||
},
|
"@types/react-router-hash-link": "^2.4.6",
|
||||||
"eslintConfig": {
|
"@types/react-syntax-highlighter": "^15.5.7",
|
||||||
"extends": "react-app"
|
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
||||||
},
|
"@typescript-eslint/parser": "^6.2.0",
|
||||||
"browserslist": {
|
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||||
"production": [
|
"eslint": "^8.45.0",
|
||||||
">0.2%",
|
"eslint-plugin-react": "^7.33.0",
|
||||||
"not dead",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"not op_mini all",
|
"eslint-plugin-react-refresh": "^0.4.3",
|
||||||
"ie 11"
|
"prettier": "^3.0.0",
|
||||||
],
|
"typescript": "^5.1.6",
|
||||||
"development": [
|
"vite": "^4.4.7",
|
||||||
"last 1 chrome version",
|
"vite-plugin-node-stdlib-browser": "^0.2.1",
|
||||||
"last 1 firefox version",
|
"vite-plugin-rewrite-all": "^1.0.1"
|
||||||
"last 1 safari version",
|
|
||||||
"ie 11"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
RewriteEngine on
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine On
|
||||||
RewriteBase /
|
RewriteBase /
|
||||||
|
|
||||||
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
|
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
|
||||||
RewriteRule ^degu/modules/xoonips/download.php /degu/file/%2? [R=301,L]
|
RewriteRule ^degu/modules/xoonips/download.php /data/degu/file/%2? [R=301,L]
|
||||||
|
|
||||||
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
|
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
|
||||||
RewriteRule ^jm/modules/xoonips/download.php /jm/file/%2? [R=301,L]
|
RewriteRule ^jm/modules/xoonips/download.php /data/jm/file/%2? [R=301,L]
|
||||||
|
|
||||||
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
|
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
|
||||||
RewriteRule ^marmoset/modules/xoonips/download.php /marmoset/file/%2? [R=301,L]
|
RewriteRule ^marmoset/modules/xoonips/download.php /data/marmoset/file/%2? [R=301,L]
|
||||||
|
|
||||||
|
RewriteRule ^index\.html$ - [L]
|
||||||
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d [OR]
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-l [OR]
|
||||||
RewriteCond %{REQUEST_FILENAME} -d
|
RewriteCond %{REQUEST_FILENAME} -d
|
||||||
RewriteCond %{REQUEST_FILENAME}index.html !-f
|
RewriteCond %{REQUEST_FILENAME}index.html !-f
|
||||||
RewriteRule . /index.html [L]
|
RewriteRule . /index.html [L]
|
||||||
|
</IfModule>
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
test('renders learn react link', () => {
|
|
||||||
render(<App />);
|
|
||||||
const linkElement = screen.getByText(/learn react/i);
|
|
||||||
expect(linkElement).toBeInTheDocument();
|
|
||||||
});
|
|
40
src/App.tsx
40
src/App.tsx
@ -1,26 +1,32 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React from 'react';
|
||||||
import { CookiesProvider, useCookies } from "react-cookie";
|
|
||||||
import ReactGA from "react-ga4";
|
import { CookiesProvider, useCookies } from 'react-cookie';
|
||||||
import { HelmetProvider } from "react-helmet-async";
|
import ReactGA from 'react-ga4';
|
||||||
import { BrowserRouter, useLocation } from "react-router-dom";
|
import { HelmetProvider } from 'react-helmet-async';
|
||||||
import "./App.css";
|
import { BrowserRouter, useLocation } from 'react-router-dom';
|
||||||
import AppRoot from "./common/AppRoot";
|
import './App.css';
|
||||||
import Config, { MultiLang } from "./config";
|
import AppRoot from './common/AppRoot';
|
||||||
|
import Config, { MultiLang } from './config';
|
||||||
|
|
||||||
|
const mlang = ['en', 'ja'] as const;
|
||||||
|
const isMultiLang = (name: string): name is MultiLang => {
|
||||||
|
return mlang.some((value) => value === name);
|
||||||
|
};
|
||||||
|
|
||||||
const AppMain: React.FC = () => {
|
const AppMain: React.FC = () => {
|
||||||
const [cookies, setCookie] = useCookies();
|
const [cookies, setCookie] = useCookies();
|
||||||
const [lang, setLang] = useState<MultiLang>(["en", "ja"].includes(cookies.ml_lang) ? cookies.ml_lang : "en");
|
const typedCookies = cookies as Record<string, string>;
|
||||||
|
const [lang, setLang] = React.useState<MultiLang>(
|
||||||
|
isMultiLang(typedCookies?.ml_lang ?? '') ? (cookies.ml_lang as MultiLang) : 'en',
|
||||||
|
);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (Config.GOOGLE_ANALYTICS_TRACKING_ID !== "") {
|
|
||||||
ReactGA.send("pageview");
|
|
||||||
}
|
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const ml_lang = params.get("ml_lang");
|
const ml_lang = params.get('ml_lang');
|
||||||
if (ml_lang != null && ["en", "ja"].includes(ml_lang)) {
|
if (ml_lang != null && ['en', 'ja'].includes(ml_lang)) {
|
||||||
if (cookies.ml_lang !== ml_lang) {
|
if (cookies.ml_lang !== ml_lang) {
|
||||||
setCookie("ml_lang", ml_lang);
|
setCookie('ml_lang', ml_lang);
|
||||||
}
|
}
|
||||||
if (lang !== ml_lang) {
|
if (lang !== ml_lang) {
|
||||||
setLang(ml_lang as MultiLang);
|
setLang(ml_lang as MultiLang);
|
||||||
@ -33,7 +39,7 @@ const AppMain: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
if (Config.GOOGLE_ANALYTICS_TRACKING_ID !== "") {
|
if (Config.GOOGLE_ANALYTICS_TRACKING_ID.startsWith('G-')) {
|
||||||
ReactGA.initialize(Config.GOOGLE_ANALYTICS_TRACKING_ID);
|
ReactGA.initialize(Config.GOOGLE_ANALYTICS_TRACKING_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Helmet } from "react-helmet-async";
|
|
||||||
import { Route, Routes, useLocation } from "react-router-dom";
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
import { Route, Routes, useLocation } from 'react-router-dom';
|
||||||
import SiteIndex from "../custom/SiteIndex";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
import Functions from "../functions";
|
import SiteIndex from '../custom/SiteIndex';
|
||||||
import Footer from "./Footer";
|
import Functions from '../functions';
|
||||||
import Header from "./Header";
|
import Footer from './Footer';
|
||||||
import PageNotFound from "./lib/PageNotFound";
|
import Header from './Header';
|
||||||
import MainContent from "./MainContent";
|
import MainContent from './MainContent';
|
||||||
|
import PageNotFound from './lib/PageNotFound';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -19,7 +20,7 @@ interface PropsMain extends Props {
|
|||||||
isLink: boolean;
|
isLink: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PageMain: React.FC<PropsMain> = (props: PropsMain) => {
|
const PageMain: React.FC<PropsMain> = (props) => {
|
||||||
const { lang, type, isHtml, isLink } = props;
|
const { lang, type, isHtml, isLink } = props;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -32,10 +33,12 @@ const PageMain: React.FC<PropsMain> = (props: PropsMain) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppRoot: React.FC<Props> = (props: Props) => {
|
const AppRoot: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const match = location.pathname.match(/^\/(degu|jm|marmoset)(?:\/|$|(?:_(html)(?:\/$|$|\/(link\.html$))))/);
|
const match = location.pathname.match(
|
||||||
|
/^\/(degu|jm|marmoset)(?:\/|$|(?:_(html)(?:\/$|$|\/(link\.html$))))/,
|
||||||
|
);
|
||||||
const isHtml = match !== null ? typeof match[2] !== 'undefined' : false;
|
const isHtml = match !== null ? typeof match[2] !== 'undefined' : false;
|
||||||
const isLink = match !== null ? typeof match[3] !== 'undefined' : false;
|
const isLink = match !== null ? typeof match[3] !== 'undefined' : false;
|
||||||
|
|
||||||
@ -48,12 +51,30 @@ const AppRoot: React.FC<Props> = (props: Props) => {
|
|||||||
</Helmet>
|
</Helmet>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route index element={<SiteIndex lang={lang} />} />
|
<Route index element={<SiteIndex lang={lang} />} />
|
||||||
<Route path="degu_html/*" element={<PageMain lang={lang} type="degu" isHtml={isHtml} isLink={isLink} />} />
|
<Route
|
||||||
<Route path="jm_html/*" element={<PageMain lang={lang} type="jm" isHtml={isHtml} isLink={isLink} />} />
|
path="degu_html/*"
|
||||||
<Route path="marmoset_html/*" element={<PageMain lang={lang} type="marmoset" isHtml={isHtml} isLink={isLink} />} />
|
element={<PageMain lang={lang} type="degu" isHtml={isHtml} isLink={isLink} />}
|
||||||
<Route path="degu/*" element={<PageMain lang={lang} type="degu" isHtml={isHtml} isLink={isLink} />} />
|
/>
|
||||||
<Route path="jm/*" element={<PageMain lang={lang} type="jm" isHtml={isHtml} isLink={isLink} />} />
|
<Route
|
||||||
<Route path="marmoset/*" element={<PageMain lang={lang} type="marmoset" isHtml={isHtml} isLink={isLink} />} />
|
path="jm_html/*"
|
||||||
|
element={<PageMain lang={lang} type="jm" isHtml={isHtml} isLink={isLink} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="marmoset_html/*"
|
||||||
|
element={<PageMain lang={lang} type="marmoset" isHtml={isHtml} isLink={isLink} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="degu/*"
|
||||||
|
element={<PageMain lang={lang} type="degu" isHtml={isHtml} isLink={isLink} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="jm/*"
|
||||||
|
element={<PageMain lang={lang} type="jm" isHtml={isHtml} isLink={isLink} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="marmoset/*"
|
||||||
|
element={<PageMain lang={lang} type="marmoset" isHtml={isHtml} isLink={isLink} />}
|
||||||
|
/>
|
||||||
<Route path="*" element={<PageNotFound lang={lang} />} />
|
<Route path="*" element={<PageNotFound lang={lang} />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
import { Link } from 'react-router-dom';
|
||||||
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -8,25 +9,40 @@ interface Props {
|
|||||||
isLink: boolean;
|
isLink: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Footer: React.FC<Props> = (props: Props) => {
|
const Footer: React.FC<Props> = (props) => {
|
||||||
const { type, isLink } = props;
|
const { type, isLink } = props;
|
||||||
return (
|
return (
|
||||||
<footer>
|
<footer>
|
||||||
<div className="links clearfix">
|
<div className="links clearfix">
|
||||||
<span className={`image ${type}`}> </span>
|
<span className={`image ${type}`}> </span>
|
||||||
{!isLink && (
|
{!isLink && (
|
||||||
<Link className="relatedLink" to={"/" + type + "_html/link.html"}>
|
<Link className="relatedLink" to={'/' + type + '_html/link.html'}>
|
||||||
<span>Related Link</span>
|
<span>Related Link</span>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
<a className="bsi-ni" href="https://bsi-ni.brain.riken.jp/" target="_blank" rel="noopener noreferrer">
|
<a
|
||||||
|
className="bsi-ni"
|
||||||
|
href="https://bsi-ni.brain.riken.jp/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
<span>BSI-Neuroinformatics</span>
|
<span>BSI-Neuroinformatics</span>
|
||||||
</a>
|
</a>
|
||||||
<span className="gotoTop">
|
<span className="gotoTop">
|
||||||
<Link to="/">» GO TO TOP</Link>
|
<Link to="/">» GO TO TOP</Link>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{type === "marmoset" ? <div className="copyright">Copyright (C) 2018 Laboratory for Symbolic Cognitive Development, RIKEN Center for Biosystems Dynamics Research.</div> : <div className="copyright">Copyright (C) 2017 BSI-NI Project & Laboratory for Symbolic Cognitive Development, RIKEN Brain Science Insititute.</div>}
|
{type === 'marmoset' ? (
|
||||||
|
<div className="copyright">
|
||||||
|
Copyright (C) 2018 Laboratory for Symbolic Cognitive Development, RIKEN Center for
|
||||||
|
Biosystems Dynamics Research.
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="copyright">
|
||||||
|
Copyright (C) 2017 BSI-NI Project & Laboratory for Symbolic Cognitive Development,
|
||||||
|
RIKEN Brain Science Insititute.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,58 +1,59 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Helmet } from "react-helmet-async";
|
|
||||||
import { Link, useLocation } from "react-router-dom";
|
import { Helmet } from 'react-helmet-async';
|
||||||
import Config, { BrainAtlasType, MultiLang } from "../config";
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
import Config, { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeaderType = BrainAtlasType | "marmoset_3d" | "marmoset_std";
|
type HeaderType = BrainAtlasType | 'marmoset_3d' | 'marmoset_std';
|
||||||
|
|
||||||
const titles = {
|
const titles = {
|
||||||
degu: "Degu - 3D Brain Atlas",
|
degu: 'Degu - 3D Brain Atlas',
|
||||||
jm: "Japanese Macaque Monkey - the MRI Standard Brain",
|
jm: 'Japanese Macaque Monkey - the MRI Standard Brain',
|
||||||
marmoset: "Marmoset",
|
marmoset: 'Marmoset',
|
||||||
marmoset_3d: "Marmoset - 3D Brain Atlas",
|
marmoset_3d: 'Marmoset - 3D Brain Atlas',
|
||||||
marmoset_std: "Marmoset - the MRI Standard Brain",
|
marmoset_std: 'Marmoset - the MRI Standard Brain',
|
||||||
};
|
};
|
||||||
const urls = {
|
const urls = {
|
||||||
degu: "/degu/modules/xoonips/listitem.php?index_id=24",
|
degu: '/degu/modules/xoonips/listitem.php?index_id=24',
|
||||||
jm: "/jm/modules/xoonips/listitem.php?index_id=9",
|
jm: '/jm/modules/xoonips/listitem.php?index_id=9',
|
||||||
marmoset: "/marmoset_html/",
|
marmoset: '/marmoset_html/',
|
||||||
marmoset_3d: "/marmoset/modules/xoonips/listitem.php?index_id=66",
|
marmoset_3d: '/marmoset/modules/xoonips/listitem.php?index_id=66',
|
||||||
marmoset_std: "/marmoset/modules/xoonips/listitem.php?index_id=71",
|
marmoset_std: '/marmoset/modules/xoonips/listitem.php?index_id=71',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getHeaderType = (type: BrainAtlasType, pathname: string, search: string): HeaderType => {
|
const getHeaderType = (type: BrainAtlasType, pathname: string, search: string): HeaderType => {
|
||||||
if (type === "marmoset") {
|
if (type === 'marmoset') {
|
||||||
const params = new URLSearchParams(search);
|
const params = new URLSearchParams(search);
|
||||||
switch (pathname) {
|
switch (pathname) {
|
||||||
case "/marmoset/modules/xoonips/listitem.php": {
|
case '/marmoset/modules/xoonips/listitem.php': {
|
||||||
const index_id = params.get("index_id") || "3";
|
const index_id = params.get('index_id') ?? '3';
|
||||||
if (["66", "69"].includes(index_id)) {
|
if (['66', '69'].includes(index_id)) {
|
||||||
return "marmoset_3d";
|
return 'marmoset_3d';
|
||||||
}
|
}
|
||||||
if (["71", "73"].includes(index_id)) {
|
if (['71', '73'].includes(index_id)) {
|
||||||
return "marmoset_std";
|
return 'marmoset_std';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "/marmoset/modules/xoonips/detail.php": {
|
case '/marmoset/modules/xoonips/detail.php': {
|
||||||
const item_id = params.get("item_id") || "";
|
const item_id = params.get('item_id') ?? '';
|
||||||
if (["77", "75", "79", "80"].includes(item_id)) {
|
if (['77', '75', '79', '80'].includes(item_id)) {
|
||||||
return "marmoset_3d";
|
return 'marmoset_3d';
|
||||||
}
|
}
|
||||||
if (["72"].includes(item_id)) {
|
if (['72'].includes(item_id)) {
|
||||||
return "marmoset_std";
|
return 'marmoset_std';
|
||||||
}
|
}
|
||||||
const id = params.get("id") || "";
|
const id = params.get('id') ?? '';
|
||||||
if (["Marmoset02", "Marmoset04", "Marmoset05", "Marmoset06"].includes(id)) {
|
if (['Marmoset02', 'Marmoset04', 'Marmoset05', 'Marmoset06'].includes(id)) {
|
||||||
return "marmoset_3d";
|
return 'marmoset_3d';
|
||||||
}
|
}
|
||||||
if (["004"].includes(id)) {
|
if (['004'].includes(id)) {
|
||||||
return "marmoset_std";
|
return 'marmoset_std';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -61,19 +62,19 @@ const getHeaderType = (type: BrainAtlasType, pathname: string, search: string):
|
|||||||
return type;
|
return type;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header: React.FC<Props> = (props: Props) => {
|
const Header: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { pathname, search } = location;
|
const { pathname, search } = location;
|
||||||
const params = new URLSearchParams(search);
|
const params = new URLSearchParams(search);
|
||||||
params.set("ml_lang", lang === "en" ? "ja" : "en");
|
params.set('ml_lang', lang === 'en' ? 'ja' : 'en');
|
||||||
const langUrl = location.pathname + "?" + params.toString();
|
const langUrl = `${location.pathname}?${params.toString()}`;
|
||||||
const langLabel = lang === "en" ? "To Japanese" : "To English";
|
const langLabel = lang === 'en' ? 'To Japanese' : 'To English';
|
||||||
const xtype = getHeaderType(type, pathname, search);
|
const hType = getHeaderType(type, pathname, search);
|
||||||
const title = Config.SITE_TITLE + " " + titles[xtype];
|
const title = Config.SITE_TITLE + ' ' + titles[hType];
|
||||||
const url = urls[xtype];
|
const url = urls[hType];
|
||||||
return (
|
return (
|
||||||
<header className={xtype}>
|
<header className={hType}>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Route, Routes } from "react-router-dom";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
import { Route, Routes } from 'react-router-dom';
|
||||||
import CoverPage from "../custom/CoverPage";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
import RelatedLink from "../custom/RelatedLink";
|
import CoverPage from '../custom/CoverPage';
|
||||||
import Database from "../database/Database";
|
import RelatedLink from '../custom/RelatedLink';
|
||||||
import DatabaseTop from "../database/DatabaseTop";
|
import Database from '../database/Database';
|
||||||
import XoopsPathRedirect from "./XoopsPathRedirect";
|
import DatabaseTop from '../database/DatabaseTop';
|
||||||
|
import XoopsPathRedirect from './XoopsPathRedirect';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -14,7 +15,7 @@ interface Props {
|
|||||||
isLink: boolean;
|
isLink: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MainContent: React.FC<Props> = (props: Props) => {
|
const MainContent: React.FC<Props> = (props) => {
|
||||||
const { lang, type, isHtml, isLink } = props;
|
const { lang, type, isHtml, isLink } = props;
|
||||||
return (
|
return (
|
||||||
<div className="mainContent">
|
<div className="mainContent">
|
||||||
|
@ -1,26 +1,27 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Navigate, useLocation } from "react-router-dom";
|
|
||||||
import { MultiLang } from "../config";
|
import { Navigate, useLocation } from 'react-router-dom';
|
||||||
import PageNotFound from "./lib/PageNotFound";
|
import { MultiLang } from '../config';
|
||||||
|
import PageNotFound from './lib/PageNotFound';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XoopsPathRedirect: React.FC<Props> = (props: Props) => {
|
const XoopsPathRedirect: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { pathname } = location;
|
const { pathname } = location;
|
||||||
const getRedirectUrl = () => {
|
const getRedirectUrl = () => {
|
||||||
switch (pathname || "") {
|
switch (pathname || '') {
|
||||||
case "/index.php": {
|
case '/index.php': {
|
||||||
return "/";
|
return '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return '';
|
||||||
};
|
};
|
||||||
const url = getRedirectUrl();
|
const url = getRedirectUrl();
|
||||||
if (url === "") {
|
if (url === '') {
|
||||||
return <PageNotFound lang={lang} />;
|
return <PageNotFound lang={lang} />;
|
||||||
}
|
}
|
||||||
return <Navigate to={url} />;
|
return <Navigate to={url} />;
|
||||||
|
@ -141,7 +141,7 @@ tr.even:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.clearfix::after {
|
.clearfix::after {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,62 @@
|
|||||||
img {border: 0;}
|
img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#xoopsHiddenText {visibility: hidden; color: #000000; font-weight: normal; font-style: normal; text-decoration: none;}
|
#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);}
|
.pagneutral {
|
||||||
.pagact {font-size: 10px; width: 16px; height: 19px;text-align: center; background-image: url(./images/pagact.gif);}
|
font-size: 10px;
|
||||||
.paginact {font-size: 10px; width: 16px; height: 19px;text-align: center; background-image: url(./images/paginact.gif);}
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
#mainmenu a {text-align:left; display: block; margin: 0; padding: 4px;}
|
#usermenu a {
|
||||||
#mainmenu a.menuTop {padding-left: 3px;}
|
text-align: left;
|
||||||
#mainmenu a.menuMain {padding-left: 3px;}
|
display: block;
|
||||||
#mainmenu a.menuSub {padding-left: 9px;}
|
margin: 0;
|
||||||
|
padding: 4px;
|
||||||
#usermenu a {text-align:left; display: block; margin: 0; padding: 4px;}
|
}
|
||||||
#usermenu a.menuTop {}
|
#usermenu a.menuTop {
|
||||||
#usermenu a.highlight {color: #0000ff; background-color: #fcc;}
|
}
|
||||||
|
#usermenu a.highlight {
|
||||||
|
color: #0000ff;
|
||||||
|
background-color: #fcc;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
url: string;
|
url: string;
|
||||||
@ -8,50 +9,40 @@ interface Props {
|
|||||||
imageHover?: string;
|
imageHover?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const LinkImage: React.FC<Props> = (props) => {
|
||||||
image: string;
|
const { url, title, image: imageNormal, imageHover } = props;
|
||||||
}
|
const [image, setImage] = React.useState<string>(imageNormal);
|
||||||
|
|
||||||
class LinkImage extends Component<Props, State> {
|
const handleMouseOver = () => {
|
||||||
constructor(props: Props) {
|
if (imageHover != null) {
|
||||||
super(props);
|
setImage(imageHover);
|
||||||
this.state = {
|
}
|
||||||
image: props.image,
|
|
||||||
};
|
};
|
||||||
this.handleMouseOver = this.handleMouseOver.bind(this);
|
|
||||||
this.handleMouseOut = this.handleMouseOut.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMouseOver() {
|
const handleMouseOut = () => {
|
||||||
const { imageHover } = this.props;
|
if (imageHover != null) {
|
||||||
if (typeof imageHover !== "undefined") {
|
setImage(imageNormal);
|
||||||
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 = <img style={{ verticalAlign: "middle" }} src={this.state.image} alt={title} title={title} />;
|
|
||||||
if (url.match(/^(\/|\.)/) === null) {
|
if (url.match(/^(\/|\.)/) === null) {
|
||||||
return (
|
return (
|
||||||
<a href={url} target="_blank" rel="noopener noreferrer" onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
|
<a
|
||||||
|
href={url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
onMouseOver={handleMouseOver}
|
||||||
|
onMouseOut={handleMouseOut}
|
||||||
|
>
|
||||||
{image}
|
{image}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Link to={url} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
|
<Link to={url} onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>
|
||||||
{image}
|
<img style={{ verticalAlign: 'middle' }} src={image} alt={title} title={title} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default LinkImage;
|
export default LinkImage;
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import Spinner from "react-spinner-material";
|
|
||||||
|
import Spinner from 'react-spinner-material';
|
||||||
|
|
||||||
const Loading: React.FC = () => {
|
const Loading: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", justifyContent: "center", alignContent: "center", margin: "100px 0" }}>
|
<div
|
||||||
<Spinner radius={60} color={"#cccccc"} stroke={8} visible={true} />
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignContent: 'center',
|
||||||
|
margin: '100px 0',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Spinner radius={60} color={'#cccccc'} stroke={8} visible={true} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../config";
|
|
||||||
import Functions from "../../functions";
|
import { MultiLang } from '../../config';
|
||||||
|
import Functions from '../../functions';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NoticeSiteHasBeenArchived: React.FC<Props> = (props: Props) => {
|
const NoticeSiteHasBeenArchived: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
const notice = "[en]This site has been archived since FY2019 and is no longer updated.[/en][ja]このサイトは、2019年度よりアーカイブサイトとして運用されています。[/ja]";
|
const notice =
|
||||||
return <p style={{ color: "red" }}>{Functions.mlang(notice, lang)}</p>;
|
'[en]This site has been archived since FY2019 and is no longer updated.[/en][ja]このサイトは、2019年度よりアーカイブサイトとして運用されています。[/ja]';
|
||||||
|
return <p style={{ color: 'red' }}>{Functions.mlang(notice, lang)}</p>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NoticeSiteHasBeenArchived;
|
export default NoticeSiteHasBeenArchived;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useEffect } from "react";
|
import React from 'react';
|
||||||
import { Helmet } from "react-helmet-async";
|
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { MultiLang } from "../../config";
|
import { MultiLang } from '../../config';
|
||||||
import Functions from "../../functions";
|
import Functions from '../../functions';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -10,26 +10,7 @@ interface Props {
|
|||||||
|
|
||||||
const PageNotFound: React.FC<Props> = (props) => {
|
const PageNotFound: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
const location = useLocation();
|
const url = '/';
|
||||||
const navigate = useNavigate();
|
|
||||||
const url = "/";
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let timer: NodeJS.Timeout | null = null;
|
|
||||||
if (location.pathname !== "/" && process.env.NODE_ENV === 'production') {
|
|
||||||
if (timer === null) {
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
navigate(url);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
if (timer !== null) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [location, navigate]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -38,7 +19,7 @@ const PageNotFound: React.FC<Props> = (props) => {
|
|||||||
</Helmet>
|
</Helmet>
|
||||||
<h1>Page Not Found</h1>
|
<h1>Page Not Found</h1>
|
||||||
<section>
|
<section>
|
||||||
<p>The page you were trying to access doesn't exist.</p>
|
<p>The page you were trying to access doesn't exist.</p>
|
||||||
<p>
|
<p>
|
||||||
If the page does not automatically reload, please click <a href={url}>here</a>
|
If the page does not automatically reload, please click <a href={url}>here</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../config";
|
|
||||||
import Functions from "../../functions";
|
import { MultiLang } from '../../config';
|
||||||
import imageRank2 from "../assets/images/rank3dbf8e94a6f72.gif";
|
import Functions from '../../functions';
|
||||||
import imageRank3 from "../assets/images/rank3dbf8e9e7d88d.gif";
|
|
||||||
import imageRank4 from "../assets/images/rank3dbf8ea81e642.gif";
|
import imageRank2 from '../assets/images/rank3dbf8e94a6f72.gif';
|
||||||
import imageRank5 from "../assets/images/rank3dbf8eb1a72e7.gif";
|
import imageRank3 from '../assets/images/rank3dbf8e9e7d88d.gif';
|
||||||
import imageRank6 from "../assets/images/rank3dbf8edf15093.gif";
|
import imageRank4 from '../assets/images/rank3dbf8ea81e642.gif';
|
||||||
import imageRank7 from "../assets/images/rank3dbf8ee8681cd.gif";
|
import imageRank5 from '../assets/images/rank3dbf8eb1a72e7.gif';
|
||||||
import imageRank1 from "../assets/images/rank3e632f95e81ca.gif";
|
import imageRank6 from '../assets/images/rank3dbf8edf15093.gif';
|
||||||
|
import imageRank7 from '../assets/images/rank3dbf8ee8681cd.gif';
|
||||||
|
import imageRank1 from '../assets/images/rank3e632f95e81ca.gif';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -16,16 +18,52 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userRanks = [
|
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]Just popping in[/en][ja]新米[/ja]',
|
||||||
{ title: "[en]Quite a regular[/en][ja]常連[/ja]", min: 41, max: 70, special: false, image: imageRank3 },
|
min: 0,
|
||||||
{ title: "[en]Just can't stay away[/en][ja]一人前[/ja]", min: 71, max: 150, special: false, image: imageRank4 },
|
max: 20,
|
||||||
{ title: "[en]Home away from home[/en][ja]長老[/ja]", min: 151, max: 10000, special: false, image: imageRank5 },
|
special: false,
|
||||||
{ title: "[en]Moderator[/en][ja]モデレータ[/ja]", min: 0, max: 0, special: true, image: imageRank6 },
|
image: imageRank1,
|
||||||
{ title: "[en]Webmaster[/en][ja]管理人[/ja]", min: 0, max: 0, special: true, image: imageRank7 },
|
},
|
||||||
|
{
|
||||||
|
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: React.FC<Props> = (props: Props) => {
|
const UserRankStarImage: React.FC<Props> = (props) => {
|
||||||
const { lang, rank, posts } = props;
|
const { lang, rank, posts } = props;
|
||||||
const findRank = (posts: number) => {
|
const findRank = (posts: number) => {
|
||||||
const rank = userRanks.find((userRank) => {
|
const rank = userRanks.find((userRank) => {
|
||||||
@ -34,7 +72,7 @@ const UserRankStarImage: React.FC<Props> = (props: Props) => {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
return typeof rank !== "undefined" ? rank : userRanks[0];
|
return typeof rank !== 'undefined' ? rank : userRanks[0];
|
||||||
};
|
};
|
||||||
const userRank = rank > 0 && rank <= 7 ? userRanks[rank - 1] : findRank(posts);
|
const userRank = rank > 0 && rank <= 7 ? userRanks[rank - 1] : findRank(posts);
|
||||||
const title = Functions.mlang(userRank.title, lang);
|
const title = Functions.mlang(userRank.title, lang);
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import ReactHtmlParser, { convertNodeToElement, DomElement, DomNode, Transform } from "@orrisroot/react-html-parser";
|
import React from 'react';
|
||||||
import React from "react";
|
|
||||||
import { HashLink } from "react-router-hash-link";
|
import ReactHtmlParser, {
|
||||||
import { MultiLang } from "../../config";
|
convertNodeToElement,
|
||||||
import Functions from "../../functions";
|
DomElement,
|
||||||
|
DomNode,
|
||||||
|
Transform,
|
||||||
|
} from '@orrisroot/react-html-parser';
|
||||||
|
import { ElementType } from 'htmlparser2';
|
||||||
|
import { HashLink } from 'react-router-hash-link';
|
||||||
|
import { MultiLang } from '../../config';
|
||||||
|
import Functions from '../../functions';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -16,8 +23,8 @@ interface Props {
|
|||||||
|
|
||||||
const preConvertXCode = (text: string, doxcode: boolean): string => {
|
const preConvertXCode = (text: string, doxcode: boolean): string => {
|
||||||
if (doxcode) {
|
if (doxcode) {
|
||||||
return text.replace(/\[code\](.*)\[\/code\]/gs, (m0, m1) => {
|
return text.replace(/\[code\](.*)\[\/code\]/gs, (_: string, m1: string) => {
|
||||||
return "[code]" + Functions.base64Encode(m1) + "[/code]";
|
return '[code]' + Functions.base64Encode(m1) + '[/code]';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
@ -25,26 +32,42 @@ const preConvertXCode = (text: string, doxcode: boolean): string => {
|
|||||||
|
|
||||||
const postConvertXCode = (text: string, doxcode: boolean, doimage: boolean): string => {
|
const postConvertXCode = (text: string, doxcode: boolean, doimage: boolean): string => {
|
||||||
if (doxcode) {
|
if (doxcode) {
|
||||||
return text.replace(/\[code\](.*)\[\/code\]/gs, (m0, m1) => {
|
return text.replace(/\[code\](.*)\[\/code\]/gs, (_: string, m1: string) => {
|
||||||
const text = convertXCode(Functions.htmlspecialchars(Functions.base64Decode(m1)), doimage);
|
const text = convertXCode(Functions.htmlspecialchars(Functions.base64Decode(m1)), doimage);
|
||||||
return '<div class="xoopsCode"><pre><code>' + text + "</code></pre></div>";
|
return '<div class="xoopsCode"><pre><code>' + text + '</code></pre></div>';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
const convertClickable = (text: string) => {
|
const convertClickable = (text: string) => {
|
||||||
text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+[a-zA-Z0-9=]))/g, (...matches) => {
|
text = text.replace(
|
||||||
return matches[1] + '<a href="' + matches[2] + '" target="_blank" rel="external noopener noreferrer">' + matches[2] + "</a>";
|
/(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+[a-zA-Z0-9=]))/g,
|
||||||
});
|
(...matches) => {
|
||||||
text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/:.]+)([a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+)/g, (...matches) => {
|
return (
|
||||||
return matches[1] + '<a href="mailto:' + matches[2] + '">' + matches[2] + "</a>";
|
matches[1] +
|
||||||
});
|
'<a href="' +
|
||||||
|
matches[2] +
|
||||||
|
'" target="_blank" rel="external noopener noreferrer">' +
|
||||||
|
matches[2] +
|
||||||
|
'</a>'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
text = text.replace(
|
||||||
|
/(^|[^\]_a-zA-Z0-9-="'/:.]+)([a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+)/g,
|
||||||
|
(...matches) => {
|
||||||
|
return matches[1] + '<a href="mailto:' + matches[2] + '">' + matches[2] + '</a>';
|
||||||
|
},
|
||||||
|
);
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
const convertXCode = (text: string, doimage: boolean): string => {
|
const convertXCode = (text: string, doimage: boolean): string => {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
|
if (doimage) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,17 +77,17 @@ const convertSmiley = (text: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const convertBr = (text: string): string => {
|
const convertBr = (text: string): string => {
|
||||||
return text.replace(/(\r?\n|\r)/g, "<br />");
|
return text.replace(/(\r?\n|\r)/g, '<br />');
|
||||||
};
|
};
|
||||||
|
|
||||||
const cssConvert = (text: string): object => {
|
const cssConvert = (text: string): Record<string, string> => {
|
||||||
const ret: any = {};
|
const ret: Record<string, string> = {};
|
||||||
text.split(";").forEach((line) => {
|
text.split(';').forEach((line) => {
|
||||||
const line_ = line.trim();
|
const line_ = line.trim();
|
||||||
if (line.length === 0) {
|
if (line.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const kv = line_.split(":");
|
const kv = line_.split(':');
|
||||||
const key = Functions.camelCase(kv[0].trim());
|
const key = Functions.camelCase(kv[0].trim());
|
||||||
const value = kv[1].trim();
|
const value = kv[1].trim();
|
||||||
ret[key] = value;
|
ret[key] = value;
|
||||||
@ -72,19 +95,24 @@ const cssConvert = (text: string): object => {
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
const xoopsTransform: Transform = (node: DomNode, index: number | string, transform?: Transform): React.ReactNode => {
|
const xoopsTransform: Transform = (
|
||||||
if (node.type === "tag") {
|
node: DomNode,
|
||||||
|
index: number | string,
|
||||||
|
transform?: Transform,
|
||||||
|
): React.ReactNode => {
|
||||||
|
if (node.type === ElementType.Tag) {
|
||||||
const node_ = node as DomElement;
|
const node_ = node as DomElement;
|
||||||
if (node_.name === "a") {
|
if (node_.name === 'a') {
|
||||||
const url = node_.attribs?.["href"] || "/";
|
const url = node_.attribs?.href ?? '/';
|
||||||
const download = (node_.attribs && node_.attribs["download"]) || "";
|
const download = node_.attribs?.download ?? '';
|
||||||
const rel = (node_.attribs && node_.attribs["rel"]) || "";
|
const rel = node_.attribs?.rel ?? '';
|
||||||
const klass = (node_.attribs && node_.attribs["class"]) || "";
|
const className = node_.attribs?.class ?? '';
|
||||||
const isFile = download !== "" || /\.(zip|pdf|png|gif|jpg)$/.test(url);
|
const isFile = download !== '' || /\.(zip|pdf|png|gif|jpg)$/.test(url);
|
||||||
const isExternal = /external/.test(rel) || /external/.test(klass) || /^(mailto|https?:?\/\/)/.test(url);
|
const isExternal =
|
||||||
|
/external/.test(rel) || /external/.test(className) || /^(mailto|https?:?\/\/)/.test(url);
|
||||||
if (!isFile && !isExternal) {
|
if (!isFile && !isExternal) {
|
||||||
const style = node_.attribs?.["style"] || "";
|
const style = node_.attribs?.style || '';
|
||||||
const title = node_.attribs?.["title"];
|
const title = node_.attribs?.title;
|
||||||
return (
|
return (
|
||||||
<HashLink key={index} to={url} style={cssConvert(style)} title={title}>
|
<HashLink key={index} to={url} style={cssConvert(style)} title={title}>
|
||||||
{node_.children.map((value: DomNode, index: number) => {
|
{node_.children.map((value: DomNode, index: number) => {
|
||||||
@ -94,15 +122,15 @@ const xoopsTransform: Transform = (node: DomNode, index: number | string, transf
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node_.name === "img") {
|
if (node_.name === 'img') {
|
||||||
const src = (node_.attribs && node_.attribs["src"]) || "";
|
const src = node_.attribs?.src ?? '';
|
||||||
node_.attribs["src"] = src.replace("`XOOPS_URL`", process.env.PUBLIC_URL);
|
node_.attribs.src = src.replace('`XOOPS_URL`', '/');
|
||||||
return convertNodeToElement(node_, index, transform);
|
return convertNodeToElement(node_, index, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const XoopsCode: React.FC<Props> = (props: Props) => {
|
const XoopsCode: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
let text = props.text;
|
let text = props.text;
|
||||||
const dohtml = !!props.dohtml;
|
const dohtml = !!props.dohtml;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
const SITE_TITLE = "BSI-NI Brain Atlas";
|
const SITE_TITLE = 'BSI-NI Brain Atlas';
|
||||||
const SITE_SLOGAN = "Welcome to BRAIN ATLAS";
|
const SITE_SLOGAN = 'Welcome to BRAIN ATLAS';
|
||||||
const GOOGLE_ANALYTICS_TRACKING_ID = "";
|
const GOOGLE_ANALYTICS_TRACKING_ID = '';
|
||||||
const XOONIPS_ITEMTYPES = ["files", "url", "paper", "book"];
|
const XOONIPS_ITEMTYPES = ['files', 'url', 'paper', 'book'];
|
||||||
|
|
||||||
export type MultiLang = "en" | "ja";
|
export type MultiLang = 'en' | 'ja';
|
||||||
|
|
||||||
export type BrainAtlasType = "degu" | "jm" | "marmoset";
|
export type BrainAtlasType = 'degu' | 'jm' | 'marmoset';
|
||||||
export const BrainAtlasTypes: ReadonlyArray<BrainAtlasType> = ["degu", "jm", "marmoset"];
|
export const BrainAtlasTypes: readonly BrainAtlasType[] = ['degu', 'jm', 'marmoset'];
|
||||||
|
|
||||||
const Config = {
|
const Config = {
|
||||||
SITE_TITLE,
|
SITE_TITLE,
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import PageNotFound from "../common/lib/PageNotFound";
|
import { Link } from 'react-router-dom';
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
import PageNotFound from '../common/lib/PageNotFound';
|
||||||
import styles from "./CoverPage.module.css";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
import styles from './CoverPage.module.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoverPage: React.FC<Props> = (props: Props) => {
|
const CoverPage: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
const links = [
|
const links = [
|
||||||
{ title: "Marmoset-3D Brain Atlas", url: "/marmoset/modules/xoonips/listitem.php?index_id=66" },
|
{ title: 'Marmoset-3D Brain Atlas', url: '/marmoset/modules/xoonips/listitem.php?index_id=66' },
|
||||||
{ title: "Marmoset-the MRI Standard Brain", url: "/marmoset/modules/xoonips/listitem.php?index_id=71" },
|
{
|
||||||
|
title: 'Marmoset-the MRI Standard Brain',
|
||||||
|
url: '/marmoset/modules/xoonips/listitem.php?index_id=71',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
if (type !== "marmoset") {
|
if (type !== 'marmoset') {
|
||||||
return <PageNotFound lang={lang} />;
|
return <PageNotFound lang={lang} />;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -1,22 +1,29 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import styles from "./RelatedLink.module.css";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
import styles from './RelatedLink.module.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RelatedLink: React.FC<Props> = (props: Props) => {
|
const RelatedLink: React.FC<Props> = (props) => {
|
||||||
const { type } = props;
|
const { type } = props;
|
||||||
const links = {
|
const links = {
|
||||||
degu: [{ title: "RIKEN BSI", url: "http://www.brain.riken.jp/" }],
|
degu: [{ title: 'RIKEN BSI', url: 'http://www.brain.riken.jp/' }],
|
||||||
jm: [{ title: "RIKEN BSI", url: "http://www.brain.riken.jp/" }],
|
jm: [{ title: 'RIKEN BSI', url: 'http://www.brain.riken.jp/' }],
|
||||||
marmoset: [
|
marmoset: [
|
||||||
{ title: "RIKEN BSI", url: "http://www.brain.riken.jp/" },
|
{ title: 'RIKEN BSI', url: 'http://www.brain.riken.jp/' },
|
||||||
{ title: "Keio-RIKEN Research centre for Human Congnition", url: "http://human-cognition.keio.ac.jp/english/" },
|
{
|
||||||
{ title: "FIRST project", url: "http://www.brain.riken.jp/first-okano/en/index.html" },
|
title: 'Keio-RIKEN Research centre for Human Cognition',
|
||||||
{ title: "Press release", url: "http://www.brain.riken.jp/first-okano/en/achievements/2010/papers.html" },
|
url: 'http://human-cognition.keio.ac.jp/english/',
|
||||||
|
},
|
||||||
|
{ title: 'FIRST project', url: 'http://www.brain.riken.jp/first-okano/en/index.html' },
|
||||||
|
{
|
||||||
|
title: 'Press release',
|
||||||
|
url: 'http://www.brain.riken.jp/first-okano/en/achievements/2010/papers.html',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import NoticeSiteHasBeenArchived from "../common/lib/NoticeSiteHasBeenArchived";
|
import { Link } from 'react-router-dom';
|
||||||
import { MultiLang } from "../config";
|
import NoticeSiteHasBeenArchived from '../common/lib/NoticeSiteHasBeenArchived';
|
||||||
import styles from "./SiteIndex.module.css";
|
import { MultiLang } from '../config';
|
||||||
|
import styles from './SiteIndex.module.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SiteIndex: React.FC<Props> = (props: Props) => {
|
const SiteIndex: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.siteIndex}>
|
<div className={styles.siteIndex}>
|
||||||
@ -29,7 +30,10 @@ const SiteIndex: React.FC<Props> = (props: Props) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className={styles.jm}>
|
<li className={styles.jm}>
|
||||||
<Link to="/jm/modules/xoonips/listitem.php?index_id=9" title="Japanese Macaque Monkey">
|
<Link
|
||||||
|
to="/jm/modules/xoonips/listitem.php?index_id=9"
|
||||||
|
title="Japanese Macaque Monkey"
|
||||||
|
>
|
||||||
<span>Japanese Macaque Monkey</span>
|
<span>Japanese Macaque Monkey</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,88 +1,102 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Helmet } from "react-helmet-async";
|
|
||||||
import { Route, Routes, useLocation } from "react-router-dom";
|
import { Helmet } from 'react-helmet-async';
|
||||||
import PageNotFound from "../common/lib/PageNotFound";
|
import { Route, Routes, useLocation } from 'react-router-dom';
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
import PageNotFound from '../common/lib/PageNotFound';
|
||||||
import Functions from "../functions";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
import styles from "./Database.module.css";
|
import Functions from '../functions';
|
||||||
import DatabaseAdvancedSearch from "./DatabaseAdvancedSearch";
|
import styles from './Database.module.css';
|
||||||
import DatabaseDetailItem from "./DatabaseDetailItem";
|
import DatabaseAdvancedSearch from './DatabaseAdvancedSearch';
|
||||||
import DatabaseSearchByAdvancedKeyword from "./DatabaseSearchByAdvancedKeyword";
|
import DatabaseDetailItem from './DatabaseDetailItem';
|
||||||
import DatabaseSearchByIndexId from "./DatabaseSearchByIndexId";
|
import DatabaseSearchByAdvancedKeyword from './DatabaseSearchByAdvancedKeyword';
|
||||||
import DatabaseSearchByItemType from "./DatabaseSearchByItemType";
|
import DatabaseSearchByIndexId from './DatabaseSearchByIndexId';
|
||||||
import DatabaseSearchByKeyword from "./DatabaseSearchByKeyword";
|
import DatabaseSearchByItemType from './DatabaseSearchByItemType';
|
||||||
import DatabaseTop from "./DatabaseTop";
|
import DatabaseSearchByKeyword from './DatabaseSearchByKeyword';
|
||||||
import { INDEX_ID_PUBLIC } from "./lib/IndexUtil";
|
import DatabaseTop from './DatabaseTop';
|
||||||
|
import { INDEX_ID_PUBLIC } from './lib/IndexUtil';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ItemDetail: React.FC<Props> = (props: Props) => {
|
const ItemDetail: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const itemId_ = params.get("item_id") || "";
|
const itemId_ = params.get('item_id') ?? '';
|
||||||
const itemId = /^\d+$/.test(itemId_) ? parseInt(itemId_, 10) : 0;
|
const itemId = /^\d+$/.test(itemId_) ? parseInt(itemId_, 10) : 0;
|
||||||
const doi = params.get("id") || "";
|
const doi = params.get('id') ?? '';
|
||||||
return <DatabaseDetailItem lang={lang} id={itemId} doi={doi} type={type} />;
|
return <DatabaseDetailItem lang={lang} id={itemId} doi={doi} type={type} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ItemList: React.FC<Props> = (props: Props) => {
|
const ItemList: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const id = params.get("index_id") || "";
|
const id = params.get('index_id') ?? '';
|
||||||
const indexId = /^\d+$/.test(id) ? parseInt(id, 10) : INDEX_ID_PUBLIC;
|
const indexId = /^\d+$/.test(id) ? parseInt(id, 10) : INDEX_ID_PUBLIC;
|
||||||
return <DatabaseSearchByIndexId lang={lang} type={type} indexId={indexId} />;
|
return <DatabaseSearchByIndexId lang={lang} type={type} indexId={indexId} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ItemSelect: React.FC<Props> = (props: Props) => {
|
const ItemSelect: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const op = params.get("op") || "";
|
const op = params.get('op') ?? '';
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case "itemtypesearch": {
|
case 'itemtypesearch': {
|
||||||
const searchItemtype = params.get("search_itemtype") || "";
|
const searchItemtype = params.get('search_itemtype') ?? '';
|
||||||
const match = searchItemtype.match(/^xnp([a-z]+)$/);
|
const match = searchItemtype.match(/^xnp([a-z]+)$/);
|
||||||
const itemType = match !== null ? match[1] : "";
|
const itemType = match !== null ? match[1] : '';
|
||||||
return <DatabaseSearchByItemType lang={lang} itemType={itemType} subItemType="" type={type} />;
|
return (
|
||||||
|
<DatabaseSearchByItemType lang={lang} itemType={itemType} subItemType="" type={type} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
case "itemsubtypesearch": {
|
case 'itemsubtypesearch': {
|
||||||
const searchItemtype = params.get("search_itemtype") || "";
|
const searchItemtype = params.get('search_itemtype') ?? '';
|
||||||
const match = searchItemtype.match(/^xnp([a-z]+)$/);
|
const match = searchItemtype.match(/^xnp([a-z]+)$/);
|
||||||
const itemType = match !== null ? match[1] : "";
|
const itemType = match !== null ? match[1] : '';
|
||||||
const subItemtype = params.get("search_subitemtype") || "";
|
const subItemtype = params.get('search_subitemtype') ?? '';
|
||||||
return <DatabaseSearchByItemType lang={lang} itemType={itemType} subItemType={subItemtype} type={type} />;
|
return (
|
||||||
|
<DatabaseSearchByItemType
|
||||||
|
lang={lang}
|
||||||
|
itemType={itemType}
|
||||||
|
subItemType={subItemtype}
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
case "quicksearch": {
|
case 'quicksearch': {
|
||||||
return <DatabaseSearchByKeyword lang={lang} type={type} />;
|
return <DatabaseSearchByKeyword lang={lang} type={type} />;
|
||||||
}
|
}
|
||||||
case "advanced": {
|
case 'advanced': {
|
||||||
return <DatabaseSearchByAdvancedKeyword lang={lang} type={type} />;
|
return <DatabaseSearchByAdvancedKeyword lang={lang} type={type} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <PageNotFound lang={lang} />;
|
return <PageNotFound lang={lang} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Database: React.FC<Props> = (props: Props) => {
|
const Database: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.database}>
|
<div className={styles.database}>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>
|
<title>
|
||||||
{Functions.mlang("[en]Database[/en][ja]データベース[/ja]", lang)} - {Functions.siteTitle(lang)}
|
{Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} -{' '}
|
||||||
|
{Functions.siteTitle(lang)}
|
||||||
</title>
|
</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route index element={<DatabaseTop lang={lang} type={type} />} />
|
<Route index element={<DatabaseTop lang={lang} type={type} />} />
|
||||||
<Route path="index.php" element={<DatabaseTop lang={lang} type={type} />} />
|
<Route path="index" element={<DatabaseTop lang={lang} type={type} />} />
|
||||||
<Route path="detail.php" element={<ItemDetail lang={lang} type={type} />} />
|
<Route path="detail.php" element={<ItemDetail lang={lang} type={type} />} />
|
||||||
<Route path="listitem.php" element={<ItemList lang={lang} type={type} />} />
|
<Route path="listitem.php" element={<ItemList lang={lang} type={type} />} />
|
||||||
<Route path="itemselect.php" element={<ItemSelect lang={lang} type={type} />} />
|
<Route path="itemselect.php" element={<ItemSelect lang={lang} type={type} />} />
|
||||||
<Route path="advanced_search.php" element={<DatabaseAdvancedSearch lang={lang} type={type} />} />
|
<Route
|
||||||
|
path="advanced_search.php"
|
||||||
|
element={<DatabaseAdvancedSearch lang={lang} type={type} />}
|
||||||
|
/>
|
||||||
<Route path="*" element={<PageNotFound lang={lang} />} />
|
<Route path="*" element={<PageNotFound lang={lang} />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,63 +1,47 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import Config, { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import Functions from "../functions";
|
|
||||||
import ItemType from "./item-type";
|
|
||||||
import AdvancedSearchQuery from "./lib/AdvancedSearchQuery";
|
|
||||||
import ItemUtil from "./lib/ItemUtil";
|
|
||||||
|
|
||||||
interface PropsFC {
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import Config, { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
import Functions from '../functions';
|
||||||
|
import ItemType from './item-type';
|
||||||
|
import AdvancedSearchQuery from './lib/AdvancedSearchQuery';
|
||||||
|
import ItemUtil from './lib/ItemUtil';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends PropsFC {
|
const DatabaseAdvancedSearch: React.FC<Props> = (props) => {
|
||||||
navigate: any;
|
const { lang, type } = props;
|
||||||
}
|
const query = new AdvancedSearchQuery();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
class DatabaseAdvancedSearch extends React.Component<Props> {
|
const handleClickSearchButton = () => {
|
||||||
private query: AdvancedSearchQuery = new AdvancedSearchQuery();
|
if (!query.empty()) {
|
||||||
|
const url = ItemUtil.getSearchByAdvancedKeywordsUrl(type, query);
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
this.handleClickSearchButton = this.handleClickSearchButton.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClickSearchButton() {
|
|
||||||
const { type, navigate } = this.props;
|
|
||||||
if (!this.query.empty()) {
|
|
||||||
const url = ItemUtil.getSearchByAdvancedKeywordsUrl(type, this.query);
|
|
||||||
navigate(url);
|
navigate(url);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="advancedSearch">
|
<div className="advancedSearch">
|
||||||
<h3>{Functions.mlang("[en]Search Items[/en][ja]アイテム検索[/ja]", lang)}</h3>
|
<h3>{Functions.mlang('[en]Search Items[/en][ja]アイテム検索[/ja]', lang)}</h3>
|
||||||
<div className="search">
|
<div className="search">
|
||||||
<button className="formButton" onClick={this.handleClickSearchButton}>
|
<button className="formButton" onClick={handleClickSearchButton}>
|
||||||
Search
|
Search
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{Config.XOONIPS_ITEMTYPES.map((type) => {
|
{Config.XOONIPS_ITEMTYPES.map((type) => {
|
||||||
return <ItemType.AdvancedSearch key={type} type={"xnp" + type} lang={lang} query={this.query} />;
|
return <ItemType.AdvancedSearch key={type} type={`xnp${type}`} lang={lang} query={query} />;
|
||||||
})}
|
})}
|
||||||
<div className="search">
|
<div className="search">
|
||||||
<button className="formButton" onClick={this.handleClickSearchButton}>
|
<button className="formButton" onClick={handleClickSearchButton}>
|
||||||
Search
|
Search
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DatabaseAdvancedSearchFC: React.FC<PropsFC> = (props: PropsFC) => {
|
|
||||||
const { lang, type } = props;
|
|
||||||
return <DatabaseAdvancedSearch lang={lang} type={type} navigate={useNavigate()} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DatabaseAdvancedSearchFC;
|
export default DatabaseAdvancedSearch;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Helmet } from "react-helmet-async";
|
|
||||||
import Loading from "../common/lib/Loading";
|
import { Helmet } from 'react-helmet-async';
|
||||||
import PageNotFound from "../common/lib/PageNotFound";
|
import Loading from '../common/lib/Loading';
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
import PageNotFound from '../common/lib/PageNotFound';
|
||||||
import Functions from "../functions";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
import ItemType from "./item-type";
|
import Functions from '../functions';
|
||||||
import ItemUtil, { Item } from "./lib/ItemUtil";
|
import ItemType from './item-type';
|
||||||
|
import ItemUtil, { Item } from './lib/ItemUtil';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -14,65 +15,49 @@ interface Props {
|
|||||||
doi: string;
|
doi: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const DatabaseDetailItem: React.FC<Props> = (props) => {
|
||||||
loading: boolean;
|
const { lang, type, id, doi } = props;
|
||||||
item: Item | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DatabaseDetailItem extends React.Component<Props, State> {
|
const [loading, setLoading] = React.useState<boolean>(true);
|
||||||
constructor(props: Props) {
|
const [item, setItem] = React.useState<Item | null>(null);
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
loading: true,
|
|
||||||
item: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
React.useEffect(() => {
|
||||||
this.updateItem();
|
if (doi !== '') {
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props, prevState: State) {
|
|
||||||
const { id, doi } = this.props;
|
|
||||||
if (id !== prevProps.id || doi !== prevProps.doi) {
|
|
||||||
this.updateItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateItem() {
|
|
||||||
const { id, doi, type } = this.props;
|
|
||||||
if (doi !== "") {
|
|
||||||
ItemUtil.getByDoi(type, doi, (item) => {
|
ItemUtil.getByDoi(type, doi, (item) => {
|
||||||
this.setState({ loading: false, item });
|
setItem(item);
|
||||||
|
setLoading(false);
|
||||||
});
|
});
|
||||||
} else if (id !== 0) {
|
} else if (id !== 0) {
|
||||||
ItemUtil.get(type, id, (item) => {
|
ItemUtil.get(type, id, (item) => {
|
||||||
this.setState({ loading: false, item });
|
setItem(item);
|
||||||
|
setLoading(false);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setLoading(true);
|
||||||
}
|
}
|
||||||
}
|
}, [type, id, doi]);
|
||||||
|
|
||||||
render() {
|
if (loading) {
|
||||||
const { lang, type } = this.props;
|
|
||||||
if (this.state.loading) {
|
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
if (this.state.item === null) {
|
if (item === null) {
|
||||||
return <PageNotFound lang={lang} />;
|
return <PageNotFound lang={lang} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>
|
<title>
|
||||||
{Functions.mlang(this.state.item.title, lang)} - {Functions.mlang("[en]Database[/en][ja]データベース[/ja]", lang)} - {Functions.siteTitle(lang)}
|
{Functions.mlang(item.title, lang)} -{' '}
|
||||||
|
{Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} -{' '}
|
||||||
|
{Functions.siteTitle(lang)}
|
||||||
</title>
|
</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<h3>{Functions.mlang("[en]Detail[/en][ja]詳細[/ja]", lang)}</h3>
|
<h3>{Functions.mlang('[en]Detail[/en][ja]詳細[/ja]', lang)}</h3>
|
||||||
<br />
|
<br />
|
||||||
<ItemType.Detail lang={lang} item={this.state.item} type={type} />
|
<ItemType.Detail lang={lang} item={item} type={type} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default DatabaseDetailItem;
|
export default DatabaseDetailItem;
|
||||||
|
@ -1,67 +1,32 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { useLocation } from "react-router-dom";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import AdvancedSearchQuery from "./lib/AdvancedSearchQuery";
|
|
||||||
import DatabaseListItem from "./lib/DatabaseListItem";
|
|
||||||
import ItemUtil, { SearchCallbackFunc, SortCondition } from "./lib/ItemUtil";
|
|
||||||
|
|
||||||
interface PropsFC {
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
import DatabaseListItem from './lib/DatabaseListItem';
|
||||||
|
import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends PropsFC {
|
const DatabaseSearchByAdvancedKeyword: React.FC<Props> = (props) => {
|
||||||
location: any;
|
const { lang, type } = props;
|
||||||
}
|
const location = useLocation();
|
||||||
|
const query = ItemUtil.getAdvancedSearchQueryByQuery(location.search);
|
||||||
|
|
||||||
interface State {
|
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
|
||||||
search: string;
|
ItemUtil.getListByAdvancedSearchQuery(type, query, condition, func);
|
||||||
query: AdvancedSearchQuery;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
class DatabaseSearchByAdvancedKeyword extends React.Component<Props, State> {
|
const baseUrl = ItemUtil.getSearchByAdvancedKeywordsUrl(type, query);
|
||||||
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() {
|
|
||||||
const { type } = this.props;
|
|
||||||
return ItemUtil.getSearchByAdvancedKeywordsUrl(type, this.state.query);
|
|
||||||
}
|
|
||||||
|
|
||||||
searchFunc(condition: SortCondition, func: SearchCallbackFunc) {
|
|
||||||
const { type } = this.props;
|
|
||||||
ItemUtil.getListByAdvancedSearchQuery(type, this.state.query, condition, func);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang, type } = this.props;
|
|
||||||
const baseUrl = this.getUrl();
|
|
||||||
return (
|
return (
|
||||||
<div className="list">
|
<div className="list">
|
||||||
<h3>Listing item</h3>
|
<h3>Listing item</h3>
|
||||||
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} type={type} />
|
<DatabaseListItem lang={lang} url={baseUrl} search={searchFunc} type={type} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DatabaseSearchByAdvancedKeywordFC: React.FC<PropsFC> = (props: PropsFC) => {
|
|
||||||
const { lang, type } = props;
|
|
||||||
return <DatabaseSearchByAdvancedKeyword lang={lang} type={type} location={useLocation()} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DatabaseSearchByAdvancedKeywordFC;
|
export default DatabaseSearchByAdvancedKeyword;
|
||||||
|
@ -1,80 +1,92 @@
|
|||||||
import React, { Fragment } from "react";
|
import React from 'react';
|
||||||
import { Helmet } from "react-helmet-async";
|
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import PageNotFound from "../common/lib/PageNotFound";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import Functions from "../functions";
|
|
||||||
import DatabaseListIndex from "./lib/DatabaseListIndex";
|
|
||||||
import DatabaseListItem from "./lib/DatabaseListItem";
|
|
||||||
import IndexUtil, { Index } from "./lib/IndexUtil";
|
|
||||||
import ItemUtil, { SearchCallbackFunc, SortCondition } from "./lib/ItemUtil";
|
|
||||||
|
|
||||||
export interface Props {
|
import { Helmet } from 'react-helmet-async';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import Loading from '../common/lib/Loading';
|
||||||
|
import PageNotFound from '../common/lib/PageNotFound';
|
||||||
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
import Functions from '../functions';
|
||||||
|
import DatabaseListIndex from './lib/DatabaseListIndex';
|
||||||
|
import DatabaseListItem from './lib/DatabaseListItem';
|
||||||
|
import IndexUtil, { Index } from './lib/IndexUtil';
|
||||||
|
import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
indexId: number;
|
indexId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DatabaseSearchByIndexId extends React.Component<Props> {
|
const DatabaseSearchByIndexId: React.FC<Props> = (props) => {
|
||||||
constructor(props: Props) {
|
const { lang, type, indexId } = props;
|
||||||
super(props);
|
|
||||||
this.searchFunc = this.searchFunc.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUrl() {
|
const [notFound, setNotFound] = React.useState<boolean>(false);
|
||||||
const { type, indexId } = this.props;
|
const [index, setIndex] = React.useState<Index | null>(null);
|
||||||
if (indexId === 0) {
|
const [parents, setParents] = React.useState<{ title: string; node: React.ReactNode }>({
|
||||||
return "/";
|
title: '',
|
||||||
}
|
node: null,
|
||||||
return IndexUtil.getUrl(type, indexId);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
searchFunc(condition: SortCondition, func: SearchCallbackFunc) {
|
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
|
||||||
const { type, indexId } = this.props;
|
|
||||||
if (indexId === 0) {
|
if (indexId === 0) {
|
||||||
const res = { total: 0, data: [] };
|
const res = { total: 0, data: [] };
|
||||||
func(res);
|
func(res);
|
||||||
} else {
|
} else {
|
||||||
ItemUtil.getListByIndexId(type, indexId, condition, func);
|
ItemUtil.getListByIndexId(type, indexId, condition, func);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
React.useEffect(() => {
|
||||||
const { lang, type, indexId } = this.props;
|
IndexUtil.get(type, indexId, (index) => {
|
||||||
const index = IndexUtil.get(type, indexId);
|
setIndex(index);
|
||||||
if (index === null) {
|
if (index == null) {
|
||||||
return <PageNotFound lang={lang} />;
|
setNotFound(true);
|
||||||
}
|
} else {
|
||||||
const baseUrl = this.getUrl();
|
IndexUtil.getParents(type, indexId, (pIndexes) => {
|
||||||
const pIndexes = IndexUtil.getParents(type, indexId);
|
const parents = pIndexes.map((index: Index) => {
|
||||||
const parents = pIndexes.map((value: Index) => {
|
const url: string = IndexUtil.getUrl(type, index.id);
|
||||||
const url: string = IndexUtil.getUrl(type, value.id);
|
const title = Functions.mlang(index.title, lang);
|
||||||
const title = Functions.mlang(value.title, lang);
|
|
||||||
return (
|
return (
|
||||||
<Fragment key={value.id}>
|
<React.Fragment key={index.id}>
|
||||||
/ <Link to={url}>{title}</Link>{" "}
|
/ <Link to={url}>{title}</Link>{' '}
|
||||||
</Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const title = pIndexes
|
const title = pIndexes
|
||||||
.map((value) => {
|
.map((index) => {
|
||||||
return "/" + Functions.mlang(value.title, lang);
|
return '/' + Functions.mlang(index.title, lang);
|
||||||
})
|
})
|
||||||
.join("");
|
.join('');
|
||||||
|
setParents({ title: title, node: parents });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [indexId, lang, type]);
|
||||||
|
|
||||||
|
if (notFound) {
|
||||||
|
return <PageNotFound lang={lang} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == null) {
|
||||||
|
return <Loading />;
|
||||||
|
}
|
||||||
|
const baseUrl = indexId === 0 ? '/' : IndexUtil.getUrl(type, indexId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="list">
|
<div className="list">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>
|
<title>
|
||||||
{Functions.mlang(title, lang)} - {Functions.mlang("[en]Database[/en][ja]データベース[/ja]", lang)} - {Functions.siteTitle(lang)}
|
{Functions.mlang(parents.title, lang)} -{' '}
|
||||||
|
{Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} -{' '}
|
||||||
|
{Functions.siteTitle(lang)}
|
||||||
</title>
|
</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<h3>{Functions.mlang("[en]Listing item[/en][ja]アイテム一覧[/ja]", lang)}</h3>
|
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
|
||||||
<div>{parents}</div>
|
<div>{parents.node}</div>
|
||||||
<DatabaseListIndex lang={lang} index={index} type={type} />
|
<DatabaseListIndex lang={lang} index={index} type={type} />
|
||||||
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} type={type} />
|
<DatabaseListItem lang={lang} url={baseUrl} search={searchFunc} type={type} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default DatabaseSearchByIndexId;
|
export default DatabaseSearchByIndexId;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import Functions from "../functions";
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
import DatabaseListItem from "./lib/DatabaseListItem";
|
import Functions from '../functions';
|
||||||
import ItemUtil, { SearchCallbackFunc, SortCondition } from "./lib/ItemUtil";
|
import DatabaseListItem from './lib/DatabaseListItem';
|
||||||
|
import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -11,38 +12,26 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DatabaseSearchByItemType extends React.Component<Props> {
|
const DatabaseSearchByItemType: React.FC<Props> = (props) => {
|
||||||
constructor(props: Props) {
|
const { lang, itemType, subItemType, type } = props;
|
||||||
super(props);
|
|
||||||
this.searchFunc = this.searchFunc.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
searchFunc(condition: SortCondition, func: SearchCallbackFunc) {
|
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
|
||||||
const { itemType, subItemType, type } = this.props;
|
if (itemType === '') {
|
||||||
if (itemType === "") {
|
|
||||||
const res = { total: 0, data: [] };
|
const res = { total: 0, data: [] };
|
||||||
func(res);
|
func(res);
|
||||||
} else {
|
} else {
|
||||||
ItemUtil.getListByItemType(type, itemType, subItemType, condition, func);
|
ItemUtil.getListByItemType(type, itemType, subItemType, condition, func);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
getUrl() {
|
const baseUrl = ItemUtil.getItemTypeSearchUrl(type, itemType, subItemType);
|
||||||
const { itemType, subItemType, type } = this.props;
|
|
||||||
let url = ItemUtil.getItemTypeSearchUrl(type, itemType, subItemType);
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang, type } = this.props;
|
|
||||||
const baseUrl = this.getUrl();
|
|
||||||
return (
|
return (
|
||||||
<div className="list">
|
<div className="list">
|
||||||
<h3>{Functions.mlang("[en]Listing item[/en][ja]アイテム一覧[/ja]", lang)}</h3>
|
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
|
||||||
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} type={type} />
|
<DatabaseListItem lang={lang} url={baseUrl} search={searchFunc} type={type} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default DatabaseSearchByItemType;
|
export default DatabaseSearchByItemType;
|
||||||
|
@ -1,74 +1,41 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { useLocation } from "react-router-dom";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import Functions from "../functions";
|
|
||||||
import DatabaseListItem from "./lib/DatabaseListItem";
|
|
||||||
import ItemUtil, { KeywordSearchType, SearchCallbackFunc, SortCondition } from "./lib/ItemUtil";
|
|
||||||
|
|
||||||
interface PropsFC {
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import { BrainAtlasType, MultiLang } from '../config';
|
||||||
|
import Functions from '../functions';
|
||||||
|
import DatabaseListItem from './lib/DatabaseListItem';
|
||||||
|
import ItemUtil, { SearchCallbackFunc, SortCondition } from './lib/ItemUtil';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends PropsFC {
|
const DatabaseSearchByKeyword: React.FC<Props> = (props) => {
|
||||||
location: any;
|
const { lang, type } = props;
|
||||||
}
|
|
||||||
|
|
||||||
interface State {
|
const location = useLocation();
|
||||||
type: KeywordSearchType;
|
const query = ItemUtil.getSearchKeywordByQuery(location.search);
|
||||||
keyword: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DatabaseSearchByKeyword extends React.Component<Props, State> {
|
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
|
||||||
constructor(props: Props) {
|
if (query.keyword === '') {
|
||||||
super(props);
|
|
||||||
const { location } = props;
|
|
||||||
const { type, keyword } = ItemUtil.getSearchKeywordByQuery(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() {
|
|
||||||
const { type } = this.props;
|
|
||||||
return ItemUtil.getSearchByKeywordUrl(type, this.state.type, this.state.keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
searchFunc(condition: SortCondition, func: SearchCallbackFunc) {
|
|
||||||
const { type } = this.props;
|
|
||||||
if (this.state.keyword === "") {
|
|
||||||
const res = { total: 0, data: [] };
|
const res = { total: 0, data: [] };
|
||||||
func(res);
|
func(res);
|
||||||
} else {
|
} else {
|
||||||
ItemUtil.getListByKeyword(type, this.state.type, this.state.keyword, condition, func);
|
ItemUtil.getListByKeyword(type, query.type, query.keyword, condition, func);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang, type } = this.props;
|
|
||||||
const baseUrl = this.getUrl();
|
|
||||||
return (
|
|
||||||
<div className="list">
|
|
||||||
<h3>{Functions.mlang("[en]Listing item[/en][ja]アイテム一覧[/ja]", lang)}</h3>
|
|
||||||
<p>
|
|
||||||
{Functions.mlang("[en]Search Keyword[/en][ja]検索キーワード[/ja]", lang)} : {this.state.keyword}
|
|
||||||
</p>
|
|
||||||
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} type={type} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DatabaseSearchByKeywordFC: React.FC<PropsFC> = (props: PropsFC) => {
|
|
||||||
const { lang, type } = props;
|
|
||||||
return <DatabaseSearchByKeyword lang={lang} type={type} location={useLocation()} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DatabaseSearchByKeywordFC;
|
const baseUrl = ItemUtil.getSearchByKeywordUrl(type, query.type, query.keyword);
|
||||||
|
return (
|
||||||
|
<div className="list">
|
||||||
|
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
|
||||||
|
<p>
|
||||||
|
{Functions.mlang('[en]Search Keyword[/en][ja]検索キーワード[/ja]', lang)} : {query.keyword}
|
||||||
|
</p>
|
||||||
|
<DatabaseListItem lang={lang} url={baseUrl} search={searchFunc} type={type} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DatabaseSearchByKeyword;
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import Config, { BrainAtlasType, MultiLang } from "../config";
|
|
||||||
import styles from "./DatabaseTop.module.css";
|
import Config, { BrainAtlasType, MultiLang } from '../config';
|
||||||
import ItemType from "./item-type";
|
import styles from './DatabaseTop.module.css';
|
||||||
|
import ItemType from './item-type';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DatabaseTop: React.FC<Props> = (props: Props) => {
|
const DatabaseTop: React.FC<Props> = (props) => {
|
||||||
const { lang, type } = props;
|
const { lang, type } = props;
|
||||||
const types: string[][] = [];
|
const types: string[][] = [];
|
||||||
const len = Config.XOONIPS_ITEMTYPES.length;
|
const len = Config.XOONIPS_ITEMTYPES.length;
|
||||||
@ -26,7 +27,9 @@ const DatabaseTop: React.FC<Props> = (props: Props) => {
|
|||||||
{value.map((itemType, idx) => {
|
{value.map((itemType, idx) => {
|
||||||
return (
|
return (
|
||||||
<td key={idx} className={styles.itemType}>
|
<td key={idx} className={styles.itemType}>
|
||||||
{itemType !== "" && <ItemType.Top lang={lang} itemType={"xnp" + itemType} type={type} />}
|
{itemType !== '' && (
|
||||||
|
<ItemType.Top lang={lang} itemType={'xnp' + itemType} type={type} />
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,121 +1,123 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Navigate, useLocation } from "react-router-dom";
|
|
||||||
import PageNotFound from "../common/lib/PageNotFound";
|
import { Navigate, useLocation } from 'react-router-dom';
|
||||||
import { MultiLang } from "../config";
|
import PageNotFound from '../common/lib/PageNotFound';
|
||||||
import Functions from "../functions";
|
import { MultiLang } from '../config';
|
||||||
|
import Functions from '../functions';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DatabaseXoopsPathRedirect: React.FC<Props> = (props: Props) => {
|
const DatabaseXoopsPathRedirect: React.FC<Props> = (props) => {
|
||||||
const { lang } = props;
|
const { lang } = props;
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
const getRedirectUrl = (): string => {
|
const getRedirectUrl = (): string => {
|
||||||
const location = useLocation();
|
const pathname = location.pathname || '';
|
||||||
const pathname = location.pathname || "";
|
|
||||||
const query = new URLSearchParams(location.search);
|
const query = new URLSearchParams(location.search);
|
||||||
const search = new RegExp("^/modules/xoonips(?:/+(.*))?$");
|
const search = new RegExp('^/modules/xoonips(?:/+(.*))?$');
|
||||||
const matches = pathname.match(search);
|
const matches = pathname.match(search);
|
||||||
if (matches === null) {
|
if (matches === null) {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
const path = matches[1] || "";
|
const path = matches[1] || '';
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "":
|
case '':
|
||||||
case "index.php": {
|
case 'index.php': {
|
||||||
return "/database";
|
return '/database';
|
||||||
}
|
}
|
||||||
case "detail.php": {
|
case 'detail.php': {
|
||||||
const id = query.get("id");
|
const id = query.get('id');
|
||||||
if (id !== null) {
|
if (id !== null) {
|
||||||
return "/database/item/id/" + Functions.escape(id);
|
return '/database/item/id/' + Functions.escape(id);
|
||||||
}
|
}
|
||||||
const itemId = query.get("item_id");
|
const itemId = query.get('item_id');
|
||||||
if (itemId !== null && itemId.match(/^\d+$/) !== null) {
|
if (itemId?.match(/^\d+$/) != null) {
|
||||||
return "/database/item/" + Functions.escape(itemId);
|
return '/database/item/' + Functions.escape(itemId);
|
||||||
}
|
}
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
case "listitem.php": {
|
case 'listitem.php': {
|
||||||
const indexId = query.get("index_id");
|
const indexId = query.get('index_id');
|
||||||
if (indexId !== null && indexId.match(/^\d+$/) !== null) {
|
if (indexId?.match(/^\d+$/) != null) {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
const map: any = {
|
[
|
||||||
orderby: { key: "orderby", isNumber: false },
|
{ qKey: 'orderby', pKey: 'orderby', isNumber: false },
|
||||||
order_dir: { key: "order_dir", isNumber: true },
|
{ qKey: 'order_dir', pKey: 'order_dir', isNumber: true },
|
||||||
itemcount: { key: "itemcount", isNumber: true },
|
{ qKey: 'itemcount', pKey: 'itemcount', isNumber: true },
|
||||||
page: { key: "page", isNumber: true },
|
{ qKey: 'page', pKey: 'page', isNumber: true },
|
||||||
};
|
].forEach(({ qKey, pKey, isNumber }) => {
|
||||||
for (let k in map) {
|
const v = query.get(qKey);
|
||||||
const v = query.get(k);
|
if (v == null || v.length === 0) {
|
||||||
if (v === null || v.length === 0) {
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (map[k].isNumber && v.match(/^\d+$/) !== null) {
|
if (isNumber && v.match(/^\d+$/) != null) {
|
||||||
continue;
|
return;
|
||||||
}
|
|
||||||
params.set(map[k].key, v);
|
|
||||||
}
|
}
|
||||||
|
params.set(pKey, v);
|
||||||
|
});
|
||||||
const paramStr = params.toString();
|
const paramStr = params.toString();
|
||||||
return "/database/list/" + Functions.escape(indexId) + (paramStr.length > 0 ? "?" + paramStr : "");
|
return (
|
||||||
|
`/database/list/${Functions.escape(indexId)}` +
|
||||||
|
(paramStr.length > 0 ? `?${paramStr}` : '')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "itemselect.php": {
|
case 'itemselect.php': {
|
||||||
const op = query.get("op");
|
const op = query.get('op');
|
||||||
if (op === null) {
|
if (op === null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case "quicksearch": {
|
case 'quicksearch': {
|
||||||
const keyword = query.get("keyword");
|
const keyword = query.get('keyword');
|
||||||
const itemType = query.get("search_itemtype");
|
const itemType = query.get('search_itemtype');
|
||||||
if (keyword === null || itemType === null || keyword === "") {
|
if (keyword === null || itemType === null || keyword === '') {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
const type = itemType.replace("xnp", "");
|
const type = itemType.replace('xnp', '');
|
||||||
if (itemType !== "basic" && itemType !== "all" && itemType.match(/^xnp.+/) === null) {
|
if (itemType !== 'basic' && itemType !== 'all' && itemType.match(/^xnp.+/) === null) {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
const params = new URLSearchParams({ type, keyword });
|
const params = new URLSearchParams({ type, keyword });
|
||||||
const map: any = {
|
[
|
||||||
orderby: { key: "orderby", isNumber: false },
|
{ qKey: 'orderby', pKey: 'orderby', isNumber: false },
|
||||||
orderdir: { key: "order_dir", isNumber: true },
|
{ qKey: 'orderdir', pKey: 'order_dir', isNumber: true },
|
||||||
item_per_page: { key: "itemcount", isNumber: true },
|
{ qKey: 'item_per_page', pKey: 'itemcount', isNumber: true },
|
||||||
page: { key: "page", isNumber: true },
|
{ qKey: 'page', pKey: 'page', isNumber: true },
|
||||||
};
|
].forEach(({ qKey, pKey, isNumber }) => {
|
||||||
for (let k in map) {
|
const v = query.get(qKey);
|
||||||
const v = query.get(k);
|
if (v == null || v.length === 0) {
|
||||||
if (v === null || v.length === 0) {
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (map[k].isNumber && v.match(/^\d+$/) !== null) {
|
if (isNumber && v.match(/^\d+$/) != null) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
params.set(map[k].key, v);
|
params.set(pKey, v);
|
||||||
|
});
|
||||||
|
return '/database/search?' + params.toString();
|
||||||
}
|
}
|
||||||
return "/database/search?" + params.toString();
|
case 'itemtypesearch': {
|
||||||
|
const itemType = query.get('search_itemtype');
|
||||||
|
if (itemType?.match(/^xnp.+/) == null) {
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
case "itemtypesearch": {
|
const type = itemType.replace('xnp', '');
|
||||||
const itemType = query.get("search_itemtype");
|
return '/database/search/itemtype/' + Functions.escape(type);
|
||||||
if (itemType === null || itemType.match(/^xnp.+/) === null) {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
const type = itemType.replace("xnp", "");
|
case 'itemsubtypesearch': {
|
||||||
return "/database/search/itemtype/" + Functions.escape(type);
|
let type = '';
|
||||||
}
|
let subtype = '';
|
||||||
case "itemsubtypesearch": {
|
|
||||||
let type = "";
|
|
||||||
let subtype = "";
|
|
||||||
query.forEach((v, k) => {
|
query.forEach((v, k) => {
|
||||||
if (k.match(/^xnp[a-z]+$/) !== null && !!v) {
|
if (k.match(/^xnp[a-z]+$/) !== null && !!v) {
|
||||||
type = k.replace("xnp", "");
|
type = k.replace('xnp', '');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (type === "") {
|
if (type === '') {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
query.forEach((v, k) => {
|
query.forEach((v, k) => {
|
||||||
if (k.match(`^xnp${type}_.+$`) !== null && !!v) {
|
if (k.match(`^xnp${type}_.+$`) !== null && !!v) {
|
||||||
@ -123,23 +125,28 @@ const DatabaseXoopsPathRedirect: React.FC<Props> = (props: Props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (subtype === "") {
|
if (subtype === '') {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
return "/database/search/itemtype/" + Functions.escape(type) + "/" + Functions.escape(subtype);
|
return (
|
||||||
|
'/database/search/itemtype/' +
|
||||||
|
Functions.escape(type) +
|
||||||
|
'/' +
|
||||||
|
Functions.escape(subtype)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
case "advanced_search.php": {
|
case 'advanced_search.php': {
|
||||||
return "/database/advanced";
|
return '/database/advanced';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const url = getRedirectUrl();
|
const url = getRedirectUrl();
|
||||||
if (url === "") {
|
if (url === '') {
|
||||||
return <PageNotFound lang={lang} />;
|
return <PageNotFound lang={lang} />;
|
||||||
}
|
}
|
||||||
return <Navigate to={url} />;
|
return <Navigate to={url} />;
|
||||||
|
@ -1 +0,0 @@
|
|||||||
[{"type":"degu","tree":[{"id":3,"title":"Public","num_of_items":0,"children":[{"id":16,"title":"Degu (Octodon degu)","num_of_items":0,"children":[{"id":24,"title":"The Degu 3D Brain Atlas","num_of_items":4,"children":[{"id":18,"title":"References","num_of_items":0,"children":[]}]}]}]}]},{"type":"jm","tree":[{"id":3,"title":"Public","num_of_items":0,"children":[{"id":7,"title":"Japanese Macaque Monkey","num_of_items":0,"children":[{"id":9,"title":"The MRI Standard Brain of Japanese Macaque Monkey","num_of_items":1,"children":[{"id":44,"title":"References","num_of_items":0,"children":[]}]}]}]}]},{"type":"marmoset","tree":[{"id":3,"title":"Public","num_of_items":0,"children":[{"id":66,"title":"The Marmoset 3D Brain Atlas","num_of_items":4,"children":[{"id":69,"title":"References","num_of_items":0,"children":[]}]},{"id":71,"title":"The Marmoset MRI Standard Brain","num_of_items":1,"children":[{"id":73,"title":"References","num_of_items":0,"children":[]}]}]}]}]
|
|
@ -41,13 +41,25 @@
|
|||||||
width: 9px;
|
width: 9px;
|
||||||
background: url(../assets/images/tree_line.png);
|
background: url(../assets/images/tree_line.png);
|
||||||
}
|
}
|
||||||
.indexTree:global(.rc-tree .rc-tree-treenode .rc-tree-indent .rc-tree-indent-unit:not(:last-child)) {
|
.indexTree:global(
|
||||||
|
.rc-tree .rc-tree-treenode .rc-tree-indent .rc-tree-indent-unit:not(:last-child)
|
||||||
|
) {
|
||||||
background-position: -9px 0;
|
background-position: -9px 0;
|
||||||
}
|
}
|
||||||
.indexTree:global(.rc-tree .rc-tree-treenode .rc-tree-indent .rc-tree-indent-unit:not(:last-child).rc-tree-indent-unit-end) {
|
.indexTree:global(
|
||||||
|
.rc-tree
|
||||||
|
.rc-tree-treenode
|
||||||
|
.rc-tree-indent
|
||||||
|
.rc-tree-indent-unit:not(:last-child).rc-tree-indent-unit-end
|
||||||
|
) {
|
||||||
background-position: -18px 0;
|
background-position: -18px 0;
|
||||||
}
|
}
|
||||||
.indexTree:global(.rc-tree .rc-tree-treenode .rc-tree-indent .rc-tree-indent-unit:last-child.rc-tree-indent-unit-end) {
|
.indexTree:global(
|
||||||
|
.rc-tree
|
||||||
|
.rc-tree-treenode
|
||||||
|
.rc-tree-indent
|
||||||
|
.rc-tree-indent-unit:last-child.rc-tree-indent-unit-end
|
||||||
|
) {
|
||||||
background-position: -27px 0;
|
background-position: -27px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,14 +81,20 @@
|
|||||||
.indexTree:global(.rc-tree .rc-tree-treenode:first-child .rc-tree-switcher.rc-tree-switcher_close) {
|
.indexTree:global(.rc-tree .rc-tree-treenode:first-child .rc-tree-switcher.rc-tree-switcher_close) {
|
||||||
background-position: -32px 0;
|
background-position: -32px 0;
|
||||||
}
|
}
|
||||||
.indexTree:global(.rc-tree .rc-tree-treenode:not(:first-child) .rc-tree-switcher.rc-tree-switcher-noop) {
|
.indexTree:global(
|
||||||
|
.rc-tree .rc-tree-treenode:not(:first-child) .rc-tree-switcher.rc-tree-switcher-noop
|
||||||
|
) {
|
||||||
background-position: 0 -20px;
|
background-position: 0 -20px;
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
}
|
}
|
||||||
.indexTree:global(.rc-tree .rc-tree-treenode:not(:first-child) .rc-tree-switcher.rc-tree-switcher_open) {
|
.indexTree:global(
|
||||||
|
.rc-tree .rc-tree-treenode:not(:first-child) .rc-tree-switcher.rc-tree-switcher_open
|
||||||
|
) {
|
||||||
background-position: -16px -20px;
|
background-position: -16px -20px;
|
||||||
}
|
}
|
||||||
.indexTree:global(.rc-tree .rc-tree-treenode:not(:first-child) .rc-tree-switcher.rc-tree-switcher_close) {
|
.indexTree:global(
|
||||||
|
.rc-tree .rc-tree-treenode:not(:first-child) .rc-tree-switcher.rc-tree-switcher_close
|
||||||
|
) {
|
||||||
background-position: -32px -20px;
|
background-position: -32px -20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,136 +1,133 @@
|
|||||||
import Tree from "rc-tree";
|
import React from 'react';
|
||||||
import { DataNode, EventDataNode } from "rc-tree/lib/interface";
|
|
||||||
import React, { Key } from "react";
|
import Tree from 'rc-tree';
|
||||||
import { useNavigate } from "react-router";
|
import { DataNode, EventDataNode } from 'rc-tree/lib/interface';
|
||||||
import { BrainAtlasType, MultiLang } from "../../config";
|
import { useNavigate } from 'react-router';
|
||||||
import Functions from "../../functions";
|
import Loading from '../../common/lib/Loading';
|
||||||
import IndexUtil, { Index, INDEX_ID_PUBLIC } from "../lib/IndexUtil";
|
import { BrainAtlasType, MultiLang } from '../../config';
|
||||||
import styles from "./IndexTree.module.css";
|
import Functions from '../../functions';
|
||||||
|
import IndexUtil, { INDEX_ID_PUBLIC, Index } from '../lib/IndexUtil';
|
||||||
|
import styles from './IndexTree.module.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const IndexTree: React.FC<Props> = (props) => {
|
||||||
tree: DataNode[];
|
const { lang, type } = props;
|
||||||
expandableKeys: string[];
|
const navigate = useNavigate();
|
||||||
expandedKeys: string[];
|
|
||||||
selectedKeys: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
class IndexTree extends React.Component<Props, State> {
|
const [tree, setTree] = React.useState<DataNode[]>([]);
|
||||||
constructor(props: Props) {
|
const [keys, setKeys] = React.useState<string[]>([]);
|
||||||
super(props);
|
const [expandedKeys, setExpandedKeys] = React.useState<string[]>([]);
|
||||||
this.handleClickOpenAll = this.handleClickOpenAll.bind(this);
|
const [selectedKeys, setSelectedKeys] = React.useState<number[]>([]);
|
||||||
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() {
|
React.useEffect(() => {
|
||||||
const { lang, type } = this.props;
|
const tree: DataNode[] = [];
|
||||||
let keys: string[] = [];
|
const keys: string[] = [];
|
||||||
let eKeys: string[] = [];
|
const eKeys: string[] = [];
|
||||||
const makeTreeNode = (index: Index, depth: number): DataNode => {
|
const makeTreeNode = (index: Index, depth: number, func: (node: DataNode) => void): void => {
|
||||||
const title = Functions.mlang(index.title, lang) + (index.numOfItems > 0 ? " (" + index.numOfItems + ")" : "");
|
const title =
|
||||||
const children = IndexUtil.getChildren(type, index.id);
|
Functions.mlang(index.title, lang) +
|
||||||
|
(index.numOfItems > 0 ? ' (' + index.numOfItems + ')' : '');
|
||||||
|
IndexUtil.getChildren(type, index.id, (children) => {
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
return { key: String(index.id), title: title };
|
func({ key: String(index.id), title: title });
|
||||||
}
|
} else {
|
||||||
const childTreeNodes = children.map((value: Index) => {
|
|
||||||
return makeTreeNode(value, depth + 1);
|
|
||||||
});
|
|
||||||
if (depth < 1) {
|
if (depth < 1) {
|
||||||
eKeys.push(String(index.id));
|
eKeys.push(String(index.id));
|
||||||
}
|
}
|
||||||
keys.push(String(index.id));
|
keys.push(String(index.id));
|
||||||
return { key: String(index.id), title: title, children: childTreeNodes };
|
const childTreeNodes: DataNode[] = [];
|
||||||
};
|
let called = 0;
|
||||||
let elements: DataNode[] = [];
|
children.forEach((value: Index) => {
|
||||||
const index = IndexUtil.get(type, INDEX_ID_PUBLIC);
|
makeTreeNode(value, depth + 1, (cNode) => {
|
||||||
if (index !== null) {
|
called++;
|
||||||
elements.push(makeTreeNode(index, 0));
|
childTreeNodes.push(cNode);
|
||||||
|
if (called === children.length) {
|
||||||
|
func({ key: String(index.id), title: title, children: childTreeNodes });
|
||||||
}
|
}
|
||||||
return {
|
});
|
||||||
elements: elements,
|
|
||||||
keys: keys,
|
|
||||||
expandedKeys: eKeys,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props, prevState: State) {
|
|
||||||
const { lang, type } = this.props;
|
|
||||||
if (prevProps.lang !== lang || prevProps.type !== type) {
|
|
||||||
const res = this.load();
|
|
||||||
this.setState({
|
|
||||||
tree: res.elements,
|
|
||||||
selectedKeys: [],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
IndexUtil.get(type, INDEX_ID_PUBLIC, (index) => {
|
||||||
|
if (index != null) {
|
||||||
|
makeTreeNode(index, 0, (node) => {
|
||||||
|
tree.push(node);
|
||||||
|
setTree(tree);
|
||||||
|
setKeys(keys);
|
||||||
|
setExpandedKeys(eKeys);
|
||||||
|
setSelectedKeys([]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}, [lang, type]);
|
||||||
|
|
||||||
handleClickOpenAll() {
|
const handleClickOpenAll = () => {
|
||||||
this.setState({ expandedKeys: this.state.expandableKeys });
|
setExpandedKeys(keys);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleClickCloseAll() {
|
const handleClickCloseAll = () => {
|
||||||
this.setState({ expandedKeys: [] });
|
setExpandedKeys([]);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleExpand(
|
const handleExpand: (
|
||||||
expandedKeys: Key[],
|
expandedKeys: React.Key[],
|
||||||
info: {
|
info: {
|
||||||
node: EventDataNode<DataNode>;
|
node: EventDataNode<DataNode>;
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
nativeEvent: MouseEvent;
|
nativeEvent: MouseEvent;
|
||||||
}
|
},
|
||||||
): void {
|
) => void = (expandedKeys) => {
|
||||||
const keys: string[] = expandedKeys.map((key) => {
|
const keys: string[] = expandedKeys.map((key) => {
|
||||||
return typeof key === "string" ? key : String(key);
|
return typeof key === 'string' ? key : String(key);
|
||||||
});
|
});
|
||||||
this.setState({ expandedKeys: keys });
|
setExpandedKeys(keys);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleSelect(
|
const handleSelect: (
|
||||||
selectedKeys: Key[],
|
selectedKeys: React.Key[],
|
||||||
info: {
|
info: {
|
||||||
event: "select";
|
event: 'select';
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
node: EventDataNode<DataNode>;
|
node: EventDataNode<DataNode>;
|
||||||
selectedNodes: DataNode[];
|
selectedNodes: DataNode[];
|
||||||
nativeEvent: MouseEvent;
|
nativeEvent: MouseEvent;
|
||||||
}
|
},
|
||||||
): void {
|
) => void = (selectedKeys) => {
|
||||||
const navigate = useNavigate();
|
const selectedKey = selectedKeys.shift() ?? 0;
|
||||||
const { type } = this.props;
|
const key = typeof selectedKey === 'string' ? parseInt(selectedKey, 10) : selectedKey;
|
||||||
const selectedKey = selectedKeys.shift() || 0;
|
|
||||||
const key = typeof selectedKey === "string" ? parseInt(selectedKey, 10) : selectedKey;
|
|
||||||
const url = IndexUtil.getUrl(type, key);
|
const url = IndexUtil.getUrl(type, key);
|
||||||
navigate(url);
|
navigate(url);
|
||||||
this.setState({ selectedKeys: [] });
|
setSelectedKeys([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tree.length === 0) {
|
||||||
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<button className={styles.formButton} onClick={this.handleClickOpenAll}>
|
<button className={styles.formButton} onClick={handleClickOpenAll}>
|
||||||
open all
|
open all
|
||||||
</button>
|
</button>
|
||||||
<button className={styles.formButton} onClick={this.handleClickCloseAll}>
|
<button className={styles.formButton} onClick={handleClickCloseAll}>
|
||||||
close all
|
close all
|
||||||
</button>
|
</button>
|
||||||
<Tree className={styles.indexTree} expandedKeys={this.state.expandedKeys} selectedKeys={this.state.selectedKeys} onExpand={this.handleExpand} onSelect={this.handleSelect} showIcon={false} treeData={this.state.tree} />
|
<Tree
|
||||||
|
className={styles.indexTree}
|
||||||
|
expandedKeys={expandedKeys}
|
||||||
|
selectedKeys={selectedKeys}
|
||||||
|
onExpand={handleExpand}
|
||||||
|
onSelect={handleSelect}
|
||||||
|
showIcon={false}
|
||||||
|
treeData={tree}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default IndexTree;
|
export default IndexTree;
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
|
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
|
||||||
|
|
||||||
class BinderAdvancedSearch extends AdvancedSearchBase {
|
class BinderAdvancedSearch extends AdvancedSearchBase {
|
||||||
constructor(props: AdvancedSearchBaseProps) {
|
constructor(props: AdvancedSearchBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "binder";
|
this.type = 'binder';
|
||||||
this.title = "Binder";
|
this.title = 'Binder';
|
||||||
this.state.values["title"] = "";
|
this.state.values.title = '';
|
||||||
this.state.values["keyword"] = "";
|
this.state.values.keyword = '';
|
||||||
this.state.values["description"] = "";
|
this.state.values.description = '';
|
||||||
this.state.values["doi"] = "";
|
this.state.values.doi = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows() {
|
getRows() {
|
||||||
const rows = [
|
const rows = [
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 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: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
|
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;
|
return rows;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import ItemType from "..";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../../../config";
|
import ItemType from '..';
|
||||||
import Functions from "../../../functions";
|
import { BrainAtlasType, MultiLang } from '../../../config';
|
||||||
import ItemUtil, { Item, ItemBinder } from "../../lib/ItemUtil";
|
import Functions from '../../../functions';
|
||||||
import DetailBase from "../lib/DetailBase";
|
import ItemUtil, { Item, ItemBinder } from '../../lib/ItemUtil';
|
||||||
import ItemTypeField from "../lib/field";
|
import DetailBase from '../lib/DetailBase';
|
||||||
|
import ItemTypeField from '../lib/field';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -12,46 +13,32 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const BinderLinkItems: React.FC<Props> = (props) => {
|
||||||
items: Item[];
|
const { lang, item, type } = props;
|
||||||
}
|
const [items, setItems] = React.useState<Item[]>([]);
|
||||||
|
|
||||||
class BinderLinkItems extends React.Component<Props, State> {
|
const isMounted = React.useRef<boolean>(false);
|
||||||
constructor(props: Props) {
|
React.useEffect(() => {
|
||||||
super(props);
|
isMounted.current = true;
|
||||||
this.state = {
|
return () => {
|
||||||
items: [],
|
isMounted.current = false;
|
||||||
};
|
};
|
||||||
}
|
}, []);
|
||||||
|
|
||||||
componentDidMount() {
|
React.useEffect(() => {
|
||||||
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, type } = this.props;
|
|
||||||
const itemIds = item.item_link;
|
const itemIds = item.item_link;
|
||||||
ItemUtil.getList(type, itemIds, (results) => {
|
ItemUtil.getList(type, itemIds, (results) => {
|
||||||
const items = results.data;
|
if (isMounted.current) {
|
||||||
this.setState({ items });
|
setItems(results.data);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}, [item.item_link, type]);
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang, type } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<table className="listTable">
|
<table className="listTable">
|
||||||
<tbody>
|
<tbody>
|
||||||
{this.state.items.map((item, idx) => {
|
{items.map((item, idx) => {
|
||||||
const evenodd = idx % 2 ? "even" : "odd";
|
const evenodd = idx % 2 ? 'even' : 'odd';
|
||||||
return (
|
return (
|
||||||
<tr key={item.item_id}>
|
<tr key={item.item_id}>
|
||||||
<td className={evenodd}>
|
<td className={evenodd}>
|
||||||
@ -63,24 +50,44 @@ class BinderLinkItems extends React.Component<Props, State> {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
class BinderDetail extends DetailBase {
|
class BinderDetail extends DetailBase {
|
||||||
getFields() {
|
getFields() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const item = this.props.item as ItemBinder;
|
const item = this.props.item as ItemBinder;
|
||||||
return [
|
return [
|
||||||
{ label: "ID", value: item.doi },
|
{ label: 'ID', value: item.doi },
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: Functions.mlang(item.title, lang) },
|
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) },
|
||||||
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} /> },
|
{
|
||||||
{ label: "[en]Description[/en][ja]概要[/ja]", value: <ItemTypeField.Description lang={lang} description={item.description} /> },
|
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "[en]Last Modified Date[/en][ja]最終更新日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} /> },
|
value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} />,
|
||||||
{ label: "[en]Created Date[/en][ja]作成日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} /> },
|
},
|
||||||
{ label: "[en]Contributor[/en][ja]登録者[/ja]", value: <ItemTypeField.Contributer lang={lang} uname={item.uname} name={item.name} /> },
|
{
|
||||||
{ label: "[en]Item Type[/en][ja]アイテムタイプ[/ja]", value: item.item_type_display_name },
|
label: '[en]Description[/en][ja]概要[/ja]',
|
||||||
{ label: "[en]Change Log(History)[/en][ja]変更履歴[/ja]", value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} /> },
|
value: <ItemTypeField.Description lang={lang} description={item.description} />,
|
||||||
{ label: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Created Date[/en][ja]作成日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Contributor[/en][ja]登録者[/ja]',
|
||||||
|
value: <ItemTypeField.Contributor lang={lang} uname={item.uname} name={item.name} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name },
|
||||||
|
{
|
||||||
|
label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]',
|
||||||
|
value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Index',
|
||||||
|
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import React from "react";
|
import { Link } from 'react-router-dom';
|
||||||
import { Link } from "react-router-dom";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import iconFile from '../../assets/images/icon_binder.gif';
|
||||||
import iconFile from "../../assets/images/icon_binder.gif";
|
import { ItemBinder } from '../../lib/ItemUtil';
|
||||||
import { ItemBinder } from "../../lib/ItemUtil";
|
import ListBase, { ListBaseProps } from '../lib/ListBase';
|
||||||
import ListBase, { ListBaseProps } from "../lib/ListBase";
|
|
||||||
|
|
||||||
class BinderList extends ListBase {
|
class BinderList extends ListBase {
|
||||||
constructor(props: ListBaseProps) {
|
constructor(props: ListBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.label = "Binder";
|
this.label = 'Binder';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import iconFile from "../../assets/images/icon_binder.gif";
|
import iconFile from '../../assets/images/icon_binder.gif';
|
||||||
import TopBase, { TopBaseProps } from "../lib/TopBase";
|
import TopBase, { TopBaseProps } from '../lib/TopBase';
|
||||||
|
|
||||||
class BinderTop extends TopBase {
|
class BinderTop extends TopBase {
|
||||||
constructor(props: TopBaseProps) {
|
constructor(props: TopBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "binder";
|
this.type = 'binder';
|
||||||
this.label = "Binder";
|
this.label = 'Binder';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
this.description = "[en]Binder collection.[/en][ja]バインダー[/ja]";
|
this.description = '[en]Binder collection.[/en][ja]バインダー[/ja]';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import BinderAdvancedSearch from "./BinderAdvancedSearch";
|
import BinderAdvancedSearch from './BinderAdvancedSearch';
|
||||||
import BinderDetail from "./BinderDetail";
|
import BinderDetail from './BinderDetail';
|
||||||
import BinderList from "./BinderList";
|
import BinderList from './BinderList';
|
||||||
import BinderTop from "./BinderTop";
|
import BinderTop from './BinderTop';
|
||||||
|
|
||||||
const ItemTypeBinder = {
|
const ItemTypeBinder = {
|
||||||
Top: BinderTop,
|
Top: BinderTop,
|
||||||
|
@ -1,34 +1,52 @@
|
|||||||
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
|
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
|
||||||
|
|
||||||
class BookAdvancedSearch extends AdvancedSearchBase {
|
class BookAdvancedSearch extends AdvancedSearchBase {
|
||||||
constructor(props: AdvancedSearchBaseProps) {
|
constructor(props: AdvancedSearchBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "book";
|
this.type = 'book';
|
||||||
this.title = "Book";
|
this.title = 'Book';
|
||||||
this.state.values["title"] = "";
|
this.state.values.title = '';
|
||||||
this.state.values["keyword"] = "";
|
this.state.values.keyword = '';
|
||||||
this.state.values["description"] = "";
|
this.state.values.description = '';
|
||||||
this.state.values["doi"] = "";
|
this.state.values.doi = '';
|
||||||
this.state.values["author"] = "";
|
this.state.values.author = '';
|
||||||
this.state.values["editor"] = "";
|
this.state.values.editor = '';
|
||||||
this.state.values["publisher"] = "";
|
this.state.values.publisher = '';
|
||||||
this.state.values["publication_year"] = "";
|
this.state.values.publication_year = '';
|
||||||
this.state.values["isbn"] = "";
|
this.state.values.isbn = '';
|
||||||
this.state.values["file.book_pdf.original_file_name"] = "";
|
this.state.values['file.book_pdf.original_file_name'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows() {
|
getRows() {
|
||||||
const rows = [
|
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]Book Title[/en][ja]著書名[/ja]',
|
||||||
{ label: "[en]Description[/en][ja]概要[/ja]", value: this.renderFieldInputText("description", 50) },
|
value: this.renderFieldInputText('title', 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]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "[en]Publisher[/en][ja]出版社[/ja]", value: this.renderFieldInputText("publisher", 50) },
|
value: this.renderFieldInputText('keyword', 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) },
|
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;
|
return rows;
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,79 @@
|
|||||||
import React from "react";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import { ItemBook } from '../../lib/ItemUtil';
|
||||||
import { ItemBook } from "../../lib/ItemUtil";
|
import DetailBase from '../lib/DetailBase';
|
||||||
import DetailBase from "../lib/DetailBase";
|
import ItemTypeField from '../lib/field';
|
||||||
import ItemTypeField from "../lib/field";
|
|
||||||
|
|
||||||
class BookDetail extends DetailBase {
|
class BookDetail extends DetailBase {
|
||||||
getFields() {
|
getFields() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const item = this.props.item as ItemBook;
|
const item = this.props.item as ItemBook;
|
||||||
return [
|
return [
|
||||||
{ label: "ID", value: item.doi },
|
{ label: 'ID', value: item.doi },
|
||||||
{ label: "[en]Language[/en][ja]言語[/ja]", value: <ItemTypeField.Language lang={lang} itemLang={item.lang} /> },
|
|
||||||
{ label: "[en]Book Title[/en][ja]著書名[/ja]", value: Functions.mlang(item.title, lang) },
|
|
||||||
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} /> },
|
|
||||||
{ label: "[en]Description[/en][ja]概要[/ja]", value: <ItemTypeField.Description lang={lang} description={item.description} /> },
|
|
||||||
{ label: "[en]Last Modified Date[/en][ja]最終更新日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} /> },
|
|
||||||
{ label: "[en]Created Date[/en][ja]作成日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} /> },
|
|
||||||
{ label: "[en]Contributor[/en][ja]登録者[/ja]", value: <ItemTypeField.Contributer lang={lang} uname={item.uname} name={item.name} /> },
|
|
||||||
{ label: "[en]Item Type[/en][ja]アイテムタイプ[/ja]", value: item.item_type_display_name },
|
|
||||||
{ label: "[en]Change Log(History)[/en][ja]変更履歴[/ja]", value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} /> },
|
|
||||||
{ label: "[en]Author[/en][ja]著者[/ja]", value: <ItemTypeField.Author lang={lang} author={item.author} /> },
|
|
||||||
{ 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",
|
label: '[en]Language[/en][ja]言語[/ja]',
|
||||||
|
value: <ItemTypeField.Language lang={lang} itemLang={item.lang} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Book Title[/en][ja]著書名[/ja]', value: Functions.mlang(item.title, lang) },
|
||||||
|
{
|
||||||
|
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
|
value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Description[/en][ja]概要[/ja]',
|
||||||
|
value: <ItemTypeField.Description lang={lang} description={item.description} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Created Date[/en][ja]作成日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Contributor[/en][ja]登録者[/ja]',
|
||||||
|
value: <ItemTypeField.Contributor lang={lang} uname={item.uname} name={item.name} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name },
|
||||||
|
{
|
||||||
|
label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]',
|
||||||
|
value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Author[/en][ja]著者[/ja]',
|
||||||
|
value: <ItemTypeField.Author lang={lang} author={item.author} />,
|
||||||
|
},
|
||||||
|
{ 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: (
|
value: (
|
||||||
<a href={item.url} target="_blank" rel="noopener noreferrer">
|
<a href={item.url} target="_blank" rel="noopener noreferrer">
|
||||||
{item.url}
|
{item.url}
|
||||||
</a>
|
</a>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ label: "[en]PDF File[/en][ja]PDF ファイル[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="book_pdf" downloadLimit={item.attachment_dl_limit} type={type} /> },
|
{
|
||||||
{ label: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
|
label: '[en]PDF File[/en][ja]PDF ファイル[/ja]',
|
||||||
{ label: "[en]Related to[/en][ja]関連アイテム[/ja]", value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} /> },
|
value: (
|
||||||
|
<ItemTypeField.ItemFile
|
||||||
|
lang={lang}
|
||||||
|
file={item.file}
|
||||||
|
fileType="book_pdf"
|
||||||
|
downloadLimit={item.attachment_dl_limit}
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Index',
|
||||||
|
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Related to[/en][ja]関連アイテム[/ja]',
|
||||||
|
value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import React, { Fragment } from "react";
|
import { Fragment } from 'react';
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from 'react-router-dom';
|
||||||
import Functions from "../../../functions";
|
import Functions from '../../../functions';
|
||||||
import iconFile from "../../assets/images/icon_book.gif";
|
import iconFile from '../../assets/images/icon_book.gif';
|
||||||
import { ItemBook } from "../../lib/ItemUtil";
|
import { ItemBook } from '../../lib/ItemUtil';
|
||||||
import ListBase, { ListBaseProps } from "../lib/ListBase";
|
import ListBase, { ListBaseProps } from '../lib/ListBase';
|
||||||
|
|
||||||
class BookList extends ListBase {
|
class BookList extends ListBase {
|
||||||
constructor(props: ListBaseProps) {
|
constructor(props: ListBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.label = "Book";
|
this.label = 'Book';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ class BookList extends ListBase {
|
|||||||
const authors = item.author.map((author, i) => {
|
const authors = item.author.map((author, i) => {
|
||||||
return (
|
return (
|
||||||
<Fragment key={i}>
|
<Fragment key={i}>
|
||||||
{i > 0 && ", "}
|
{i > 0 && ', '}
|
||||||
{Functions.mlang(author, lang)}
|
{Functions.mlang(author, lang)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import iconFile from "../../assets/images/icon_book.gif";
|
import iconFile from '../../assets/images/icon_book.gif';
|
||||||
import TopBase, { TopBaseProps } from "../lib/TopBase";
|
import TopBase, { TopBaseProps } from '../lib/TopBase';
|
||||||
|
|
||||||
class BookTop extends TopBase {
|
class BookTop extends TopBase {
|
||||||
constructor(props: TopBaseProps) {
|
constructor(props: TopBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "book";
|
this.type = 'book';
|
||||||
this.label = "Book";
|
this.label = 'Book';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
this.description = "[en]Related book collection.[/en][ja]関連書籍[/ja]";
|
this.description = '[en]Related book collection.[/en][ja]関連書籍[/ja]';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import BookAdvancedSearch from "./BookAdvancedSearch";
|
import BookAdvancedSearch from './BookAdvancedSearch';
|
||||||
import BookDetail from "./BookDetail";
|
import BookDetail from './BookDetail';
|
||||||
import BookList from "./BookList";
|
import BookList from './BookList';
|
||||||
import BookTop from "./BookTop";
|
import BookTop from './BookTop';
|
||||||
|
|
||||||
const ItemTypeBook = {
|
const ItemTypeBook = {
|
||||||
Top: BookTop,
|
Top: BookTop,
|
||||||
|
@ -1,48 +1,67 @@
|
|||||||
import React from "react";
|
import { ItemConferenceSubTypes } from '../../lib/ItemUtil';
|
||||||
import { ItemConferenceSubTypes } from "../../lib/ItemUtil";
|
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
|
||||||
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
|
|
||||||
|
|
||||||
class ConferenceAdvancedSearch extends AdvancedSearchBase {
|
class ConferenceAdvancedSearch extends AdvancedSearchBase {
|
||||||
constructor(props: AdvancedSearchBaseProps) {
|
constructor(props: AdvancedSearchBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "conference";
|
this.type = 'conference';
|
||||||
this.title = "Conference";
|
this.title = 'Conference';
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const year = String(now.getFullYear());
|
const year = String(now.getFullYear());
|
||||||
const month = String(now.getMonth() + 1);
|
const month = String(now.getMonth() + 1);
|
||||||
const mday = String(now.getDate());
|
const mday = String(now.getDate());
|
||||||
this.state.values["title"] = "";
|
this.state.values.title = '';
|
||||||
this.state.values["presentation_type"] = "";
|
this.state.values.presentation_type = '';
|
||||||
this.state.values["author"] = "";
|
this.state.values.author = '';
|
||||||
this.state.values["conference_from_year"] = year;
|
this.state.values.conference_from_year = year;
|
||||||
this.state.values["conference_from_month"] = month;
|
this.state.values.conference_from_month = month;
|
||||||
this.state.values["conference_from_mday"] = mday;
|
this.state.values.conference_from_mday = mday;
|
||||||
this.state.values["conference_to_year"] = year;
|
this.state.values.conference_to_year = year;
|
||||||
this.state.values["conference_to_month"] = month;
|
this.state.values.conference_to_month = month;
|
||||||
this.state.values["conference_to_mday"] = mday;
|
this.state.values.conference_to_mday = mday;
|
||||||
this.setIgnoreKey("conference_from_year");
|
this.setIgnoreKey('conference_from_year');
|
||||||
this.setIgnoreKey("conference_from_month");
|
this.setIgnoreKey('conference_from_month');
|
||||||
this.setIgnoreKey("conference_from_mday");
|
this.setIgnoreKey('conference_from_mday');
|
||||||
this.setIgnoreKey("conference_to_year");
|
this.setIgnoreKey('conference_to_year');
|
||||||
this.setIgnoreKey("conference_to_month");
|
this.setIgnoreKey('conference_to_month');
|
||||||
this.setIgnoreKey("conference_to_mday");
|
this.setIgnoreKey('conference_to_mday');
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDate() {
|
renderDate() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>{this.renderFieldDate("From", "conference_from_year", "conference_from_month", "conference_from_mday")}</div>
|
<div>
|
||||||
<div>{this.renderFieldDate("To", "conference_to_year", "conference_to_month", "conference_to_mday")}</div>
|
{this.renderFieldDate(
|
||||||
|
'From',
|
||||||
|
'conference_from_year',
|
||||||
|
'conference_from_month',
|
||||||
|
'conference_from_mday',
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{this.renderFieldDate(
|
||||||
|
'To',
|
||||||
|
'conference_to_year',
|
||||||
|
'conference_to_month',
|
||||||
|
'conference_to_mday',
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows() {
|
getRows() {
|
||||||
const rows = [
|
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]Presentation Title[/en][ja]発表議題[/ja]',
|
||||||
{ label: "[en]Author[/en][ja]発表者[/ja]", value: this.renderFieldInputText("author", 50) },
|
value: this.renderFieldInputText('title', 50),
|
||||||
{ label: "[en]Date[/en][ja]日付[/ja]", value: this.renderDate() },
|
},
|
||||||
|
{
|
||||||
|
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;
|
return rows;
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,91 @@
|
|||||||
import React from "react";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import { ItemConference } from '../../lib/ItemUtil';
|
||||||
import { ItemConference } from "../../lib/ItemUtil";
|
import DetailBase from '../lib/DetailBase';
|
||||||
import DetailBase from "../lib/DetailBase";
|
import ItemTypeField from '../lib/field';
|
||||||
import ItemTypeField from "../lib/field";
|
import ConferenceUtil from './ConferenceUtil';
|
||||||
import ConferenceUtil from "./ConferenceUtil";
|
|
||||||
|
|
||||||
class ConferenceDetail extends DetailBase {
|
class ConferenceDetail extends DetailBase {
|
||||||
getFields() {
|
getFields() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const item = this.props.item as ItemConference;
|
const item = this.props.item as ItemConference;
|
||||||
return [
|
return [
|
||||||
{ label: "ID", value: item.doi },
|
{ label: 'ID', value: item.doi },
|
||||||
{ label: "[en]Language[/en][ja]言語[/ja]", value: <ItemTypeField.Language lang={lang} itemLang={item.lang} /> },
|
{
|
||||||
{ label: "[en]Conference Title[/en][ja]学会名[/ja]", value: Functions.mlang(item.conference_title, lang) },
|
label: '[en]Language[/en][ja]言語[/ja]',
|
||||||
{ label: "[en]Place[/en][ja]開催地[/ja]", value: item.place },
|
value: <ItemTypeField.Language lang={lang} itemLang={item.lang} />,
|
||||||
{ label: "[en]Date[/en][ja]日付[/ja]", value: <ConferenceUtil.ConferenceDate lang={lang} item={item} /> },
|
},
|
||||||
{ label: "[en]Last Modified Date[/en][ja]最終更新日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} /> },
|
{
|
||||||
{ label: "[en]Created Date[/en][ja]作成日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} /> },
|
label: '[en]Conference Title[/en][ja]学会名[/ja]',
|
||||||
{ label: "[en]Contributor[/en][ja]登録者[/ja]", value: <ItemTypeField.Contributer lang={lang} uname={item.uname} name={item.name} /> },
|
value: Functions.mlang(item.conference_title, lang),
|
||||||
{ label: "[en]Item Type[/en][ja]アイテムタイプ[/ja]", value: item.item_type_display_name },
|
},
|
||||||
{ label: "[en]Change Log(History)[/en][ja]変更履歴[/ja]", value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} /> },
|
{ label: '[en]Place[/en][ja]開催地[/ja]', value: item.place },
|
||||||
{ label: "[en]Presentation Title[/en][ja]発表議題[/ja]", value: Functions.mlang(item.title, lang) },
|
{
|
||||||
{ label: "[en]Author[/en][ja]発表者[/ja]", value: <ItemTypeField.Author lang={lang} author={item.author} /> },
|
label: '[en]Date[/en][ja]日付[/ja]',
|
||||||
{ label: "[en]Abstract[/en][ja]要約[/ja]", value: <ItemTypeField.Description lang={lang} description={item.abstract} /> },
|
value: <ConferenceUtil.ConferenceDate lang={lang} item={item} />,
|
||||||
{ label: "[en]Presentation File[/en][ja]発表資料[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="conference_file" type={type} /> },
|
},
|
||||||
{ label: "[en]Presentation Type[/en][ja]発表資料ファイル形式[/ja]", value: <ConferenceUtil.PresentationType lang={lang} type={item.presentation_type} /> },
|
{
|
||||||
{ label: "[en]Conference Paper[/en][ja]学会資料[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="conference_paper" type={type} /> },
|
label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]',
|
||||||
{ label: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
|
value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} />,
|
||||||
{ label: "[en]Related to[/en][ja]関連アイテム[/ja]", value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} /> },
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Created Date[/en][ja]作成日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Contributor[/en][ja]登録者[/ja]',
|
||||||
|
value: <ItemTypeField.Contributor lang={lang} uname={item.uname} name={item.name} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name },
|
||||||
|
{
|
||||||
|
label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]',
|
||||||
|
value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Presentation Title[/en][ja]発表議題[/ja]',
|
||||||
|
value: Functions.mlang(item.title, lang),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Author[/en][ja]発表者[/ja]',
|
||||||
|
value: <ItemTypeField.Author lang={lang} author={item.author} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Abstract[/en][ja]要約[/ja]',
|
||||||
|
value: <ItemTypeField.Description lang={lang} description={item.abstract} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Presentation File[/en][ja]発表資料[/ja]',
|
||||||
|
value: (
|
||||||
|
<ItemTypeField.ItemFile
|
||||||
|
lang={lang}
|
||||||
|
file={item.file}
|
||||||
|
fileType="conference_file"
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Presentation Type[/en][ja]発表資料ファイル形式[/ja]',
|
||||||
|
value: <ConferenceUtil.PresentationType lang={lang} type={item.presentation_type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Conference Paper[/en][ja]学会資料[/ja]',
|
||||||
|
value: (
|
||||||
|
<ItemTypeField.ItemFile
|
||||||
|
lang={lang}
|
||||||
|
file={item.file}
|
||||||
|
fileType="conference_paper"
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Index',
|
||||||
|
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Related to[/en][ja]関連アイテム[/ja]',
|
||||||
|
value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import React, { Fragment } from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import Functions from "../../../functions";
|
import { Link } from 'react-router-dom';
|
||||||
import iconFile from "../../assets/images/icon_conference.gif";
|
import Functions from '../../../functions';
|
||||||
import { ItemConference } from "../../lib/ItemUtil";
|
import iconFile from '../../assets/images/icon_conference.gif';
|
||||||
import ListBase, { ListBaseProps } from "../lib/ListBase";
|
import { ItemConference } from '../../lib/ItemUtil';
|
||||||
import ConferenceUtil from "./ConferenceUtil";
|
import ListBase, { ListBaseProps } from '../lib/ListBase';
|
||||||
|
import ConferenceUtil from './ConferenceUtil';
|
||||||
|
|
||||||
class ConferenceList extends ListBase {
|
class ConferenceList extends ListBase {
|
||||||
constructor(props: ListBaseProps) {
|
constructor(props: ListBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.label = "Conference";
|
this.label = 'Conference';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,17 +19,18 @@ class ConferenceList extends ListBase {
|
|||||||
const item = this.props.item as ItemConference;
|
const item = this.props.item as ItemConference;
|
||||||
const authors = item.author.map((author, i) => {
|
const authors = item.author.map((author, i) => {
|
||||||
return (
|
return (
|
||||||
<Fragment key={i}>
|
<React.Fragment key={i}>
|
||||||
{i > 0 && ", "}
|
{i > 0 && ', '}
|
||||||
{Functions.mlang(author, lang)}
|
{Functions.mlang(author, lang)}
|
||||||
</Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
|
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
|
||||||
<br />
|
<br />
|
||||||
{Functions.mlang(item.conference_title, lang)} (<ConferenceUtil.PresentationType lang={lang} type={item.presentation_type} />)<br />
|
{Functions.mlang(item.conference_title, lang)} (
|
||||||
|
<ConferenceUtil.PresentationType lang={lang} type={item.presentation_type} />)<br />
|
||||||
{authors}
|
{authors}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import iconFile from "../../assets/images/icon_conference.gif";
|
import iconFile from '../../assets/images/icon_conference.gif';
|
||||||
import { ItemConferenceSubTypes } from "../../lib/ItemUtil";
|
import { ItemConferenceSubTypes } from '../../lib/ItemUtil';
|
||||||
import TopBase, { TopBaseProps } from "../lib/TopBase";
|
import TopBase, { TopBaseProps } from '../lib/TopBase';
|
||||||
|
|
||||||
class ConferenceTop extends TopBase {
|
class ConferenceTop extends TopBase {
|
||||||
constructor(props: TopBaseProps) {
|
constructor(props: TopBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "conference";
|
this.type = 'conference';
|
||||||
this.label = "Conference";
|
this.label = 'Conference';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
this.description = "[en]Electrical presentation files for conference.[/en][ja]学会発表[/ja]";
|
this.description = '[en]Electrical presentation files for conference.[/en][ja]学会発表[/ja]';
|
||||||
this.subTypes = ItemConferenceSubTypes;
|
this.subTypes = ItemConferenceSubTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../config";
|
import { MultiLang } from '../../../config';
|
||||||
import { ItemConference, ItemConferenceSubType, ItemConferenceSubTypes } from "../../lib/ItemUtil";
|
import { ItemConference, ItemConferenceSubType, ItemConferenceSubTypes } from '../../lib/ItemUtil';
|
||||||
|
|
||||||
interface PresentationTypeProps {
|
interface PresentationTypeProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -12,7 +12,7 @@ const PresentationType: React.FC<PresentationTypeProps> = (props: PresentationTy
|
|||||||
const subtype = ItemConferenceSubTypes.find((value) => {
|
const subtype = ItemConferenceSubTypes.find((value) => {
|
||||||
return value.type === type;
|
return value.type === type;
|
||||||
});
|
});
|
||||||
if (typeof subtype === "undefined") {
|
if (typeof subtype === 'undefined') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <span>{subtype.label}</span>;
|
return <span>{subtype.label}</span>;
|
||||||
@ -25,9 +25,34 @@ interface ConferenceDateProps {
|
|||||||
|
|
||||||
const ConferenceDate: React.FC<ConferenceDateProps> = (props: ConferenceDateProps) => {
|
const ConferenceDate: React.FC<ConferenceDateProps> = (props: ConferenceDateProps) => {
|
||||||
const { item } = props;
|
const { item } = props;
|
||||||
const monthStr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
const monthStr = [
|
||||||
const from = "From: " + monthStr[item.conference_from_month - 1] + " " + item.conference_from_mday + ", " + item.conference_from_year;
|
'Jan',
|
||||||
const to = "To: " + monthStr[item.conference_to_month - 1] + " " + item.conference_to_mday + ", " + item.conference_to_year;
|
'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 (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{from} {to}
|
{from} {to}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import ConferenceAdvancedSearch from "./ConferenceAdvancedSearch";
|
import ConferenceAdvancedSearch from './ConferenceAdvancedSearch';
|
||||||
import ConferenceDetail from "./ConferenceDetail";
|
import ConferenceDetail from './ConferenceDetail';
|
||||||
import ConferenceList from "./ConferenceList";
|
import ConferenceList from './ConferenceList';
|
||||||
import ConferenceTop from "./ConferenceTop";
|
import ConferenceTop from './ConferenceTop';
|
||||||
|
|
||||||
const ItemTypeConference = {
|
const ItemTypeConference = {
|
||||||
Top: ConferenceTop,
|
Top: ConferenceTop,
|
||||||
|
@ -1,42 +1,68 @@
|
|||||||
import { ItemDataSubTypes } from "../../lib/ItemUtil";
|
import { ItemDataSubTypes } from '../../lib/ItemUtil';
|
||||||
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
|
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
|
||||||
|
|
||||||
class DataAdvancedSearch extends AdvancedSearchBase {
|
class DataAdvancedSearch extends AdvancedSearchBase {
|
||||||
constructor(props: AdvancedSearchBaseProps) {
|
constructor(props: AdvancedSearchBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "data";
|
this.type = 'data';
|
||||||
this.title = "Data";
|
this.title = 'Data';
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const year = String(now.getFullYear());
|
const year = String(now.getFullYear());
|
||||||
const month = String(now.getMonth() + 1);
|
const month = String(now.getMonth() + 1);
|
||||||
const mday = String(now.getDate());
|
const mday = String(now.getDate());
|
||||||
this.state.values["title"] = "";
|
this.state.values.title = '';
|
||||||
this.state.values["keyword"] = "";
|
this.state.values.keyword = '';
|
||||||
this.state.values["description"] = "";
|
this.state.values.description = '';
|
||||||
this.state.values["doi"] = "";
|
this.state.values.doi = '';
|
||||||
this.state.values["data_type"] = "";
|
this.state.values.data_type = '';
|
||||||
this.state.values["experimenter"] = "";
|
this.state.values.experimenter = '';
|
||||||
this.state.values["publication_year"] = year;
|
this.state.values.publication_year = year;
|
||||||
this.state.values["publication_month"] = month;
|
this.state.values.publication_month = month;
|
||||||
this.state.values["publication_mday"] = mday;
|
this.state.values.publication_mday = mday;
|
||||||
this.state.values["file.preview.caption"] = "";
|
this.state.values['file.preview.caption'] = '';
|
||||||
this.state.values["file.data_file.original_file_name"] = "";
|
this.state.values['file.data_file.original_file_name'] = '';
|
||||||
this.setIgnoreKey("publication_year");
|
this.setIgnoreKey('publication_year');
|
||||||
this.setIgnoreKey("publication_month");
|
this.setIgnoreKey('publication_month');
|
||||||
this.setIgnoreKey("publication_mday");
|
this.setIgnoreKey('publication_mday');
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows() {
|
getRows() {
|
||||||
const rows = [
|
const rows = [
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 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: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
|
value: this.renderFieldInputText('keyword', 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]Description[/en][ja]概要[/ja]',
|
||||||
{ label: "[en]Caption[/en][ja]キャプション[/ja]", value: this.renderFieldInputText("file.preview.caption", 50) },
|
value: this.renderFieldInputText('description', 50),
|
||||||
{ label: "[en]Data File[/en][ja]データファイル[/ja]", value: this.renderFieldInputText("file.data_file.original_file_name", 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;
|
return rows;
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,113 @@
|
|||||||
import React from "react";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import ItemUtil, { ItemData } from '../../lib/ItemUtil';
|
||||||
import ItemUtil, { ItemData } from "../../lib/ItemUtil";
|
import DetailBase from '../lib/DetailBase';
|
||||||
import DetailBase from "../lib/DetailBase";
|
import ItemTypeField from '../lib/field';
|
||||||
import ItemTypeField from "../lib/field";
|
import SimPFLinkIcon from '../lib/field/SimPFLinkIcon';
|
||||||
import SimPFLinkIcon from "../lib/field/SimPFLinkIcon";
|
import DataUtil from './DataUtil';
|
||||||
import DataUtil from "./DataUtil";
|
|
||||||
|
|
||||||
class DataDetail extends DetailBase {
|
class DataDetail extends DetailBase {
|
||||||
getFields() {
|
getFields() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const item = this.props.item as ItemData;
|
const item = this.props.item as ItemData;
|
||||||
const fields = [
|
const fields = [
|
||||||
{ label: "ID", value: item.doi },
|
{ label: 'ID', value: item.doi },
|
||||||
{ label: "[en]Language[/en][ja]言語[/ja]", value: <ItemTypeField.Language lang={lang} itemLang={item.lang} /> },
|
{
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: Functions.mlang(item.title, lang) },
|
label: '[en]Language[/en][ja]言語[/ja]',
|
||||||
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} /> },
|
value: <ItemTypeField.Language lang={lang} itemLang={item.lang} />,
|
||||||
{ label: "[en]Description[/en][ja]概要[/ja]", value: <ItemTypeField.Description lang={lang} description={item.description} /> },
|
},
|
||||||
{ label: "[en]Date[/en][ja]日付[/ja]", value: <ItemTypeField.PublicationDate lang={lang} year={item.publication_year} month={item.publication_month} mday={item.publication_mday} /> },
|
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) },
|
||||||
{ label: "[en]Last Modified Date[/en][ja]最終更新日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} /> },
|
{
|
||||||
{ label: "[en]Created Date[/en][ja]作成日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} /> },
|
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "[en]Contributor[/en][ja]登録者[/ja]", value: <ItemTypeField.Contributer lang={lang} uname={item.uname} name={item.name} /> },
|
value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} />,
|
||||||
{ label: "[en]Item Type[/en][ja]アイテムタイプ[/ja]", value: item.item_type_display_name },
|
},
|
||||||
{ label: "[en]Change Log(History)[/en][ja]変更履歴[/ja]", value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} /> },
|
{
|
||||||
{ label: "[en]Data Type[/en][ja]データタイプ[/ja]", value: <DataUtil.DataType lang={lang} type={item.data_type} /> },
|
label: '[en]Description[/en][ja]概要[/ja]',
|
||||||
{ label: "[en]Experimenter[/en][ja]実験者[/ja]", value: <ItemTypeField.Author lang={lang} author={item.experimenter} /> },
|
value: <ItemTypeField.Description lang={lang} description={item.description} />,
|
||||||
{ label: "[en]Preview[/en][ja]プレビュー[/ja]", value: <ItemTypeField.Preview lang={lang} file={item.file} type={type} /> },
|
},
|
||||||
{ label: "[en]Data File[/en][ja]データファイル[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="data_file" rights={item.rights} useCc={item.use_cc} ccCommercialUse={item.cc_commercial_use} ccModification={item.cc_modification} downloadLimit={item.attachment_dl_limit} type={type} /> },
|
{
|
||||||
{ label: "Readme", value: <ItemTypeField.Readme lang={lang} readme={item.readme} /> },
|
label: '[en]Date[/en][ja]日付[/ja]',
|
||||||
{ label: "Rights", value: <ItemTypeField.Rights lang={lang} rights={item.rights} useCc={item.use_cc} ccCommercialUse={item.cc_commercial_use} ccModification={item.cc_modification} /> },
|
value: (
|
||||||
{ label: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
|
<ItemTypeField.PublicationDate
|
||||||
{ label: "[en]Related to[/en][ja]関連アイテム[/ja]", value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} /> },
|
lang={lang}
|
||||||
|
year={item.publication_year}
|
||||||
|
month={item.publication_month}
|
||||||
|
mday={item.publication_mday}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Created Date[/en][ja]作成日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Contributor[/en][ja]登録者[/ja]',
|
||||||
|
value: <ItemTypeField.Contributor lang={lang} uname={item.uname} name={item.name} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name },
|
||||||
|
{
|
||||||
|
label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]',
|
||||||
|
value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Data Type[/en][ja]データタイプ[/ja]',
|
||||||
|
value: <DataUtil.DataType lang={lang} type={item.data_type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Experimenter[/en][ja]実験者[/ja]',
|
||||||
|
value: <ItemTypeField.Author lang={lang} author={item.experimenter} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Preview[/en][ja]プレビュー[/ja]',
|
||||||
|
value: <ItemTypeField.Preview lang={lang} file={item.file} type={type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Data File[/en][ja]データファイル[/ja]',
|
||||||
|
value: (
|
||||||
|
<ItemTypeField.ItemFile
|
||||||
|
lang={lang}
|
||||||
|
file={item.file}
|
||||||
|
fileType="data_file"
|
||||||
|
rights={item.rights}
|
||||||
|
useCc={item.use_cc}
|
||||||
|
ccCommercialUse={item.cc_commercial_use}
|
||||||
|
ccModification={item.cc_modification}
|
||||||
|
downloadLimit={item.attachment_dl_limit}
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ label: 'Readme', value: <ItemTypeField.Readme lang={lang} readme={item.readme} /> },
|
||||||
|
{
|
||||||
|
label: 'Rights',
|
||||||
|
value: (
|
||||||
|
<ItemTypeField.Rights
|
||||||
|
lang={lang}
|
||||||
|
rights={item.rights}
|
||||||
|
useCc={item.use_cc}
|
||||||
|
ccCommercialUse={item.cc_commercial_use}
|
||||||
|
ccModification={item.cc_modification}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Index',
|
||||||
|
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Related to[/en][ja]関連アイテム[/ja]',
|
||||||
|
value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id);
|
const simpfLinkUrl = ItemUtil.getSimPFLinkUrl(item.item_id);
|
||||||
if (simpfLinkUrl !== "") {
|
if (simpfLinkUrl !== '') {
|
||||||
const field = { label: "Online Simulation", value: <SimPFLinkIcon lang={lang} url={simpfLinkUrl} isDetail={true} /> };
|
const field = {
|
||||||
|
label: 'Online Simulation',
|
||||||
|
value: <SimPFLinkIcon lang={lang} url={simpfLinkUrl} isDetail={true} />,
|
||||||
|
};
|
||||||
fields.splice(14, 0, field);
|
fields.splice(14, 0, field);
|
||||||
}
|
}
|
||||||
return fields;
|
return fields;
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import React, { Fragment } from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import Functions from "../../../functions";
|
import { Link } from 'react-router-dom';
|
||||||
import iconFile from "../../assets/images/icon_data.gif";
|
import Functions from '../../../functions';
|
||||||
import { ItemData } from "../../lib/ItemUtil";
|
import iconFile from '../../assets/images/icon_data.gif';
|
||||||
import ListBase, { ListBaseProps } from "../lib/ListBase";
|
import { ItemData } from '../../lib/ItemUtil';
|
||||||
|
import ListBase, { ListBaseProps } from '../lib/ListBase';
|
||||||
|
|
||||||
class DataList extends ListBase {
|
class DataList extends ListBase {
|
||||||
constructor(props: ListBaseProps) {
|
constructor(props: ListBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.label = "Data";
|
this.label = 'Data';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,10 +18,10 @@ class DataList extends ListBase {
|
|||||||
const item = this.props.item as ItemData;
|
const item = this.props.item as ItemData;
|
||||||
const authors = item.experimenter.map((author, i) => {
|
const authors = item.experimenter.map((author, i) => {
|
||||||
return (
|
return (
|
||||||
<Fragment key={i}>
|
<React.Fragment key={i}>
|
||||||
{i > 0 && ", "}
|
{i > 0 && ', '}
|
||||||
{Functions.mlang(author, lang)}
|
{Functions.mlang(author, lang)}
|
||||||
</Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import iconFile from "../../assets/images/icon_data.gif";
|
import iconFile from '../../assets/images/icon_data.gif';
|
||||||
import { ItemDataSubTypes } from "../../lib/ItemUtil";
|
import { ItemDataSubTypes } from '../../lib/ItemUtil';
|
||||||
import TopBase, { TopBaseProps } from "../lib/TopBase";
|
import TopBase, { TopBaseProps } from '../lib/TopBase';
|
||||||
|
|
||||||
class DataTop extends TopBase {
|
class DataTop extends TopBase {
|
||||||
constructor(props: TopBaseProps) {
|
constructor(props: TopBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "data";
|
this.type = 'data';
|
||||||
this.label = "Data";
|
this.label = 'Data';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
this.description = "[en]Result data in numerical text/image/movie formats.[/en][ja]実験結果の数値データ/画像/動画など[/ja]";
|
this.description =
|
||||||
|
'[en]Result data in numerical text/image/movie formats.[/en][ja]実験結果の数値データ/画像/動画など[/ja]';
|
||||||
this.subTypes = ItemDataSubTypes;
|
this.subTypes = ItemDataSubTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../config";
|
import { MultiLang } from '../../../config';
|
||||||
import { ItemDataSubType, ItemDataSubTypes } from "../../lib/ItemUtil";
|
import { ItemDataSubType, ItemDataSubTypes } from '../../lib/ItemUtil';
|
||||||
|
|
||||||
interface DataTypeProps {
|
interface DataTypeProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -12,7 +12,7 @@ const DataType: React.FC<DataTypeProps> = (props: DataTypeProps) => {
|
|||||||
const subtype = ItemDataSubTypes.find((value) => {
|
const subtype = ItemDataSubTypes.find((value) => {
|
||||||
return value.type === type;
|
return value.type === type;
|
||||||
});
|
});
|
||||||
if (typeof subtype === "undefined") {
|
if (typeof subtype === 'undefined') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <span>{subtype.label}</span>;
|
return <span>{subtype.label}</span>;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import DataAdvancedSearch from "./DataAdvancedSearch";
|
import DataAdvancedSearch from './DataAdvancedSearch';
|
||||||
import DataDetail from "./DataDetail";
|
import DataDetail from './DataDetail';
|
||||||
import DataList from "./DataList";
|
import DataList from './DataList';
|
||||||
import DataTop from "./DataTop";
|
import DataTop from './DataTop';
|
||||||
|
|
||||||
const ItemTypeData = {
|
const ItemTypeData = {
|
||||||
Top: DataTop,
|
Top: DataTop,
|
||||||
|
@ -1,26 +1,41 @@
|
|||||||
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
|
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
|
||||||
|
|
||||||
class FilesAdvancedSearch extends AdvancedSearchBase {
|
class FilesAdvancedSearch extends AdvancedSearchBase {
|
||||||
constructor(props: AdvancedSearchBaseProps) {
|
constructor(props: AdvancedSearchBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "files";
|
this.type = 'files';
|
||||||
this.title = "Files";
|
this.title = 'Files';
|
||||||
this.state.values["title"] = "";
|
this.state.values.title = '';
|
||||||
this.state.values["data_file_name"] = "";
|
this.state.values.data_file_name = '';
|
||||||
this.state.values["data_file_mimetype"] = "";
|
this.state.values.data_file_mimetype = '';
|
||||||
this.state.values["data_file_filetype"] = "";
|
this.state.values.data_file_filetype = '';
|
||||||
this.state.values["keyword"] = "";
|
this.state.values.keyword = '';
|
||||||
this.state.values["description"] = "";
|
this.state.values.description = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows() {
|
getRows() {
|
||||||
const rows = [
|
const rows = [
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 50) },
|
{ 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 Name[/en][ja]ファイル名[/ja]',
|
||||||
{ label: "- [en]File Type[/en][ja]ファイルタイプ[/ja]", value: this.renderFieldInputText("data_file_filetype", 20) },
|
value: this.renderFieldInputText('data_file_name', 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: '- [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;
|
return rows;
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,61 @@
|
|||||||
import React from "react";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import { ItemFiles } from '../../lib/ItemUtil';
|
||||||
import { ItemFiles } from "../../lib/ItemUtil";
|
import DetailBase from '../lib/DetailBase';
|
||||||
import DetailBase from "../lib/DetailBase";
|
import ItemTypeField from '../lib/field';
|
||||||
import ItemTypeField from "../lib/field";
|
|
||||||
|
|
||||||
class FilesDetail extends DetailBase {
|
class FilesDetail extends DetailBase {
|
||||||
getFields() {
|
getFields() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const item = this.props.item as ItemFiles;
|
const item = this.props.item as ItemFiles;
|
||||||
return [
|
return [
|
||||||
{ label: "ID", value: item.doi },
|
{ label: 'ID', value: item.doi },
|
||||||
{ label: "[en]Language[/en][ja]言語[/ja]", value: <ItemTypeField.Language lang={lang} itemLang={item.lang} /> },
|
{
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: Functions.mlang(item.title, lang) },
|
label: '[en]Language[/en][ja]言語[/ja]',
|
||||||
{ label: "[en]Last Modified Date[/en][ja]最終更新日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} /> },
|
value: <ItemTypeField.Language lang={lang} itemLang={item.lang} />,
|
||||||
{ label: "[en]Created Date[/en][ja]作成日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} /> },
|
},
|
||||||
{ label: "[en]Contributor[/en][ja]登録者[/ja]", value: <ItemTypeField.Contributer lang={lang} uname={item.uname} name={item.name} /> },
|
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) },
|
||||||
{ label: "[en]Item Type[/en][ja]アイテムタイプ[/ja]", value: item.item_type_display_name },
|
{
|
||||||
{ label: "[en]Change Log(History)[/en][ja]変更履歴[/ja]", value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} /> },
|
label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]',
|
||||||
{ label: "[en]Data File[/en][ja]データファイル[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="files_file" type={type} /> },
|
value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} />,
|
||||||
{ 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]Created Date[/en][ja]作成日[/ja]',
|
||||||
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} /> },
|
value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} />,
|
||||||
{ label: "[en]Description[/en][ja]概要[/ja]", value: <ItemTypeField.Description lang={lang} description={item.description} /> },
|
},
|
||||||
{ label: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
|
{
|
||||||
{ label: "[en]Related to[/en][ja]関連アイテム[/ja]", value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} /> },
|
label: '[en]Contributor[/en][ja]登録者[/ja]',
|
||||||
|
value: <ItemTypeField.Contributor lang={lang} uname={item.uname} name={item.name} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name },
|
||||||
|
{
|
||||||
|
label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]',
|
||||||
|
value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Data File[/en][ja]データファイル[/ja]',
|
||||||
|
value: (
|
||||||
|
<ItemTypeField.ItemFile lang={lang} file={item.file} fileType="files_file" type={type} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ 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: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Description[/en][ja]概要[/ja]',
|
||||||
|
value: <ItemTypeField.Description lang={lang} description={item.description} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Index',
|
||||||
|
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Related to[/en][ja]関連アイテム[/ja]',
|
||||||
|
value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import React from "react";
|
import { Link } from 'react-router-dom';
|
||||||
import { Link } from "react-router-dom";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import iconFile from '../../assets/images/icon_files.gif';
|
||||||
import iconFile from "../../assets/images/icon_files.gif";
|
import { ItemFiles } from '../../lib/ItemUtil';
|
||||||
import { ItemFiles } from "../../lib/ItemUtil";
|
import ListBase, { ListBaseProps } from '../lib/ListBase';
|
||||||
import Contributer from "../lib/field/Contributer";
|
import Contributor from '../lib/field/Contributor';
|
||||||
import ListBase, { ListBaseProps } from "../lib/ListBase";
|
|
||||||
|
|
||||||
class FilesList extends ListBase {
|
class FilesList extends ListBase {
|
||||||
constructor(props: ListBaseProps) {
|
constructor(props: ListBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.label = "Files";
|
this.label = 'Files';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,7 +19,7 @@ class FilesList extends ListBase {
|
|||||||
<>
|
<>
|
||||||
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
|
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
|
||||||
<br />
|
<br />
|
||||||
<Contributer lang={lang} uname={item.uname} name={item.name} />
|
<Contributor lang={lang} uname={item.uname} name={item.name} />
|
||||||
<br />
|
<br />
|
||||||
{item.data_file_mimetype}
|
{item.data_file_mimetype}
|
||||||
</>
|
</>
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import iconFile from "../../assets/images/icon_files.gif";
|
import iconFile from '../../assets/images/icon_files.gif';
|
||||||
import { ItemFilesSubTypes } from "../../lib/ItemUtil";
|
import { ItemFilesSubTypes } from '../../lib/ItemUtil';
|
||||||
import TopBase, { TopBaseProps } from "../lib/TopBase";
|
import TopBase, { TopBaseProps } from '../lib/TopBase';
|
||||||
|
|
||||||
class FilesTop extends TopBase {
|
class FilesTop extends TopBase {
|
||||||
constructor(props: TopBaseProps) {
|
constructor(props: TopBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "files";
|
this.type = 'files';
|
||||||
this.label = "Files";
|
this.label = 'Files';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
this.description = "[en]Various type of File.[/en][ja]ファイル[/ja]";
|
this.description = '[en]Various type of File.[/en][ja]ファイル[/ja]';
|
||||||
this.subTypes = ItemFilesSubTypes;
|
this.subTypes = ItemFilesSubTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import FilesAdvancedSearch from "./FilesAdvancedSearch";
|
import FilesAdvancedSearch from './FilesAdvancedSearch';
|
||||||
import FilesDetail from "./FilesDetail";
|
import FilesDetail from './FilesDetail';
|
||||||
import FilesList from "./FilesList";
|
import FilesList from './FilesList';
|
||||||
import FilesTop from "./FilesTop";
|
import FilesTop from './FilesTop';
|
||||||
|
|
||||||
const ItemTypeFiles = {
|
const ItemTypeFiles = {
|
||||||
Top: FilesTop,
|
Top: FilesTop,
|
||||||
|
@ -1,7 +1,21 @@
|
|||||||
import React from 'react';
|
import { BrainAtlasType, MultiLang } from '../../config';
|
||||||
import { MultiLang, BrainAtlasType } from '../../config';
|
|
||||||
import AdvancedSearchQuery from '../lib/AdvancedSearchQuery';
|
import AdvancedSearchQuery from '../lib/AdvancedSearchQuery';
|
||||||
import { Item, ItemBinder, ItemBook, ItemConference, ItemData, ItemFiles, ItemModel, ItemPaper, ItemPresentation, ItemSimulator, ItemStimulus, ItemTool, ItemUrl, ItemMemo } from '../lib/ItemUtil';
|
import {
|
||||||
|
Item,
|
||||||
|
ItemBinder,
|
||||||
|
ItemBook,
|
||||||
|
ItemConference,
|
||||||
|
ItemData,
|
||||||
|
ItemFiles,
|
||||||
|
ItemMemo,
|
||||||
|
ItemModel,
|
||||||
|
ItemPaper,
|
||||||
|
ItemPresentation,
|
||||||
|
ItemSimulator,
|
||||||
|
ItemStimulus,
|
||||||
|
ItemTool,
|
||||||
|
ItemUrl,
|
||||||
|
} from '../lib/ItemUtil';
|
||||||
import ItemTypeBinder from './binder';
|
import ItemTypeBinder from './binder';
|
||||||
import ItemTypeBook from './book';
|
import ItemTypeBook from './book';
|
||||||
import ItemTypeConference from './conference';
|
import ItemTypeConference from './conference';
|
||||||
@ -53,7 +67,7 @@ const Top = (props: TopProps) => {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
interface ListProps {
|
interface ListProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -92,7 +106,7 @@ const List = (props: ListProps) => {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
interface DetailProps {
|
interface DetailProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -119,7 +133,9 @@ const Detail = (props: DetailProps) => {
|
|||||||
case 'xnppaper':
|
case 'xnppaper':
|
||||||
return <ItemTypePaper.Detail lang={lang} item={item as ItemPaper} type={type} />;
|
return <ItemTypePaper.Detail lang={lang} item={item as ItemPaper} type={type} />;
|
||||||
case 'xnppresentation':
|
case 'xnppresentation':
|
||||||
return <ItemTypePresentation.Detail lang={lang} item={item as ItemPresentation} type={type} />;
|
return (
|
||||||
|
<ItemTypePresentation.Detail lang={lang} item={item as ItemPresentation} type={type} />
|
||||||
|
);
|
||||||
case 'xnpsimulator':
|
case 'xnpsimulator':
|
||||||
return <ItemTypeSimulator.Detail lang={lang} item={item as ItemSimulator} type={type} />;
|
return <ItemTypeSimulator.Detail lang={lang} item={item as ItemSimulator} type={type} />;
|
||||||
case 'xnpstimulus':
|
case 'xnpstimulus':
|
||||||
@ -131,7 +147,7 @@ const Detail = (props: DetailProps) => {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
interface AdvancedSearchProps {
|
interface AdvancedSearchProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -170,13 +186,13 @@ const AdvancedSearch = (props: AdvancedSearchProps) => {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const ItemType = {
|
const ItemType = {
|
||||||
Top,
|
Top,
|
||||||
List,
|
List,
|
||||||
Detail,
|
Detail,
|
||||||
AdvancedSearch
|
AdvancedSearch,
|
||||||
}
|
};
|
||||||
|
|
||||||
export default ItemType;
|
export default ItemType;
|
@ -1,8 +1,8 @@
|
|||||||
import React, { ChangeEvent } from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../config";
|
import { MultiLang } from '../../../config';
|
||||||
import Functions from "../../../functions";
|
import Functions from '../../../functions';
|
||||||
import AdvancedSearchQuery from "../../lib/AdvancedSearchQuery";
|
import AdvancedSearchQuery from '../../lib/AdvancedSearchQuery';
|
||||||
import { ItemSubTypes } from "../../lib/ItemUtil";
|
import { ItemSubTypesAll } from '../../lib/ItemUtil';
|
||||||
|
|
||||||
export interface AdvancedSearchBaseProps {
|
export interface AdvancedSearchBaseProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -11,12 +11,12 @@ export interface AdvancedSearchBaseProps {
|
|||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
show: boolean;
|
show: boolean;
|
||||||
values: any;
|
values: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State> {
|
class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State> {
|
||||||
protected type: string = "base";
|
protected type = 'base';
|
||||||
protected title: string = "Base";
|
protected title = 'Base';
|
||||||
protected query: AdvancedSearchQuery;
|
protected query: AdvancedSearchQuery;
|
||||||
protected ignoreKeys: string[] = [];
|
protected ignoreKeys: string[] = [];
|
||||||
|
|
||||||
@ -55,13 +55,13 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateField(key: string, value: string) {
|
updateField(key: string, value: string) {
|
||||||
let values = Object.assign({}, this.state.values);
|
const values = Object.assign({}, this.state.values);
|
||||||
values[key] = value;
|
values[key] = value;
|
||||||
this.updateQuery(key, value);
|
this.updateQuery(key, value);
|
||||||
this.setState({ values });
|
this.setState({ values });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeTitleCheck(e: ChangeEvent<HTMLInputElement>) {
|
handleChangeTitleCheck(e: React.ChangeEvent<HTMLInputElement>) {
|
||||||
const show = e.target.checked;
|
const show = e.target.checked;
|
||||||
if (show) {
|
if (show) {
|
||||||
Object.keys(this.state.values).forEach((key) => {
|
Object.keys(this.state.values).forEach((key) => {
|
||||||
@ -79,14 +79,22 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderFieldInputText(key: string, size: number) {
|
renderFieldInputText(key: string, size: number) {
|
||||||
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
|
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
this.updateField(key, e.target.value);
|
this.updateField(key, e.target.value);
|
||||||
};
|
};
|
||||||
return <input className="fieldInputText" type="text" value={this.state.values[key]} size={size} onChange={onChange} />;
|
return (
|
||||||
|
<input
|
||||||
|
className="fieldInputText"
|
||||||
|
type="text"
|
||||||
|
value={this.state.values[key]}
|
||||||
|
size={size}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFieldSelect(key: string, values: ItemSubTypes<any>) {
|
renderFieldSelect(key: string, values: ItemSubTypesAll) {
|
||||||
const onChange = (e: ChangeEvent<HTMLSelectElement>) => {
|
const onChange: React.ChangeEventHandler<HTMLSelectElement> = (e) => {
|
||||||
this.updateField(key, e.target.value);
|
this.updateField(key, e.target.value);
|
||||||
};
|
};
|
||||||
const options = values.map(({ type, label }, i) => {
|
const options = values.map(({ type, label }, i) => {
|
||||||
@ -105,18 +113,31 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderFieldDate(label: string, keyYear: string, keyMonth: string, keyMday: string) {
|
renderFieldDate(label: string, keyYear: string, keyMonth: string, keyMday: string) {
|
||||||
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
|
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
this.deleteIgnoreKey(keyYear);
|
this.deleteIgnoreKey(keyYear);
|
||||||
keyMonth !== "" && this.deleteIgnoreKey(keyMonth);
|
keyMonth !== '' && this.deleteIgnoreKey(keyMonth);
|
||||||
keyMday !== "" && this.deleteIgnoreKey(keyMday);
|
keyMday !== '' && this.deleteIgnoreKey(keyMday);
|
||||||
} else {
|
} else {
|
||||||
this.setIgnoreKey(keyYear);
|
this.setIgnoreKey(keyYear);
|
||||||
keyMonth !== "" && this.setIgnoreKey(keyMonth);
|
keyMonth !== '' && this.setIgnoreKey(keyMonth);
|
||||||
keyMday !== "" && this.setIgnoreKey(keyMday);
|
keyMday !== '' && this.setIgnoreKey(keyMday);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
const month = [
|
||||||
|
'Jan',
|
||||||
|
'Feb',
|
||||||
|
'Mar',
|
||||||
|
'Apr',
|
||||||
|
'May',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Aug',
|
||||||
|
'Sep',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Dec',
|
||||||
|
];
|
||||||
const monthOptions = month.map((value, i) => {
|
const monthOptions = month.map((value, i) => {
|
||||||
return (
|
return (
|
||||||
<option key={i} value={i + 1}>
|
<option key={i} value={i + 1}>
|
||||||
@ -124,29 +145,40 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
|
|||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
let mdayOptions: JSX.Element[] = [];
|
const mdayOptions: JSX.Element[] = [];
|
||||||
for (let i = 1; i <= 31; i++) {
|
for (let i = 1; i <= 31; i++) {
|
||||||
mdayOptions.push(
|
mdayOptions.push(
|
||||||
<option key={i} value={i}>
|
<option key={i} value={i}>
|
||||||
{i}
|
{i}
|
||||||
</option>
|
</option>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="fieldDate">
|
<div className="fieldDate">
|
||||||
<input type="checkbox" onChange={onChange} />
|
<input type="checkbox" onChange={onChange} />
|
||||||
{label.length !== 0 && <label className="fieldDateLabel">{label}</label>}
|
{label.length !== 0 && <label className="fieldDateLabel">{label}</label>}
|
||||||
{keyMonth !== "" && (
|
{keyMonth !== '' && (
|
||||||
<select value={this.state.values[keyMonth]} onChange={(e) => this.updateField(keyMonth, e.target.value)}>
|
<select
|
||||||
|
value={this.state.values[keyMonth]}
|
||||||
|
onChange={(e) => this.updateField(keyMonth, e.target.value)}
|
||||||
|
>
|
||||||
{monthOptions}
|
{monthOptions}
|
||||||
</select>
|
</select>
|
||||||
)}
|
)}
|
||||||
{keyMday !== "" && (
|
{keyMday !== '' && (
|
||||||
<select value={this.state.values[keyMday]} onChange={(e) => this.updateField(keyMday, e.target.value)}>
|
<select
|
||||||
|
value={this.state.values[keyMday]}
|
||||||
|
onChange={(e) => this.updateField(keyMday, e.target.value)}
|
||||||
|
>
|
||||||
{mdayOptions}
|
{mdayOptions}
|
||||||
</select>
|
</select>
|
||||||
)}
|
)}
|
||||||
<input type="text" value={this.state.values[keyYear]} size={5} onChange={(e) => this.updateField(keyYear, e.target.value)} />
|
<input
|
||||||
|
type="text"
|
||||||
|
value={this.state.values[keyYear]}
|
||||||
|
size={5}
|
||||||
|
onChange={(e) => this.updateField(keyYear, e.target.value)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -158,7 +190,7 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
|
|||||||
}
|
}
|
||||||
const rows = this.getRows();
|
const rows = this.getRows();
|
||||||
const fields = rows.map((value, idx) => {
|
const fields = rows.map((value, idx) => {
|
||||||
const evenodd = idx % 2 === 0 ? "even" : "odd";
|
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
|
||||||
return (
|
return (
|
||||||
<tr key={idx}>
|
<tr key={idx}>
|
||||||
<td className="head">{Functions.mlang(value.label, lang)}</td>
|
<td className="head">{Functions.mlang(value.label, lang)}</td>
|
||||||
@ -180,7 +212,11 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th align="left">
|
<th align="left">
|
||||||
<input type="checkbox" checked={this.state.show} onChange={this.handleChangeTitleCheck} />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={this.state.show}
|
||||||
|
onChange={(e) => this.handleChangeTitleCheck(e)}
|
||||||
|
/>
|
||||||
{this.title}
|
{this.title}
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React, { ReactNode } from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../../../config";
|
|
||||||
import Functions from "../../../functions";
|
import { BrainAtlasType, MultiLang } from '../../../config';
|
||||||
import { Item } from "../../lib/ItemUtil";
|
import Functions from '../../../functions';
|
||||||
|
import { Item } from '../../lib/ItemUtil';
|
||||||
|
|
||||||
export interface DetailBaseField {
|
export interface DetailBaseField {
|
||||||
label: string;
|
label: string;
|
||||||
value: ReactNode;
|
value: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DetailBaseProps {
|
export interface DetailBaseProps {
|
||||||
@ -22,7 +23,7 @@ class DetailBase extends React.Component<DetailBaseProps> {
|
|||||||
render() {
|
render() {
|
||||||
const { lang } = this.props;
|
const { lang } = this.props;
|
||||||
const elements = this.getFields().map((value, idx) => {
|
const elements = this.getFields().map((value, idx) => {
|
||||||
const evenodd = idx % 2 === 0 ? "even" : "odd";
|
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
|
||||||
return (
|
return (
|
||||||
<tr key={idx}>
|
<tr key={idx}>
|
||||||
<td className="head">{Functions.mlang(value.label, lang)}</td>
|
<td className="head">{Functions.mlang(value.label, lang)}</td>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../../../config";
|
|
||||||
import ItemUtil, { Item } from "../../lib/ItemUtil";
|
import { BrainAtlasType, MultiLang } from '../../../config';
|
||||||
import SimPFLinkIcon from "./field/SimPFLinkIcon";
|
import ItemUtil, { Item } from '../../lib/ItemUtil';
|
||||||
|
import SimPFLinkIcon from './field/SimPFLinkIcon';
|
||||||
|
|
||||||
export interface ListBaseProps {
|
export interface ListBaseProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -10,8 +11,8 @@ export interface ListBaseProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ListBase extends React.Component<ListBaseProps> {
|
class ListBase extends React.Component<ListBaseProps> {
|
||||||
protected label = "";
|
protected label = '';
|
||||||
protected icon = "";
|
protected icon = '';
|
||||||
protected url: string;
|
protected url: string;
|
||||||
protected simpfLinkUrl: string;
|
protected simpfLinkUrl: string;
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { Fragment } from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../../../config";
|
import { Link } from 'react-router-dom';
|
||||||
import Functions from "../../../functions";
|
import { BrainAtlasType, MultiLang } from '../../../config';
|
||||||
import ItemUtil, { ItemSubTypes } from "../../lib/ItemUtil";
|
import Functions from '../../../functions';
|
||||||
|
import ItemUtil, { ItemSubTypesAll } from '../../lib/ItemUtil';
|
||||||
|
|
||||||
export interface TopBaseProps {
|
export interface TopBaseProps {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -10,22 +11,22 @@ export interface TopBaseProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TopBase extends React.Component<TopBaseProps> {
|
class TopBase extends React.Component<TopBaseProps> {
|
||||||
protected type: string = "";
|
protected type = '';
|
||||||
protected label: string = "";
|
protected label = '';
|
||||||
protected icon: string = "";
|
protected icon = '';
|
||||||
protected description: string = "";
|
protected description = '';
|
||||||
protected subTypes: ItemSubTypes<any> = [];
|
protected subTypes: ItemSubTypesAll = [];
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const url = ItemUtil.getItemTypeSearchUrl(type, this.type, "");
|
const url = ItemUtil.getItemTypeSearchUrl(type, this.type, '');
|
||||||
const links = this.subTypes.map((subtype, i) => {
|
const links = this.subTypes.map((subtype, i) => {
|
||||||
const url = ItemUtil.getItemTypeSearchUrl(type, this.type, subtype.type);
|
const url = ItemUtil.getItemTypeSearchUrl(type, this.type, subtype.type);
|
||||||
return (
|
return (
|
||||||
<Fragment key={i}>
|
<React.Fragment key={i}>
|
||||||
{i > 0 && " / "}
|
{i > 0 && ' / '}
|
||||||
<Link to={url}>{subtype.label}</Link>
|
<Link to={url}>{subtype.label}</Link>
|
||||||
</Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
|
import { MultiLang } from '../../../../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
author: string[];
|
author: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Author: React.FC<Props> = (props: Props) => {
|
const Author: React.FC<Props> = (props) => {
|
||||||
const { author } = props;
|
const { author } = props;
|
||||||
if (author.length === 0) {
|
if (author.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const elements = author.map((value, idx) => {
|
const elements = author.map((value, idx) => {
|
||||||
const evenodd = idx % 2 === 0 ? "even" : "odd";
|
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
|
||||||
return (
|
return (
|
||||||
<tr key={idx}>
|
<tr key={idx}>
|
||||||
<td className={evenodd}>{value}</td>
|
<td className={evenodd}>{value}</td>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
import Functions from "../../../../functions";
|
import { MultiLang } from '../../../../config';
|
||||||
import { ItemBasicChangeLog } from "../../../lib/ItemUtil";
|
import Functions from '../../../../functions';
|
||||||
import DateTime from "./DateTime";
|
import { ItemBasicChangeLog } from '../../../lib/ItemUtil';
|
||||||
|
import DateTime from './DateTime';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
changelog: ItemBasicChangeLog[];
|
changelog: ItemBasicChangeLog[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChangeLog: React.FC<Props> = (props: Props) => {
|
const ChangeLog: React.FC<Props> = (props) => {
|
||||||
const { lang, changelog } = props;
|
const { lang, changelog } = props;
|
||||||
if (changelog.length === 0) {
|
if (changelog.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
import Functions from "../../../../functions";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
lang: MultiLang;
|
|
||||||
uname: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Contributer: React.FC<Props> = (props: Props) => {
|
|
||||||
const { lang, name, uname } = props;
|
|
||||||
const unsubscribed = "([en]Unsubscribed User[/en][ja]退会済みユーザ[/ja])";
|
|
||||||
const label = uname === "" ? unsubscribed : name === "" ? uname : name + " (" + uname + ")";
|
|
||||||
return <span>{Functions.mlang(label, lang)}</span>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Contributer;
|
|
19
src/database/item-type/lib/field/Contributor.tsx
Normal file
19
src/database/item-type/lib/field/Contributor.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { MultiLang } from '../../../../config';
|
||||||
|
import Functions from '../../../../functions';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
lang: MultiLang;
|
||||||
|
uname: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Contributor: React.FC<Props> = (props) => {
|
||||||
|
const { lang, name, uname } = props;
|
||||||
|
const unsubscribed = '([en]Unsubscribed User[/en][ja]退会済みユーザ[/ja])';
|
||||||
|
const label = uname === '' ? unsubscribed : name === '' ? uname : name + ' (' + uname + ')';
|
||||||
|
return <span>{Functions.mlang(label, lang)}</span>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Contributor;
|
@ -1,51 +1,57 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
|
|
||||||
export type CreativeCommonsType = "by" | "by-nc" | "by-nc-nd" | "by-nc-sa" | "by-nd" | "by-sa";
|
import { MultiLang } from '../../../../config';
|
||||||
|
|
||||||
export const getCreativeCommonsType = (ccCommercialUse: number, ccModification: number): CreativeCommonsType => {
|
type CreativeCommonsType = 'by' | 'by-nc' | 'by-nc-nd' | 'by-nc-sa' | 'by-nd' | 'by-sa';
|
||||||
|
|
||||||
|
const getCreativeCommonsType = (
|
||||||
|
ccCommercialUse: number,
|
||||||
|
ccModification: number,
|
||||||
|
): CreativeCommonsType => {
|
||||||
const cc = ccCommercialUse * 10 + ccModification;
|
const cc = ccCommercialUse * 10 + ccModification;
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
case 0:
|
case 0:
|
||||||
return "by-nc-nd";
|
return 'by-nc-nd';
|
||||||
case 1:
|
case 1:
|
||||||
return "by-nc-sa";
|
return 'by-nc-sa';
|
||||||
case 2:
|
case 2:
|
||||||
return "by-nc";
|
return 'by-nc';
|
||||||
case 10:
|
case 10:
|
||||||
return "by-nd";
|
return 'by-nd';
|
||||||
case 11:
|
case 11:
|
||||||
return "by-sa";
|
return 'by-sa';
|
||||||
case 12:
|
case 12:
|
||||||
default:
|
default:
|
||||||
return "by";
|
return 'by';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
type: CreativeCommonsType;
|
ccCommercialUse: number;
|
||||||
|
ccModification: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreativeCommons: React.FC<Props> = (props: Props) => {
|
const CreativeCommons: React.FC<Props> = (props) => {
|
||||||
const { type } = props;
|
const { ccCommercialUse, ccModification } = props;
|
||||||
const url = "http://creativecommons.org/licenses/" + type + "/4.0/";
|
const type = getCreativeCommonsType(ccCommercialUse, ccModification);
|
||||||
const logoUrl = "https://i.creativecommons.org/l/" + type + "/4.0/88x31.png";
|
const url = 'http://creativecommons.org/licenses/' + type + '/4.0/';
|
||||||
|
const logoUrl = 'https://i.creativecommons.org/l/' + type + '/4.0/88x31.png';
|
||||||
const labels = {
|
const labels = {
|
||||||
by: "Attribution",
|
by: 'Attribution',
|
||||||
nc: "NonCommercial",
|
nc: 'NonCommercial',
|
||||||
nd: "NoDerivatives",
|
nd: 'NoDerivatives',
|
||||||
sa: "ShareAlike",
|
sa: 'ShareAlike',
|
||||||
};
|
};
|
||||||
const label = type
|
const label = type
|
||||||
.split("-")
|
.split('-')
|
||||||
.map((value) => {
|
.map((value) => {
|
||||||
const prop = value as "by" | "nc" | "nd" | "sa";
|
const prop = value as 'by' | 'nc' | 'nd' | 'sa';
|
||||||
return labels[prop];
|
return labels[prop];
|
||||||
})
|
})
|
||||||
.join("-");
|
.join('-');
|
||||||
return (
|
return (
|
||||||
<table style={{ borderCollapse: "separate", borderSpacing: "5px" }}>
|
<table style={{ borderCollapse: 'separate', borderSpacing: '5px' }}>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -54,9 +60,9 @@ const CreativeCommons: React.FC<Props> = (props: Props) => {
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This work is licensed under a{" "}
|
This work is licensed under a{' '}
|
||||||
<a href={url} target="_blank" rel="license noopener noreferrer">
|
<a href={url} target="_blank" rel="license noopener noreferrer">
|
||||||
Criative Commons {label} 4.0 International License
|
Creative Commons {label} 4.0 International License
|
||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
</td>
|
</td>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import moment from "moment";
|
import React from 'react';
|
||||||
import React from "react";
|
|
||||||
import { MultiLang } from "../../../../config";
|
import moment from 'moment';
|
||||||
|
import { MultiLang } from '../../../../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -8,12 +9,12 @@ interface Props {
|
|||||||
onlyDate?: boolean;
|
onlyDate?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DateTime: React.FC<Props> = (props: Props) => {
|
const DateTime: React.FC<Props> = (props) => {
|
||||||
const { date, onlyDate } = props;
|
const { date, onlyDate } = props;
|
||||||
const d = moment(new Date(date * 1000));
|
const d = moment(new Date(date * 1000));
|
||||||
let format = "MMM D, Y";
|
let format = 'MMM D, Y';
|
||||||
if (typeof onlyDate === "undefined" || !onlyDate) {
|
if (typeof onlyDate === 'undefined' || !onlyDate) {
|
||||||
format += " HH:mm:ss";
|
format += ' HH:mm:ss';
|
||||||
}
|
}
|
||||||
return <span>{d.format(format)}</span>;
|
return <span>{d.format(format)}</span>;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import XoopsCode from "../../../../common/lib/XoopsCode";
|
|
||||||
import { MultiLang } from "../../../../config";
|
import XoopsCode from '../../../../common/lib/XoopsCode';
|
||||||
|
import { MultiLang } from '../../../../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -8,10 +9,10 @@ interface Props {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Description: React.FC<Props> = (props: Props) => {
|
const Description: React.FC<Props> = (props) => {
|
||||||
const { lang, description, className } = props;
|
const { lang, description, className } = props;
|
||||||
const textarea = <XoopsCode lang={lang} text={description} dobr={true} />;
|
const textarea = <XoopsCode lang={lang} text={description} dobr={true} />;
|
||||||
const name = typeof className === "undefined" ? "description" : className;
|
const name = typeof className === 'undefined' ? 'description' : className;
|
||||||
return <div className={name}>{textarea}</div>;
|
return <div className={name}>{textarea}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../../../../config";
|
|
||||||
import ItemUtil, { ItemBasicFile } from "../../../lib/ItemUtil";
|
import { BrainAtlasType, MultiLang } from '../../../../config';
|
||||||
import styles from "./FileDownloadButton.module.css";
|
import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil';
|
||||||
import LicenseAgreementDialog from "./LicenseAgreementDialog";
|
import styles from './FileDownloadButton.module.css';
|
||||||
|
import LicenseAgreementDialog from './LicenseAgreementDialog';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -14,44 +15,45 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const FileDownloadButton: React.FC<Props> = (props) => {
|
||||||
show: boolean;
|
const { lang, file, rights, useCc, ccCommercialUse, ccModification, type } = props;
|
||||||
}
|
|
||||||
|
|
||||||
class FileDownloadButton extends React.Component<Props, State> {
|
const [show, setShow] = React.useState<boolean>(false);
|
||||||
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<HTMLAnchorElement, MouseEvent>) {
|
const handleClickDownload: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
|
||||||
if (this.props.rights !== "") {
|
if (rights !== '') {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState({ show: true });
|
setShow(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
unsetShow() {
|
const url = ItemUtil.getFileUrl(type, file);
|
||||||
this.setState({ show: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang, file, rights, useCc, ccCommercialUse, ccModification, type } = this.props;
|
|
||||||
const url = ItemUtil.getFileUrl(type, this.props.file);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<a className={styles.downloadButton} href={url} download={file.original_file_name} target="_blank" rel="noopener noreferrer" onClick={this.handleClickDownload}>
|
<a
|
||||||
|
className={styles.downloadButton}
|
||||||
|
href={url}
|
||||||
|
download={file.original_file_name}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
onClick={handleClickDownload}
|
||||||
|
>
|
||||||
Download
|
Download
|
||||||
</a>
|
</a>
|
||||||
<LicenseAgreementDialog lang={lang} file={file} rights={rights} useCc={useCc} ccCommercialUse={ccCommercialUse} ccModification={ccModification} show={this.state.show} unsetShow={this.unsetShow} type={type} />
|
<LicenseAgreementDialog
|
||||||
|
lang={lang}
|
||||||
|
file={file}
|
||||||
|
rights={rights}
|
||||||
|
useCc={useCc}
|
||||||
|
ccCommercialUse={ccCommercialUse}
|
||||||
|
ccModification={ccModification}
|
||||||
|
show={show}
|
||||||
|
unsetShow={() => setShow(false)}
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default FileDownloadButton;
|
export default FileDownloadButton;
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
|
import { MultiLang } from '../../../../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
size: number;
|
size: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileSize: React.FC<Props> = (props: Props) => {
|
const FileSize: React.FC<Props> = (props) => {
|
||||||
const { size } = props;
|
const { size } = props;
|
||||||
const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
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 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];
|
const label = Math.round((size / Math.pow(1024, power)) * 10) / 10 + ' ' + units[power];
|
||||||
return <span>{label}</span>;
|
return <span>{label}</span>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
|
import { MultiLang } from '../../../../config';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
keyword: string[];
|
keyword: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const FreeKeyword: React.FC<Props> = (props: Props) => {
|
const FreeKeyword: React.FC<Props> = (props) => {
|
||||||
const { keyword } = props;
|
const { keyword } = props;
|
||||||
if (keyword.length === 0) {
|
if (keyword.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const label = keyword.join(", ");
|
const label = keyword.join(', ');
|
||||||
return <span>{label}</span>;
|
return <span>{label}</span>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../../../../config";
|
|
||||||
import Functions from "../../../../functions";
|
import { BrainAtlasType, MultiLang } from '../../../../config';
|
||||||
import { ItemBasicFile } from "../../../lib/ItemUtil";
|
import Functions from '../../../../functions';
|
||||||
import DateTime from "./DateTime";
|
import { ItemBasicFile } from '../../../lib/ItemUtil';
|
||||||
import FileDownloadButton from "./FileDownloadButton";
|
import DateTime from './DateTime';
|
||||||
import FileSize from "./FileSize";
|
import FileDownloadButton from './FileDownloadButton';
|
||||||
|
import FileSize from './FileSize';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
file: ItemBasicFile[];
|
file: ItemBasicFile[];
|
||||||
ftype: string;
|
fileType: string;
|
||||||
rights?: string;
|
rights?: string;
|
||||||
useCc?: number;
|
useCc?: number;
|
||||||
ccCommercialUse?: number;
|
ccCommercialUse?: number;
|
||||||
@ -18,17 +19,24 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ItemFile: React.FC<Props> = (props: Props) => {
|
const ItemFile: React.FC<Props> = (props) => {
|
||||||
const { lang, file, ftype, type } = props;
|
const {
|
||||||
const rights = typeof props.rights === "undefined" ? "" : props.rights;
|
lang,
|
||||||
const useCc = typeof props.useCc === "undefined" ? 0 : props.useCc;
|
file,
|
||||||
const ccCommercialUse = typeof props.ccCommercialUse === "undefined" ? 0 : props.ccCommercialUse;
|
fileType,
|
||||||
const ccModification = typeof props.ccModification === "undefined" ? 0 : props.ccModification;
|
type,
|
||||||
const downloadLimit = typeof props.downloadLimit === "undefined" ? 0 : props.downloadLimit;
|
rights = '',
|
||||||
|
useCc = 0,
|
||||||
|
ccCommercialUse = 0,
|
||||||
|
ccModification = 0,
|
||||||
|
downloadLimit = 0,
|
||||||
|
} = props;
|
||||||
|
|
||||||
const data = file.find((value) => {
|
const data = file.find((value) => {
|
||||||
return value.file_type_name === ftype;
|
return value.file_type_name === fileType;
|
||||||
});
|
});
|
||||||
if (typeof data === "undefined") {
|
|
||||||
|
if (typeof data === 'undefined') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const date = new Date(data.timestamp);
|
const date = new Date(data.timestamp);
|
||||||
@ -42,7 +50,19 @@ const ItemFile: React.FC<Props> = (props: Props) => {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Type</td>
|
<td>Type</td>
|
||||||
<td>: {data.mime_type}</td>
|
<td>: {data.mime_type}</td>
|
||||||
<td rowSpan={4}>{downloadLimit === 0 && <FileDownloadButton lang={lang} file={data} rights={rights} useCc={useCc} ccCommercialUse={ccCommercialUse} ccModification={ccModification} type={type} />}</td>
|
<td rowSpan={4}>
|
||||||
|
{downloadLimit === 0 && (
|
||||||
|
<FileDownloadButton
|
||||||
|
lang={lang}
|
||||||
|
file={data}
|
||||||
|
rights={rights}
|
||||||
|
useCc={useCc}
|
||||||
|
ccCommercialUse={ccCommercialUse}
|
||||||
|
ccModification={ccModification}
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Size</td>
|
<td>Size</td>
|
||||||
@ -60,7 +80,9 @@ const ItemFile: React.FC<Props> = (props: Props) => {
|
|||||||
</table>
|
</table>
|
||||||
{downloadLimit === 1 && (
|
{downloadLimit === 1 && (
|
||||||
<>
|
<>
|
||||||
<br />({Functions.mlang("[en]File has been removed[/en][ja]ファイルは削除されました[/ja]", lang)})
|
<br />(
|
||||||
|
{Functions.mlang('[en]File has been removed[/en][ja]ファイルは削除されました[/ja]', lang)}
|
||||||
|
)
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../../../../config";
|
import { Link } from 'react-router-dom';
|
||||||
import Functions from "../../../../functions";
|
import { BrainAtlasType, MultiLang } from '../../../../config';
|
||||||
import IndexUtil from "../../../lib/IndexUtil";
|
import Functions from '../../../../functions';
|
||||||
import { ItemBasicIndex } from "../../../lib/ItemUtil";
|
import IndexUtil from '../../../lib/IndexUtil';
|
||||||
|
import { ItemBasicIndex } from '../../../lib/ItemUtil';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -11,13 +12,13 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ItemIndex: React.FC<Props> = (props: Props) => {
|
const ItemIndex: React.FC<Props> = (props) => {
|
||||||
const { lang, index, type } = props;
|
const { lang, index, type } = props;
|
||||||
if (index.length === 0) {
|
if (index.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const elements = index.map((value, idx) => {
|
const elements = index.map((value, idx) => {
|
||||||
const evenodd = idx % 2 === 0 ? "even" : "odd";
|
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
|
||||||
const url = IndexUtil.getUrl(type, value.index_id);
|
const url = IndexUtil.getUrl(type, value.index_id);
|
||||||
return (
|
return (
|
||||||
<tr key={value.index_id}>
|
<tr key={value.index_id}>
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
import { MultiLang } from '../../../../config';
|
||||||
import Functions from "../../../../functions";
|
import Functions from '../../../../functions';
|
||||||
import { ItemBasicLang } from "../../../lib/ItemUtil";
|
import { ItemBasicLang } from '../../../lib/ItemUtil';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
itemLang: ItemBasicLang;
|
itemLang: ItemBasicLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Language: React.FC<Props> = (props: Props) => {
|
const Language: React.FC<Props> = (props) => {
|
||||||
const { lang, itemLang } = props;
|
const { lang, itemLang } = props;
|
||||||
const langStr = {
|
const langStr = {
|
||||||
eng: "[en]English[/en][ja]英語[/ja]",
|
eng: '[en]English[/en][ja]英語[/ja]',
|
||||||
jpn: "[en]Japanese[/en][ja]日本語[/ja]",
|
jpn: '[en]Japanese[/en][ja]日本語[/ja]',
|
||||||
fra: "[en]French[/en][ja]フランス語[/ja]",
|
fra: '[en]French[/en][ja]フランス語[/ja]',
|
||||||
deu: "[en]German[/en][ja]ドイツ語[/ja]",
|
deu: '[en]German[/en][ja]ドイツ語[/ja]',
|
||||||
esl: "[en]Spanish[/en][ja]スペイン語[/ja]",
|
esl: '[en]Spanish[/en][ja]スペイン語[/ja]',
|
||||||
ita: "[en]Italian[/en][ja]イタリア語[/ja]",
|
ita: '[en]Italian[/en][ja]イタリア語[/ja]',
|
||||||
dut: "[en]Dutch[/en][ja]オランダ語[/ja]",
|
dut: '[en]Dutch[/en][ja]オランダ語[/ja]',
|
||||||
sve: "[en]Swedish[/en][ja]スウェーデン語[/ja]",
|
sve: '[en]Swedish[/en][ja]スウェーデン語[/ja]',
|
||||||
nor: "[en]Norwegian[/en][ja]ノルウェー語[/ja]",
|
nor: '[en]Norwegian[/en][ja]ノルウェー語[/ja]',
|
||||||
dan: "[en]Danish[/en][ja]デンマーク語[/ja]",
|
dan: '[en]Danish[/en][ja]デンマーク語[/ja]',
|
||||||
fin: "[en]Finnish[/en][ja]フィンランド語[/ja]",
|
fin: '[en]Finnish[/en][ja]フィンランド語[/ja]',
|
||||||
por: "[en]Portuguese[/en][ja]ポルトガル語[/ja]",
|
por: '[en]Portuguese[/en][ja]ポルトガル語[/ja]',
|
||||||
chi: "[en]Chinese[/en][ja]中国語[/ja]",
|
chi: '[en]Chinese[/en][ja]中国語[/ja]',
|
||||||
kor: "[en]Korean[/en][ja]韓国語[/ja]",
|
kor: '[en]Korean[/en][ja]韓国語[/ja]',
|
||||||
};
|
};
|
||||||
if (!(itemLang in langStr)) {
|
if (!(itemLang in langStr)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import React, { ChangeEvent, MouseEvent } from "react";
|
import React from 'react';
|
||||||
import { Modal } from "react-overlays";
|
|
||||||
import { BrainAtlasType, MultiLang } from "../../../../config";
|
import { Modal } from 'react-overlays';
|
||||||
import Functions from "../../../../functions";
|
import { RenderModalBackdropProps } from 'react-overlays/cjs/Modal';
|
||||||
import ItemUtil, { ItemBasicFile } from "../../../lib/ItemUtil";
|
import { BrainAtlasType, MultiLang } from '../../../../config';
|
||||||
import DateTime from "./DateTime";
|
import Functions from '../../../../functions';
|
||||||
import FileSize from "./FileSize";
|
import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil';
|
||||||
import styles from "./LicenseAgreementDialog.module.css";
|
import DateTime from './DateTime';
|
||||||
import Rights from "./Rights";
|
import FileSize from './FileSize';
|
||||||
|
import styles from './LicenseAgreementDialog.module.css';
|
||||||
|
import Rights from './Rights';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -20,72 +22,67 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const LicenseAgreementDialog: React.FC<Props> = (props) => {
|
||||||
show: boolean;
|
const { lang, file, rights, useCc, ccCommercialUse, ccModification, show, unsetShow, type } =
|
||||||
disabled: boolean;
|
props;
|
||||||
}
|
|
||||||
|
|
||||||
class LicenseAgreementDialog extends React.Component<Props, State> {
|
const [isShow, setIsShow] = React.useState<boolean>(show);
|
||||||
constructor(props: Props) {
|
const [disabled, setDisabled] = React.useState<boolean>(false);
|
||||||
super(props);
|
|
||||||
this.state = {
|
React.useEffect(() => {
|
||||||
show: props.show,
|
if (show) {
|
||||||
disabled: false,
|
setDisabled(true);
|
||||||
|
}
|
||||||
|
}, [show]);
|
||||||
|
|
||||||
|
const handleChangeCheckbox: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
const disabled = e.target.value === '0';
|
||||||
|
setDisabled(disabled);
|
||||||
};
|
};
|
||||||
this.handleChangeCheckbox = this.handleChangeCheckbox.bind(this);
|
|
||||||
this.handleClickDownload = this.handleClickDownload.bind(this);
|
|
||||||
this.handleClickCancel = this.handleClickCancel.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
|
const handleClickDownload: React.MouseEventHandler<HTMLButtonElement> = () => {
|
||||||
if (nextProps.show && !prevState.show) {
|
unsetShow();
|
||||||
return { disabled: true, show: nextProps.show };
|
setIsShow(false);
|
||||||
}
|
};
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChangeCheckbox(e: ChangeEvent<HTMLInputElement>) {
|
const handleClickCancel = () => {
|
||||||
const disabled = e.target.value === "0";
|
unsetShow();
|
||||||
this.setState({ disabled });
|
setIsShow(false);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleClickDownload(e: MouseEvent<HTMLButtonElement>) {
|
const renderBackdrop = (props: RenderModalBackdropProps) => {
|
||||||
this.props.unsetShow();
|
|
||||||
this.setState({ show: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClickCancel() {
|
|
||||||
this.props.unsetShow();
|
|
||||||
this.setState({ show: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBackdrop(props: any) {
|
|
||||||
return <div className={styles.overlay} {...props} />;
|
return <div className={styles.overlay} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
const date = new Date(file.timestamp);
|
||||||
const { lang, type } = this.props;
|
|
||||||
const date = new Date(this.props.file.timestamp);
|
|
||||||
const timestamp = Math.floor(date.valueOf() / 1000);
|
const timestamp = Math.floor(date.valueOf() / 1000);
|
||||||
const url = ItemUtil.getFileUrl(type, this.props.file);
|
const url = ItemUtil.getFileUrl(type, file);
|
||||||
return (
|
return (
|
||||||
<Modal className={styles.dialog} show={this.state.show} onHide={this.handleClickCancel} renderBackdrop={this.renderBackdrop}>
|
<Modal
|
||||||
|
className={styles.dialog}
|
||||||
|
show={isShow}
|
||||||
|
onHide={handleClickCancel}
|
||||||
|
renderBackdrop={renderBackdrop}
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
{Functions.mlang("[en]Download file information[/en][ja]ダウンロードするファイルの情報[/ja]", lang)}
|
{Functions.mlang(
|
||||||
|
'[en]Download file information[/en][ja]ダウンロードするファイルの情報[/ja]',
|
||||||
|
lang,
|
||||||
|
)}
|
||||||
<div className={styles.box}>
|
<div className={styles.box}>
|
||||||
{this.props.file.original_file_name}
|
{file.original_file_name}
|
||||||
<br />
|
<br />
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Type</td>
|
<td>Type</td>
|
||||||
<td>: {this.props.file.mime_type}</td>
|
<td>: {file.mime_type}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Size</td>
|
<td>Size</td>
|
||||||
<td>
|
<td>
|
||||||
: <FileSize lang={lang} size={this.props.file.file_size} />
|
: <FileSize lang={lang} size={file.file_size} />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -100,16 +97,43 @@ class LicenseAgreementDialog extends React.Component<Props, State> {
|
|||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div>
|
<div>
|
||||||
{Functions.mlang("[en]License agreement[/en][ja]ファイルのライセンス[/ja]", lang)}
|
{Functions.mlang('[en]License agreement[/en][ja]ファイルのライセンス[/ja]', lang)}
|
||||||
<div className={styles.box}>
|
<div className={styles.box}>
|
||||||
{Functions.mlang("[en]Please read the following license agreement carefully.[/en][ja]このファイルには下記のライセンスが設定されています。[/ja]", lang)}
|
{Functions.mlang(
|
||||||
|
'[en]Please read the following license agreement carefully.[/en][ja]このファイルには下記のライセンスが設定されています。[/ja]',
|
||||||
|
lang,
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<Rights lang={lang} rights={this.props.rights} useCc={this.props.useCc} ccCommercialUse={this.props.ccCommercialUse} ccModification={this.props.ccModification} />
|
<Rights
|
||||||
<input type="radio" name="radio_license" value="1" onChange={this.handleChangeCheckbox} checked={!this.state.disabled} />
|
lang={lang}
|
||||||
{Functions.mlang("[en]I accept the terms in the license agreement.[/en][ja]ライセンスに同意します。[/ja]", lang)}
|
rights={rights}
|
||||||
|
useCc={useCc}
|
||||||
|
ccCommercialUse={ccCommercialUse}
|
||||||
|
ccModification={ccModification}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio_license"
|
||||||
|
value="1"
|
||||||
|
onChange={handleChangeCheckbox}
|
||||||
|
checked={!disabled}
|
||||||
|
/>
|
||||||
|
{Functions.mlang(
|
||||||
|
'[en]I accept the terms in the license agreement.[/en][ja]ライセンスに同意します。[/ja]',
|
||||||
|
lang,
|
||||||
|
)}
|
||||||
<br />
|
<br />
|
||||||
<input type="radio" name="radio_license" value="0" onChange={this.handleChangeCheckbox} checked={this.state.disabled} />
|
<input
|
||||||
{Functions.mlang("[en]I do not accept the terms in the license agreement.[/en][ja]ライセンスに同意しません。[/ja]", lang)}
|
type="radio"
|
||||||
|
name="radio_license"
|
||||||
|
value="0"
|
||||||
|
onChange={handleChangeCheckbox}
|
||||||
|
checked={disabled}
|
||||||
|
/>
|
||||||
|
{Functions.mlang(
|
||||||
|
'[en]I do not accept the terms in the license agreement.[/en][ja]ライセンスに同意しません。[/ja]',
|
||||||
|
lang,
|
||||||
|
)}
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -118,19 +142,18 @@ class LicenseAgreementDialog extends React.Component<Props, State> {
|
|||||||
<div className={styles.download}>
|
<div className={styles.download}>
|
||||||
Acceptance is needed to download this file.
|
Acceptance is needed to download this file.
|
||||||
<br />
|
<br />
|
||||||
<a href={url} download={this.props.file.original_file_name}>
|
<a href={url} download={file.original_file_name}>
|
||||||
<button className="formButton" onClick={this.handleClickDownload} disabled={this.state.disabled}>
|
<button className="formButton" onClick={handleClickDownload} disabled={disabled}>
|
||||||
Download
|
Download
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<button className="formButton" onClick={this.handleClickCancel}>
|
<button className="formButton" onClick={handleClickCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default LicenseAgreementDialog;
|
export default LicenseAgreementDialog;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.previewBox::after {
|
.previewBox::after {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import Lightbox from "react-image-lightbox";
|
|
||||||
import "react-image-lightbox/style.css";
|
import Lightbox, { SlideImage } from 'yet-another-react-lightbox';
|
||||||
import { BrainAtlasType, MultiLang } from "../../../../config";
|
import { BrainAtlasType, MultiLang } from '../../../../config';
|
||||||
import Functions from "../../../../functions";
|
import Functions from '../../../../functions';
|
||||||
import ItemUtil, { ItemBasicFile } from "../../../lib/ItemUtil";
|
import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil';
|
||||||
import styles from "./Preview.module.css";
|
|
||||||
|
import 'yet-another-react-lightbox/styles.css';
|
||||||
|
import styles from './Preview.module.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -12,34 +14,25 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const Preview: React.FC<Props> = (props) => {
|
||||||
isOpen: boolean;
|
const { lang, file, type } = props;
|
||||||
imageIndex: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Preview extends React.Component<Props, State> {
|
const [isOpen, setIsOpen] = React.useState<boolean>(false);
|
||||||
constructor(props: Props) {
|
const [imageIndex, setImageIndex] = React.useState<number>(0);
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
isOpen: false,
|
|
||||||
imageIndex: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { lang, file, type } = this.props;
|
|
||||||
const data = file.filter((value) => {
|
const data = file.filter((value) => {
|
||||||
return value.file_type_name === "preview";
|
return value.file_type_name === 'preview';
|
||||||
});
|
});
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let imageUrls: string[] = [];
|
const slides: SlideImage[] = [];
|
||||||
|
|
||||||
const previews = data.map((value, idx) => {
|
const previews = data.map((value, idx) => {
|
||||||
const fileUrl = ItemUtil.getFileUrl(type, value);
|
const fileUrl = ItemUtil.getFileUrl(type, value);
|
||||||
const previewUrl = ItemUtil.getPreviewFileUrl(type, value);
|
const previewUrl = ItemUtil.getPreviewFileUrl(type, value);
|
||||||
const caption = Functions.mlang(value.caption, lang);
|
const caption = Functions.mlang(value.caption, lang);
|
||||||
imageUrls.push(fileUrl);
|
slides.push({ src: fileUrl });
|
||||||
return (
|
return (
|
||||||
<figure key={value.file_id} className={styles.preview}>
|
<figure key={value.file_id} className={styles.preview}>
|
||||||
<a
|
<a
|
||||||
@ -47,7 +40,8 @@ class Preview extends React.Component<Props, State> {
|
|||||||
download={value.original_file_name}
|
download={value.original_file_name}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState({ isOpen: true, imageIndex: idx });
|
setIsOpen(true);
|
||||||
|
setImageIndex(idx);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img src={previewUrl} alt={caption} />
|
<img src={previewUrl} alt={caption} />
|
||||||
@ -56,31 +50,13 @@ class Preview extends React.Component<Props, State> {
|
|||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const { isOpen, imageIndex } = this.state;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.previewBox}>{previews}</div>
|
<div className={styles.previewBox}>{previews}</div>
|
||||||
{isOpen && (
|
{isOpen && <Lightbox index={imageIndex} slides={slides} close={() => setIsOpen(false)} />}
|
||||||
<Lightbox
|
|
||||||
mainSrc={imageUrls[imageIndex]}
|
|
||||||
nextSrc={imageUrls[(imageIndex + 1) % data.length]}
|
|
||||||
prevSrc={imageUrls[(imageIndex + data.length - 1) % data.length]}
|
|
||||||
onCloseRequest={() => 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;
|
export default Preview;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
import DateTime from "./DateTime";
|
import { MultiLang } from '../../../../config';
|
||||||
|
import DateTime from './DateTime';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -9,9 +10,9 @@ interface Props {
|
|||||||
mday: number;
|
mday: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PublicationDate: React.FC<Props> = (props: Props) => {
|
const PublicationDate: React.FC<Props> = (props) => {
|
||||||
const { lang, year, month, mday } = props;
|
const { lang, year, month, mday } = props;
|
||||||
const d = new Date(year + "-" + month + "-" + mday);
|
const d = new Date(year + '-' + month + '-' + mday);
|
||||||
const timestamp = Math.floor(d.valueOf() / 1000);
|
const timestamp = Math.floor(d.valueOf() / 1000);
|
||||||
return <DateTime lang={lang} date={timestamp} onlyDate={true} />;
|
return <DateTime lang={lang} date={timestamp} onlyDate={true} />;
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
import Description from "./Description";
|
import { MultiLang } from '../../../../config';
|
||||||
|
import Description from './Description';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
readme: string;
|
readme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Readme: React.FC<Props> = (props: Props) => {
|
const Readme: React.FC<Props> = (props) => {
|
||||||
const { lang, readme } = props;
|
const { lang, readme } = props;
|
||||||
return <Description lang={lang} description={readme} className="readme" />;
|
return <Description lang={lang} description={readme} className="readme" />;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { BrainAtlasType, MultiLang } from "../../../../config";
|
|
||||||
import ItemType from "../../../item-type";
|
import { BrainAtlasType, MultiLang } from '../../../../config';
|
||||||
import ItemUtil from "../../../lib/ItemUtil";
|
import ItemType from '../../../item-type';
|
||||||
|
import ItemUtil from '../../../lib/ItemUtil';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -9,44 +10,26 @@ interface Props {
|
|||||||
type: BrainAtlasType;
|
type: BrainAtlasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const RelatedTo: React.FC<Props> = (props) => {
|
||||||
elements: JSX.Element[];
|
const { lang, relatedTo, type } = props;
|
||||||
}
|
const isMounted = React.useRef<boolean>(false);
|
||||||
|
|
||||||
class RelatedTo extends React.Component<Props, State> {
|
const [elements, setElements] = React.useState<React.ReactNode[]>([]);
|
||||||
private isActive: boolean;
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
React.useEffect(() => {
|
||||||
super(props);
|
isMounted.current = true;
|
||||||
this.state = {
|
return () => {
|
||||||
elements: [],
|
isMounted.current = false;
|
||||||
};
|
};
|
||||||
this.isActive = false;
|
}, []);
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
React.useEffect(() => {
|
||||||
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, type } = this.props;
|
|
||||||
if (relatedTo.length === 0) {
|
if (relatedTo.length === 0) {
|
||||||
this.setState({ elements: [] });
|
setElements([]);
|
||||||
} else {
|
} else {
|
||||||
ItemUtil.getList(type, relatedTo, (results) => {
|
ItemUtil.getList(type, relatedTo, (results) => {
|
||||||
const elements = results.data.map((item, idx) => {
|
const elements = results.data.map((item, idx) => {
|
||||||
const evenodd = idx % 0 ? "even" : "odd";
|
const evenodd = idx % 0 ? 'even' : 'odd';
|
||||||
return (
|
return (
|
||||||
<tr key={item.item_id}>
|
<tr key={item.item_id}>
|
||||||
<td className={evenodd}>
|
<td className={evenodd}>
|
||||||
@ -55,15 +38,14 @@ class RelatedTo extends React.Component<Props, State> {
|
|||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (this.isActive) {
|
if (isMounted.current) {
|
||||||
this.setState({ elements });
|
setElements(elements);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}, [lang, relatedTo, type]);
|
||||||
|
|
||||||
render() {
|
if (elements.length === 0) {
|
||||||
if (this.state.elements.length === 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@ -72,11 +54,10 @@ class RelatedTo extends React.Component<Props, State> {
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Item summary</th>
|
<th>Item summary</th>
|
||||||
</tr>
|
</tr>
|
||||||
{this.state.elements}
|
{elements}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default RelatedTo;
|
export default RelatedTo;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
|
||||||
import CreativeCommons, { getCreativeCommonsType } from "./CreativeCommons";
|
import { MultiLang } from '../../../../config';
|
||||||
import Description from "./Description";
|
import CreativeCommons from './CreativeCommons';
|
||||||
|
import Description from './Description';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -11,13 +12,18 @@ interface Props {
|
|||||||
ccModification: number;
|
ccModification: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Rights: React.FC<Props> = (props: Props) => {
|
const Rights: React.FC<Props> = (props) => {
|
||||||
const { lang, rights, useCc, ccCommercialUse, ccModification } = props;
|
const { lang, rights, useCc, ccCommercialUse, ccModification } = props;
|
||||||
if (useCc === 0) {
|
if (useCc === 0) {
|
||||||
return <Description lang={lang} description={rights} className="rights" />;
|
return <Description lang={lang} description={rights} className="rights" />;
|
||||||
}
|
}
|
||||||
const ccType = getCreativeCommonsType(ccCommercialUse, ccModification);
|
return (
|
||||||
return <CreativeCommons lang={lang} type={ccType} />;
|
<CreativeCommons
|
||||||
|
lang={lang}
|
||||||
|
ccCommercialUse={ccCommercialUse}
|
||||||
|
ccModification={ccModification}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Rights;
|
export default Rights;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { MultiLang } from "../../../../config";
|
import { MultiLang } from '../../../../config';
|
||||||
import imageButton from "../../../assets/images/simpf_button.png";
|
import imageButton from '../../../assets/images/simpf_button.png';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
lang: MultiLang;
|
lang: MultiLang;
|
||||||
@ -8,11 +8,11 @@ interface Props {
|
|||||||
isDetail: boolean;
|
isDetail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SimPFLinkIcon: React.FC<Props> = (props: Props) => {
|
const SimPFLinkIcon: React.FC<Props> = (props) => {
|
||||||
const { url, isDetail } = props;
|
const { url, isDetail } = props;
|
||||||
const title = "Online Simulation";
|
const title = 'Online Simulation';
|
||||||
const size = isDetail ? 64 : 35;
|
const size = isDetail ? 64 : 35;
|
||||||
if (url === "") {
|
if (url === '') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import Author from "./Author";
|
import Author from './Author';
|
||||||
import ChangeLog from "./ChangeLog";
|
import ChangeLog from './ChangeLog';
|
||||||
import Contributer from "./Contributer";
|
import Contributor from './Contributor';
|
||||||
import CreativeCommons from "./CreativeCommons";
|
import CreativeCommons from './CreativeCommons';
|
||||||
import DateTime from "./DateTime";
|
import DateTime from './DateTime';
|
||||||
import Description from "./Description";
|
import Description from './Description';
|
||||||
import FileDownloadButton from "./FileDownloadButton";
|
import FileDownloadButton from './FileDownloadButton';
|
||||||
import FileSize from "./FileSize";
|
import FileSize from './FileSize';
|
||||||
import FreeKeyword from "./FreeKeyword";
|
import FreeKeyword from './FreeKeyword';
|
||||||
import ItemFile from "./ItemFile";
|
import ItemFile from './ItemFile';
|
||||||
import ItemIndex from "./ItemIndex";
|
import ItemIndex from './ItemIndex';
|
||||||
import Language from "./Language";
|
import Language from './Language';
|
||||||
import Preview from "./Preview";
|
import Preview from './Preview';
|
||||||
import PublicationDate from "./PublicationDate";
|
import PublicationDate from './PublicationDate';
|
||||||
import Readme from "./Readme";
|
import Readme from './Readme';
|
||||||
import RelatedTo from "./RelatedTo";
|
import RelatedTo from './RelatedTo';
|
||||||
import Rights from "./Rights";
|
import Rights from './Rights';
|
||||||
|
|
||||||
const ItemTypeField = {
|
const ItemTypeField = {
|
||||||
Author,
|
Author,
|
||||||
ChangeLog,
|
ChangeLog,
|
||||||
Contributer,
|
Contributor,
|
||||||
CreativeCommons,
|
CreativeCommons,
|
||||||
DateTime,
|
DateTime,
|
||||||
Description,
|
Description,
|
||||||
|
@ -1,24 +1,33 @@
|
|||||||
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
|
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
|
||||||
|
|
||||||
class MemoAdvancedSearch extends AdvancedSearchBase {
|
class MemoAdvancedSearch extends AdvancedSearchBase {
|
||||||
constructor(props: AdvancedSearchBaseProps) {
|
constructor(props: AdvancedSearchBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "memo";
|
this.type = 'memo';
|
||||||
this.title = "Memo";
|
this.title = 'Memo';
|
||||||
this.state.values["title"] = "";
|
this.state.values.title = '';
|
||||||
this.state.values["keyword"] = "";
|
this.state.values.keyword = '';
|
||||||
this.state.values["description"] = "";
|
this.state.values.description = '';
|
||||||
this.state.values["doi"] = "";
|
this.state.values.doi = '';
|
||||||
this.state.values["item_link"] = "";
|
this.state.values.item_link = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows() {
|
getRows() {
|
||||||
const rows = [
|
const rows = [
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 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: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
|
value: this.renderFieldInputText('keyword', 50),
|
||||||
{ label: "[en]Item Link[/en][ja]リンク[/ja]", value: this.renderFieldInputText("item_link", 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;
|
return rows;
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,63 @@
|
|||||||
import React from "react";
|
import XoopsCode from '../../../common/lib/XoopsCode';
|
||||||
import XoopsCode from "../../../common/lib/XoopsCode";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import { ItemMemo } from '../../lib/ItemUtil';
|
||||||
import { ItemMemo } from "../../lib/ItemUtil";
|
import DetailBase from '../lib/DetailBase';
|
||||||
import DetailBase from "../lib/DetailBase";
|
import ItemTypeField from '../lib/field';
|
||||||
import ItemTypeField from "../lib/field";
|
|
||||||
|
|
||||||
class MemoDetail extends DetailBase {
|
class MemoDetail extends DetailBase {
|
||||||
getFields() {
|
getFields() {
|
||||||
const { lang, type } = this.props;
|
const { lang, type } = this.props;
|
||||||
const item = this.props.item as ItemMemo;
|
const item = this.props.item as ItemMemo;
|
||||||
const fields = [
|
const fields = [
|
||||||
{ label: "ID", value: item.doi },
|
{ label: 'ID', value: item.doi },
|
||||||
{ label: "[en]Language[/en][ja]言語[/ja]", value: <ItemTypeField.Language lang={lang} itemLang={item.lang} /> },
|
{
|
||||||
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: Functions.mlang(item.title, lang) },
|
label: '[en]Language[/en][ja]言語[/ja]',
|
||||||
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} /> },
|
value: <ItemTypeField.Language lang={lang} itemLang={item.lang} />,
|
||||||
{ label: "[en]Description[/en][ja]概要[/ja]", value: <ItemTypeField.Description lang={lang} description={item.description} /> },
|
},
|
||||||
{ label: "[en]Last Modified Date[/en][ja]最終更新日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} /> },
|
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) },
|
||||||
{ label: "[en]Created Date[/en][ja]作成日[/ja]", value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} /> },
|
{
|
||||||
{ label: "[en]Contributor[/en][ja]登録者[/ja]", value: <ItemTypeField.Contributer lang={lang} uname={item.uname} name={item.name} /> },
|
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
|
||||||
{ label: "[en]Item Type[/en][ja]アイテムタイプ[/ja]", value: item.item_type_display_name },
|
value: <ItemTypeField.FreeKeyword lang={lang} keyword={item.keyword} />,
|
||||||
{ label: "[en]Change Log(History)[/en][ja]変更履歴[/ja]", value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} /> },
|
},
|
||||||
{ label: "[en]Item Link[/en][ja]リンク[/ja]", value: <XoopsCode lang={lang} text={item.item_link} /> },
|
{
|
||||||
{ label: "[en]Memo File[/en][ja]メモファイル[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="memo_file" type={type} /> },
|
label: '[en]Description[/en][ja]概要[/ja]',
|
||||||
{ label: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
|
value: <ItemTypeField.Description lang={lang} description={item.description} />,
|
||||||
{ label: "[en]Related to[/en][ja]関連アイテム[/ja]", value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} /> },
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Last Modified Date[/en][ja]最終更新日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.last_update_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Created Date[/en][ja]作成日[/ja]',
|
||||||
|
value: <ItemTypeField.DateTime lang={lang} date={item.creation_date} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Contributor[/en][ja]登録者[/ja]',
|
||||||
|
value: <ItemTypeField.Contributor lang={lang} uname={item.uname} name={item.name} />,
|
||||||
|
},
|
||||||
|
{ label: '[en]Item Type[/en][ja]アイテムタイプ[/ja]', value: item.item_type_display_name },
|
||||||
|
{
|
||||||
|
label: '[en]Change Log(History)[/en][ja]変更履歴[/ja]',
|
||||||
|
value: <ItemTypeField.ChangeLog lang={lang} changelog={item.changelog} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Item Link[/en][ja]リンク[/ja]',
|
||||||
|
value: <XoopsCode lang={lang} text={item.item_link} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Memo File[/en][ja]メモファイル[/ja]',
|
||||||
|
value: (
|
||||||
|
<ItemTypeField.ItemFile lang={lang} file={item.file} fileType="memo_file" type={type} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Index',
|
||||||
|
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '[en]Related to[/en][ja]関連アイテム[/ja]',
|
||||||
|
value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
import React from "react";
|
import { Link } from 'react-router-dom';
|
||||||
import { Link } from "react-router-dom";
|
import XoopsCode from '../../../common/lib/XoopsCode';
|
||||||
import XoopsCode from "../../../common/lib/XoopsCode";
|
import Functions from '../../../functions';
|
||||||
import Functions from "../../../functions";
|
import iconFile from '../../assets/images/icon_memo.gif';
|
||||||
import iconFile from "../../assets/images/icon_memo.gif";
|
import { ItemMemo } from '../../lib/ItemUtil';
|
||||||
import { ItemMemo } from "../../lib/ItemUtil";
|
import ListBase, { ListBaseProps } from '../lib/ListBase';
|
||||||
import ListBase, { ListBaseProps } from "../lib/ListBase";
|
|
||||||
|
|
||||||
class MemoList extends ListBase {
|
class MemoList extends ListBase {
|
||||||
constructor(props: ListBaseProps) {
|
constructor(props: ListBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.label = "Memo";
|
this.label = 'Memo';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBody() {
|
renderBody() {
|
||||||
const { lang } = this.props;
|
const { lang } = this.props;
|
||||||
const item = this.props.item as ItemMemo;
|
const item = this.props.item as ItemMemo;
|
||||||
const link = item.item_link !== "" ? <XoopsCode lang={lang} text={item.item_link} /> : null;
|
const link = item.item_link !== '' ? <XoopsCode lang={lang} text={item.item_link} /> : null;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
|
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import iconFile from "../../assets/images/icon_memo.gif";
|
import iconFile from '../../assets/images/icon_memo.gif';
|
||||||
import TopBase, { TopBaseProps } from "../lib/TopBase";
|
import TopBase, { TopBaseProps } from '../lib/TopBase';
|
||||||
|
|
||||||
class MemoTop extends TopBase {
|
class MemoTop extends TopBase {
|
||||||
constructor(props: TopBaseProps) {
|
constructor(props: TopBaseProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.type = "memo";
|
this.type = 'memo';
|
||||||
this.label = "Memo";
|
this.label = 'Memo';
|
||||||
this.icon = iconFile;
|
this.icon = iconFile;
|
||||||
this.description = "[en]Personal Memo Pad.[/en][ja]汎用メモパッド[/ja]";
|
this.description = '[en]Personal Memo Pad.[/en][ja]汎用メモパッド[/ja]';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user