revised and updated sources.

This commit is contained in:
Yoshihiro OKUMURA 2023-07-28 22:05:26 +09:00
parent 040eee8240
commit 8f37b9c537
Signed by: orrisroot
GPG Key ID: 470AA444C92904B2
163 changed files with 10291 additions and 12457 deletions

29
.eslintrc.cjs Normal file
View 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
View File

@ -22,3 +22,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# customize
/public/data

8
.prettierrc.json Normal file
View 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
View 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
View 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
View 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
View 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
}
}
]
}

View File

@ -1,8 +1,8 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<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="theme-color" content="#000000" />
<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."
/>
<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 name="author" content="BSI-NI and Laboratory for Symbolic Cognitive Development, RIKEN Brain Science Institute" />
<meta
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 &copy; 2017" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="manifest" href="/manifest.json" />
<title>BSI-NI Brain Atlas</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

5515
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,65 +1,58 @@
{
"name": "brainatlas",
"version": "1.0.0",
"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": {
"@orrisroot/react-html-parser": "^2.1.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.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",
"@orrisroot/react-html-parser": "^2.1.1",
"async-lock": "^1.4.0",
"axios": "^1.4.0",
"lokijs": "^1.5.12",
"moment": "^2.29.3",
"rc-tree": "^5.6.5",
"react": "^18.1.0",
"moment": "^2.29.4",
"node-stdlib-browser": "^1.2.0",
"rc-tree": "^5.7.9",
"react": "^18.2.0",
"react-app-polyfill": "^3.0.0",
"react-cookie": "^4.1.1",
"react-dom": "^18.1.0",
"react-ga4": "^1.4.1",
"react-dom": "^18.2.0",
"react-ga4": "^2.1.0",
"react-helmet-async": "^1.3.0",
"react-image-lightbox": "^5.1.4",
"react-overlays": "^5.2.0",
"react-router-dom": "^6.3.0",
"react-overlays": "^5.2.1",
"react-router-dom": "^6.14.2",
"react-router-hash-link": "^2.4.3",
"react-scripts": "^5.0.1",
"react-spinner-material": "^1.4.0",
"typescript": "^4.7.3",
"web-vitals": "^2.1.4",
"xregexp": "^5.1.1"
"sanitize.css": "^13.0.0",
"xregexp": "^5.1.1",
"yet-another-react-lightbox": "^3.11.4"
},
"resolutions": {
"@svgr/webpack": "^6.2.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all",
"ie 11"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version",
"ie 11"
]
"devDependencies": {
"@types/async-lock": "^1.4.0",
"@types/jest": "^29.5.3",
"@types/lokijs": "^1.5.8",
"@types/node": "^18.17.1",
"@types/react": "^18.2.17",
"@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3",
"@types/react-router-hash-link": "^2.4.6",
"@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^6.2.0",
"@typescript-eslint/parser": "^6.2.0",
"@vitejs/plugin-react-swc": "^3.3.2",
"eslint": "^8.45.0",
"eslint-plugin-react": "^7.33.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"prettier": "^3.0.0",
"typescript": "^5.1.6",
"vite": "^4.4.7",
"vite-plugin-node-stdlib-browser": "^0.2.1",
"vite-plugin-rewrite-all": "^1.0.1"
}
}

View File

@ -1,17 +1,22 @@
RewriteEngine on
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
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]+)($|&)
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]+)($|&)
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} !-d [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}index.html !-f
RewriteRule . /index.html [L]
</IfModule>

View File

@ -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();
});

View File

@ -1,26 +1,32 @@
import React, { useEffect, useState } from "react";
import { CookiesProvider, useCookies } from "react-cookie";
import ReactGA from "react-ga4";
import { HelmetProvider } from "react-helmet-async";
import { BrowserRouter, useLocation } from "react-router-dom";
import "./App.css";
import AppRoot from "./common/AppRoot";
import Config, { MultiLang } from "./config";
import React from 'react';
import { CookiesProvider, useCookies } from 'react-cookie';
import ReactGA from 'react-ga4';
import { HelmetProvider } from 'react-helmet-async';
import { BrowserRouter, useLocation } from 'react-router-dom';
import './App.css';
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 [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();
useEffect(() => {
if (Config.GOOGLE_ANALYTICS_TRACKING_ID !== "") {
ReactGA.send("pageview");
}
React.useEffect(() => {
const params = new URLSearchParams(location.search);
const ml_lang = params.get("ml_lang");
if (ml_lang != null && ["en", "ja"].includes(ml_lang)) {
const ml_lang = params.get('ml_lang');
if (ml_lang != null && ['en', 'ja'].includes(ml_lang)) {
if (cookies.ml_lang !== ml_lang) {
setCookie("ml_lang", ml_lang);
setCookie('ml_lang', ml_lang);
}
if (lang !== ml_lang) {
setLang(ml_lang as MultiLang);
@ -33,7 +39,7 @@ const AppMain: 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);
}

View File

@ -1,13 +1,14 @@
import React from "react";
import { Helmet } from "react-helmet-async";
import { Route, Routes, useLocation } from "react-router-dom";
import { BrainAtlasType, MultiLang } from "../config";
import SiteIndex from "../custom/SiteIndex";
import Functions from "../functions";
import Footer from "./Footer";
import Header from "./Header";
import PageNotFound from "./lib/PageNotFound";
import MainContent from "./MainContent";
import React from 'react';
import { Helmet } from 'react-helmet-async';
import { Route, Routes, useLocation } from 'react-router-dom';
import { BrainAtlasType, MultiLang } from '../config';
import SiteIndex from '../custom/SiteIndex';
import Functions from '../functions';
import Footer from './Footer';
import Header from './Header';
import MainContent from './MainContent';
import PageNotFound from './lib/PageNotFound';
interface Props {
lang: MultiLang;
@ -19,7 +20,7 @@ interface PropsMain extends Props {
isLink: boolean;
}
const PageMain: React.FC<PropsMain> = (props: PropsMain) => {
const PageMain: React.FC<PropsMain> = (props) => {
const { lang, type, isHtml, isLink } = props;
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 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 isLink = match !== null ? typeof match[3] !== 'undefined' : false;
@ -48,12 +51,30 @@ const AppRoot: React.FC<Props> = (props: Props) => {
</Helmet>
<Routes>
<Route index element={<SiteIndex lang={lang} />} />
<Route path="degu_html/*" element={<PageMain lang={lang} type="degu" isHtml={isHtml} isLink={isLink} />} />
<Route 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="degu_html/*"
element={<PageMain lang={lang} type="degu" isHtml={isHtml} isLink={isLink} />}
/>
<Route
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} />} />
</Routes>
</div>

View File

@ -1,6 +1,7 @@
import React from "react";
import { Link } from "react-router-dom";
import { BrainAtlasType, MultiLang } from "../config";
import React from 'react';
import { Link } from 'react-router-dom';
import { BrainAtlasType, MultiLang } from '../config';
interface Props {
lang: MultiLang;
@ -8,25 +9,40 @@ interface Props {
isLink: boolean;
}
const Footer: React.FC<Props> = (props: Props) => {
const Footer: React.FC<Props> = (props) => {
const { type, isLink } = props;
return (
<footer>
<div className="links clearfix">
<span className={`image ${type}`}>&nbsp;</span>
{!isLink && (
<Link className="relatedLink" to={"/" + type + "_html/link.html"}>
<Link className="relatedLink" to={'/' + type + '_html/link.html'}>
<span>Related Link</span>
</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>
</a>
<span className="gotoTop">
<Link to="/">&raquo; GO TO TOP</Link>
</span>
</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 &amp; 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 &amp; Laboratory for Symbolic Cognitive Development,
RIKEN Brain Science Insititute.
</div>
)}
</footer>
);
};

View File

@ -1,58 +1,59 @@
import React from "react";
import { Helmet } from "react-helmet-async";
import { Link, useLocation } from "react-router-dom";
import Config, { BrainAtlasType, MultiLang } from "../config";
import React from 'react';
import { Helmet } from 'react-helmet-async';
import { Link, useLocation } from 'react-router-dom';
import Config, { BrainAtlasType, MultiLang } from '../config';
interface Props {
lang: MultiLang;
type: BrainAtlasType;
}
type HeaderType = BrainAtlasType | "marmoset_3d" | "marmoset_std";
type HeaderType = BrainAtlasType | 'marmoset_3d' | 'marmoset_std';
const titles = {
degu: "Degu - 3D Brain Atlas",
jm: "Japanese Macaque Monkey - the MRI Standard Brain",
marmoset: "Marmoset",
marmoset_3d: "Marmoset - 3D Brain Atlas",
marmoset_std: "Marmoset - the MRI Standard Brain",
degu: 'Degu - 3D Brain Atlas',
jm: 'Japanese Macaque Monkey - the MRI Standard Brain',
marmoset: 'Marmoset',
marmoset_3d: 'Marmoset - 3D Brain Atlas',
marmoset_std: 'Marmoset - the MRI Standard Brain',
};
const urls = {
degu: "/degu/modules/xoonips/listitem.php?index_id=24",
jm: "/jm/modules/xoonips/listitem.php?index_id=9",
marmoset: "/marmoset_html/",
marmoset_3d: "/marmoset/modules/xoonips/listitem.php?index_id=66",
marmoset_std: "/marmoset/modules/xoonips/listitem.php?index_id=71",
degu: '/degu/modules/xoonips/listitem.php?index_id=24',
jm: '/jm/modules/xoonips/listitem.php?index_id=9',
marmoset: '/marmoset_html/',
marmoset_3d: '/marmoset/modules/xoonips/listitem.php?index_id=66',
marmoset_std: '/marmoset/modules/xoonips/listitem.php?index_id=71',
};
const getHeaderType = (type: BrainAtlasType, pathname: string, search: string): HeaderType => {
if (type === "marmoset") {
if (type === 'marmoset') {
const params = new URLSearchParams(search);
switch (pathname) {
case "/marmoset/modules/xoonips/listitem.php": {
const index_id = params.get("index_id") || "3";
if (["66", "69"].includes(index_id)) {
return "marmoset_3d";
case '/marmoset/modules/xoonips/listitem.php': {
const index_id = params.get('index_id') ?? '3';
if (['66', '69'].includes(index_id)) {
return 'marmoset_3d';
}
if (["71", "73"].includes(index_id)) {
return "marmoset_std";
if (['71', '73'].includes(index_id)) {
return 'marmoset_std';
}
break;
}
case "/marmoset/modules/xoonips/detail.php": {
const item_id = params.get("item_id") || "";
if (["77", "75", "79", "80"].includes(item_id)) {
return "marmoset_3d";
case '/marmoset/modules/xoonips/detail.php': {
const item_id = params.get('item_id') ?? '';
if (['77', '75', '79', '80'].includes(item_id)) {
return 'marmoset_3d';
}
if (["72"].includes(item_id)) {
return "marmoset_std";
if (['72'].includes(item_id)) {
return 'marmoset_std';
}
const id = params.get("id") || "";
if (["Marmoset02", "Marmoset04", "Marmoset05", "Marmoset06"].includes(id)) {
return "marmoset_3d";
const id = params.get('id') ?? '';
if (['Marmoset02', 'Marmoset04', 'Marmoset05', 'Marmoset06'].includes(id)) {
return 'marmoset_3d';
}
if (["004"].includes(id)) {
return "marmoset_std";
if (['004'].includes(id)) {
return 'marmoset_std';
}
break;
}
@ -61,19 +62,19 @@ const getHeaderType = (type: BrainAtlasType, pathname: string, search: string):
return type;
};
const Header: React.FC<Props> = (props: Props) => {
const Header: React.FC<Props> = (props) => {
const { lang, type } = props;
const location = useLocation();
const { pathname, search } = location;
const params = new URLSearchParams(search);
params.set("ml_lang", lang === "en" ? "ja" : "en");
const langUrl = location.pathname + "?" + params.toString();
const langLabel = lang === "en" ? "To Japanese" : "To English";
const xtype = getHeaderType(type, pathname, search);
const title = Config.SITE_TITLE + " " + titles[xtype];
const url = urls[xtype];
params.set('ml_lang', lang === 'en' ? 'ja' : 'en');
const langUrl = `${location.pathname}?${params.toString()}`;
const langLabel = lang === 'en' ? 'To Japanese' : 'To English';
const hType = getHeaderType(type, pathname, search);
const title = Config.SITE_TITLE + ' ' + titles[hType];
const url = urls[hType];
return (
<header className={xtype}>
<header className={hType}>
<Helmet>
<title>{title}</title>
</Helmet>

View File

@ -1,11 +1,12 @@
import React from "react";
import { Route, Routes } from "react-router-dom";
import { BrainAtlasType, MultiLang } from "../config";
import CoverPage from "../custom/CoverPage";
import RelatedLink from "../custom/RelatedLink";
import Database from "../database/Database";
import DatabaseTop from "../database/DatabaseTop";
import XoopsPathRedirect from "./XoopsPathRedirect";
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import { BrainAtlasType, MultiLang } from '../config';
import CoverPage from '../custom/CoverPage';
import RelatedLink from '../custom/RelatedLink';
import Database from '../database/Database';
import DatabaseTop from '../database/DatabaseTop';
import XoopsPathRedirect from './XoopsPathRedirect';
interface Props {
lang: MultiLang;
@ -14,7 +15,7 @@ interface Props {
isLink: boolean;
}
const MainContent: React.FC<Props> = (props: Props) => {
const MainContent: React.FC<Props> = (props) => {
const { lang, type, isHtml, isLink } = props;
return (
<div className="mainContent">

View File

@ -1,26 +1,27 @@
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
import { MultiLang } from "../config";
import PageNotFound from "./lib/PageNotFound";
import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { MultiLang } from '../config';
import PageNotFound from './lib/PageNotFound';
interface Props {
lang: MultiLang;
}
const XoopsPathRedirect: React.FC<Props> = (props: Props) => {
const XoopsPathRedirect: React.FC<Props> = (props) => {
const { lang } = props;
const location = useLocation();
const { pathname } = location;
const getRedirectUrl = () => {
switch (pathname || "") {
case "/index.php": {
return "/";
switch (pathname || '') {
case '/index.php': {
return '/';
}
}
return "";
return '';
};
const url = getRedirectUrl();
if (url === "") {
if (url === '') {
return <PageNotFound lang={lang} />;
}
return <Navigate to={url} />;

View File

@ -141,7 +141,7 @@ tr.even:hover {
}
.clearfix::after {
content: "";
content: '';
display: block;
clear: both;
}

View File

@ -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);}
.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);}
.pagneutral {
font-size: 10px;
width: 16px;
height: 19px;
text-align: center;
background-image: url(./images/pagneutral.gif);
}
.pagact {
font-size: 10px;
width: 16px;
height: 19px;
text-align: center;
background-image: url(./images/pagact.gif);
}
.paginact {
font-size: 10px;
width: 16px;
height: 19px;
text-align: center;
background-image: url(./images/paginact.gif);
}
#mainmenu a {
text-align: left;
display: block;
margin: 0;
padding: 4px;
}
#mainmenu a.menuTop {
padding-left: 3px;
}
#mainmenu a.menuMain {
padding-left: 3px;
}
#mainmenu a.menuSub {
padding-left: 9px;
}
#mainmenu a {text-align:left; display: block; margin: 0; padding: 4px;}
#mainmenu a.menuTop {padding-left: 3px;}
#mainmenu a.menuMain {padding-left: 3px;}
#mainmenu a.menuSub {padding-left: 9px;}
#usermenu a {text-align:left; display: block; margin: 0; padding: 4px;}
#usermenu a.menuTop {}
#usermenu a.highlight {color: #0000ff; background-color: #fcc;}
#usermenu a {
text-align: left;
display: block;
margin: 0;
padding: 4px;
}
#usermenu a.menuTop {
}
#usermenu a.highlight {
color: #0000ff;
background-color: #fcc;
}

View File

@ -1,5 +1,6 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import React from 'react';
import { Link } from 'react-router-dom';
interface Props {
url: string;
@ -8,50 +9,40 @@ interface Props {
imageHover?: string;
}
interface State {
image: string;
}
const LinkImage: React.FC<Props> = (props) => {
const { url, title, image: imageNormal, imageHover } = props;
const [image, setImage] = React.useState<string>(imageNormal);
class LinkImage extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
image: props.image,
const handleMouseOver = () => {
if (imageHover != null) {
setImage(imageHover);
}
};
this.handleMouseOver = this.handleMouseOver.bind(this);
this.handleMouseOut = this.handleMouseOut.bind(this);
}
handleMouseOver() {
const { imageHover } = this.props;
if (typeof imageHover !== "undefined") {
this.setState({ image: imageHover });
}
const handleMouseOut = () => {
if (imageHover != null) {
setImage(imageNormal);
}
};
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) {
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}
</a>
);
}
return (
<Link to={url} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
{image}
<Link to={url} onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>
<img style={{ verticalAlign: 'middle' }} src={image} alt={title} title={title} />
</Link>
);
}
}
};
export default LinkImage;

View File

@ -1,10 +1,18 @@
import React from "react";
import Spinner from "react-spinner-material";
import React from 'react';
import Spinner from 'react-spinner-material';
const Loading: React.FC = () => {
return (
<div style={{ display: "flex", justifyContent: "center", alignContent: "center", margin: "100px 0" }}>
<Spinner radius={60} color={"#cccccc"} stroke={8} visible={true} />
<div
style={{
display: 'flex',
justifyContent: 'center',
alignContent: 'center',
margin: '100px 0',
}}
>
<Spinner radius={60} color={'#cccccc'} stroke={8} visible={true} />
</div>
);
};

View File

@ -1,15 +1,17 @@
import React from "react";
import { MultiLang } from "../../config";
import Functions from "../../functions";
import React from 'react';
import { MultiLang } from '../../config';
import Functions from '../../functions';
interface Props {
lang: MultiLang;
}
const NoticeSiteHasBeenArchived: React.FC<Props> = (props: Props) => {
const NoticeSiteHasBeenArchived: React.FC<Props> = (props) => {
const { lang } = props;
const notice = "[en]This site has been archived since FY2019 and is no longer updated.[/en][ja]このサイトは、2019年度よりアーカイブサイトとして運用されています。[/ja]";
return <p style={{ color: "red" }}>{Functions.mlang(notice, lang)}</p>;
const notice =
'[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;

View File

@ -1,8 +1,8 @@
import React, { useEffect } from "react";
import { Helmet } from "react-helmet-async";
import { useLocation, useNavigate } from "react-router-dom";
import { MultiLang } from "../../config";
import Functions from "../../functions";
import React from 'react';
import { Helmet } from 'react-helmet-async';
import { MultiLang } from '../../config';
import Functions from '../../functions';
interface Props {
lang: MultiLang;
@ -10,26 +10,7 @@ interface Props {
const PageNotFound: React.FC<Props> = (props) => {
const { lang } = props;
const location = useLocation();
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]);
const url = '/';
return (
<div>
@ -38,7 +19,7 @@ const PageNotFound: React.FC<Props> = (props) => {
</Helmet>
<h1>Page Not Found</h1>
<section>
<p>The page you were trying to access doesn't exist.</p>
<p>The page you were trying to access doesn&apos;t exist.</p>
<p>
If the page does not automatically reload, please click <a href={url}>here</a>
</p>

View File

@ -1,13 +1,15 @@
import React from "react";
import { MultiLang } from "../../config";
import Functions from "../../functions";
import imageRank2 from "../assets/images/rank3dbf8e94a6f72.gif";
import imageRank3 from "../assets/images/rank3dbf8e9e7d88d.gif";
import imageRank4 from "../assets/images/rank3dbf8ea81e642.gif";
import imageRank5 from "../assets/images/rank3dbf8eb1a72e7.gif";
import imageRank6 from "../assets/images/rank3dbf8edf15093.gif";
import imageRank7 from "../assets/images/rank3dbf8ee8681cd.gif";
import imageRank1 from "../assets/images/rank3e632f95e81ca.gif";
import React from 'react';
import { MultiLang } from '../../config';
import Functions from '../../functions';
import imageRank2 from '../assets/images/rank3dbf8e94a6f72.gif';
import imageRank3 from '../assets/images/rank3dbf8e9e7d88d.gif';
import imageRank4 from '../assets/images/rank3dbf8ea81e642.gif';
import imageRank5 from '../assets/images/rank3dbf8eb1a72e7.gif';
import imageRank6 from '../assets/images/rank3dbf8edf15093.gif';
import imageRank7 from '../assets/images/rank3dbf8ee8681cd.gif';
import imageRank1 from '../assets/images/rank3e632f95e81ca.gif';
interface Props {
lang: MultiLang;
@ -16,16 +18,52 @@ interface Props {
}
const userRanks = [
{ title: "[en]Just popping in[/en][ja]新米[/ja]", min: 0, max: 20, special: false, image: imageRank1 },
{ title: "[en]Not too shy to talk[/en][ja]半人前[/ja]", min: 21, max: 40, special: false, image: imageRank2 },
{ title: "[en]Quite a regular[/en][ja]常連[/ja]", min: 41, max: 70, special: false, image: imageRank3 },
{ title: "[en]Just can't stay away[/en][ja]一人前[/ja]", min: 71, max: 150, special: false, image: imageRank4 },
{ title: "[en]Home away from home[/en][ja]長老[/ja]", min: 151, max: 10000, special: false, image: imageRank5 },
{ title: "[en]Moderator[/en][ja]モデレータ[/ja]", min: 0, max: 0, special: true, image: imageRank6 },
{ title: "[en]Webmaster[/en][ja]管理人[/ja]", min: 0, max: 0, special: true, image: imageRank7 },
{
title: '[en]Just popping in[/en][ja]新米[/ja]',
min: 0,
max: 20,
special: false,
image: imageRank1,
},
{
title: '[en]Not too shy to talk[/en][ja]半人前[/ja]',
min: 21,
max: 40,
special: false,
image: imageRank2,
},
{
title: '[en]Quite a regular[/en][ja]常連[/ja]',
min: 41,
max: 70,
special: false,
image: imageRank3,
},
{
title: "[en]Just can't stay away[/en][ja]一人前[/ja]",
min: 71,
max: 150,
special: false,
image: imageRank4,
},
{
title: '[en]Home away from home[/en][ja]長老[/ja]',
min: 151,
max: 10000,
special: false,
image: imageRank5,
},
{
title: '[en]Moderator[/en][ja]モデレータ[/ja]',
min: 0,
max: 0,
special: true,
image: imageRank6,
},
{ title: '[en]Webmaster[/en][ja]管理人[/ja]', min: 0, max: 0, special: true, image: imageRank7 },
];
const UserRankStarImage: React.FC<Props> = (props: Props) => {
const UserRankStarImage: React.FC<Props> = (props) => {
const { lang, rank, posts } = props;
const findRank = (posts: number) => {
const rank = userRanks.find((userRank) => {
@ -34,7 +72,7 @@ const UserRankStarImage: React.FC<Props> = (props: Props) => {
}
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 title = Functions.mlang(userRank.title, lang);

View File

@ -1,8 +1,15 @@
import ReactHtmlParser, { convertNodeToElement, DomElement, DomNode, Transform } from "@orrisroot/react-html-parser";
import React from "react";
import { HashLink } from "react-router-hash-link";
import { MultiLang } from "../../config";
import Functions from "../../functions";
import React from 'react';
import ReactHtmlParser, {
convertNodeToElement,
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 {
lang: MultiLang;
@ -16,8 +23,8 @@ interface Props {
const preConvertXCode = (text: string, doxcode: boolean): string => {
if (doxcode) {
return text.replace(/\[code\](.*)\[\/code\]/gs, (m0, m1) => {
return "[code]" + Functions.base64Encode(m1) + "[/code]";
return text.replace(/\[code\](.*)\[\/code\]/gs, (_: string, m1: string) => {
return '[code]' + Functions.base64Encode(m1) + '[/code]';
});
}
return text;
@ -25,26 +32,42 @@ const preConvertXCode = (text: string, doxcode: boolean): string => {
const postConvertXCode = (text: string, doxcode: boolean, doimage: boolean): string => {
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);
return '<div class="xoopsCode"><pre><code>' + text + "</code></pre></div>";
return '<div class="xoopsCode"><pre><code>' + text + '</code></pre></div>';
});
}
return text;
};
const convertClickable = (text: string) => {
text = text.replace(/(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+[a-zA-Z0-9=]))/g, (...matches) => {
return 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>";
});
text = text.replace(
/(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+[a-zA-Z0-9=]))/g,
(...matches) => {
return (
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;
};
const convertXCode = (text: string, doimage: boolean): string => {
// TODO: implement
if (doimage) {
return text;
}
return text;
};
@ -54,17 +77,17 @@ const convertSmiley = (text: 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 ret: any = {};
text.split(";").forEach((line) => {
const cssConvert = (text: string): Record<string, string> => {
const ret: Record<string, string> = {};
text.split(';').forEach((line) => {
const line_ = line.trim();
if (line.length === 0) {
return;
}
const kv = line_.split(":");
const kv = line_.split(':');
const key = Functions.camelCase(kv[0].trim());
const value = kv[1].trim();
ret[key] = value;
@ -72,19 +95,24 @@ const cssConvert = (text: string): object => {
return ret;
};
const xoopsTransform: Transform = (node: DomNode, index: number | string, transform?: Transform): React.ReactNode => {
if (node.type === "tag") {
const xoopsTransform: Transform = (
node: DomNode,
index: number | string,
transform?: Transform,
): React.ReactNode => {
if (node.type === ElementType.Tag) {
const node_ = node as DomElement;
if (node_.name === "a") {
const url = node_.attribs?.["href"] || "/";
const download = (node_.attribs && node_.attribs["download"]) || "";
const rel = (node_.attribs && node_.attribs["rel"]) || "";
const klass = (node_.attribs && node_.attribs["class"]) || "";
const isFile = download !== "" || /\.(zip|pdf|png|gif|jpg)$/.test(url);
const isExternal = /external/.test(rel) || /external/.test(klass) || /^(mailto|https?:?\/\/)/.test(url);
if (node_.name === 'a') {
const url = node_.attribs?.href ?? '/';
const download = node_.attribs?.download ?? '';
const rel = node_.attribs?.rel ?? '';
const className = node_.attribs?.class ?? '';
const isFile = download !== '' || /\.(zip|pdf|png|gif|jpg)$/.test(url);
const isExternal =
/external/.test(rel) || /external/.test(className) || /^(mailto|https?:?\/\/)/.test(url);
if (!isFile && !isExternal) {
const style = node_.attribs?.["style"] || "";
const title = node_.attribs?.["title"];
const style = node_.attribs?.style || '';
const title = node_.attribs?.title;
return (
<HashLink key={index} to={url} style={cssConvert(style)} title={title}>
{node_.children.map((value: DomNode, index: number) => {
@ -94,15 +122,15 @@ const xoopsTransform: Transform = (node: DomNode, index: number | string, transf
);
}
}
if (node_.name === "img") {
const src = (node_.attribs && node_.attribs["src"]) || "";
node_.attribs["src"] = src.replace("`XOOPS_URL`", process.env.PUBLIC_URL);
if (node_.name === 'img') {
const src = node_.attribs?.src ?? '';
node_.attribs.src = src.replace('`XOOPS_URL`', '/');
return convertNodeToElement(node_, index, transform);
}
}
};
const XoopsCode: React.FC<Props> = (props: Props) => {
const XoopsCode: React.FC<Props> = (props) => {
const { lang } = props;
let text = props.text;
const dohtml = !!props.dohtml;

View File

@ -1,12 +1,12 @@
const SITE_TITLE = "BSI-NI Brain Atlas";
const SITE_SLOGAN = "Welcome to BRAIN ATLAS";
const GOOGLE_ANALYTICS_TRACKING_ID = "";
const XOONIPS_ITEMTYPES = ["files", "url", "paper", "book"];
const SITE_TITLE = 'BSI-NI Brain Atlas';
const SITE_SLOGAN = 'Welcome to BRAIN ATLAS';
const GOOGLE_ANALYTICS_TRACKING_ID = '';
const XOONIPS_ITEMTYPES = ['files', 'url', 'paper', 'book'];
export type MultiLang = "en" | "ja";
export type MultiLang = 'en' | 'ja';
export type BrainAtlasType = "degu" | "jm" | "marmoset";
export const BrainAtlasTypes: ReadonlyArray<BrainAtlasType> = ["degu", "jm", "marmoset"];
export type BrainAtlasType = 'degu' | 'jm' | 'marmoset';
export const BrainAtlasTypes: readonly BrainAtlasType[] = ['degu', 'jm', 'marmoset'];
const Config = {
SITE_TITLE,

View File

@ -1,21 +1,25 @@
import React from "react";
import { Link } from "react-router-dom";
import PageNotFound from "../common/lib/PageNotFound";
import { BrainAtlasType, MultiLang } from "../config";
import styles from "./CoverPage.module.css";
import React from 'react';
import { Link } from 'react-router-dom';
import PageNotFound from '../common/lib/PageNotFound';
import { BrainAtlasType, MultiLang } from '../config';
import styles from './CoverPage.module.css';
interface Props {
lang: MultiLang;
type: BrainAtlasType;
}
const CoverPage: React.FC<Props> = (props: Props) => {
const CoverPage: React.FC<Props> = (props) => {
const { lang, type } = props;
const links = [
{ 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-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',
},
];
if (type !== "marmoset") {
if (type !== 'marmoset') {
return <PageNotFound lang={lang} />;
}
return (

View File

@ -1,22 +1,29 @@
import React from "react";
import { BrainAtlasType, MultiLang } from "../config";
import styles from "./RelatedLink.module.css";
import React from 'react';
import { BrainAtlasType, MultiLang } from '../config';
import styles from './RelatedLink.module.css';
interface Props {
lang: MultiLang;
type: BrainAtlasType;
}
const RelatedLink: React.FC<Props> = (props: Props) => {
const RelatedLink: React.FC<Props> = (props) => {
const { type } = props;
const links = {
degu: [{ title: "RIKEN BSI", url: "http://www.brain.riken.jp/" }],
jm: [{ 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/' }],
marmoset: [
{ 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: "Press release", url: "http://www.brain.riken.jp/first-okano/en/achievements/2010/papers.html" },
{ title: 'RIKEN BSI', url: 'http://www.brain.riken.jp/' },
{
title: 'Keio-RIKEN Research centre for Human Cognition',
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 (

View File

@ -1,14 +1,15 @@
import React from "react";
import { Link } from "react-router-dom";
import NoticeSiteHasBeenArchived from "../common/lib/NoticeSiteHasBeenArchived";
import { MultiLang } from "../config";
import styles from "./SiteIndex.module.css";
import React from 'react';
import { Link } from 'react-router-dom';
import NoticeSiteHasBeenArchived from '../common/lib/NoticeSiteHasBeenArchived';
import { MultiLang } from '../config';
import styles from './SiteIndex.module.css';
interface Props {
lang: MultiLang;
}
const SiteIndex: React.FC<Props> = (props: Props) => {
const SiteIndex: React.FC<Props> = (props) => {
const { lang } = props;
return (
<div className={styles.siteIndex}>
@ -29,7 +30,10 @@ const SiteIndex: React.FC<Props> = (props: Props) => {
</Link>
</li>
<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>
</Link>
</li>

View File

@ -1,88 +1,102 @@
import React from "react";
import { Helmet } from "react-helmet-async";
import { Route, Routes, useLocation } from "react-router-dom";
import PageNotFound from "../common/lib/PageNotFound";
import { BrainAtlasType, MultiLang } from "../config";
import Functions from "../functions";
import styles from "./Database.module.css";
import DatabaseAdvancedSearch from "./DatabaseAdvancedSearch";
import DatabaseDetailItem from "./DatabaseDetailItem";
import DatabaseSearchByAdvancedKeyword from "./DatabaseSearchByAdvancedKeyword";
import DatabaseSearchByIndexId from "./DatabaseSearchByIndexId";
import DatabaseSearchByItemType from "./DatabaseSearchByItemType";
import DatabaseSearchByKeyword from "./DatabaseSearchByKeyword";
import DatabaseTop from "./DatabaseTop";
import { INDEX_ID_PUBLIC } from "./lib/IndexUtil";
import React from 'react';
import { Helmet } from 'react-helmet-async';
import { Route, Routes, useLocation } from 'react-router-dom';
import PageNotFound from '../common/lib/PageNotFound';
import { BrainAtlasType, MultiLang } from '../config';
import Functions from '../functions';
import styles from './Database.module.css';
import DatabaseAdvancedSearch from './DatabaseAdvancedSearch';
import DatabaseDetailItem from './DatabaseDetailItem';
import DatabaseSearchByAdvancedKeyword from './DatabaseSearchByAdvancedKeyword';
import DatabaseSearchByIndexId from './DatabaseSearchByIndexId';
import DatabaseSearchByItemType from './DatabaseSearchByItemType';
import DatabaseSearchByKeyword from './DatabaseSearchByKeyword';
import DatabaseTop from './DatabaseTop';
import { INDEX_ID_PUBLIC } from './lib/IndexUtil';
interface Props {
lang: MultiLang;
type: BrainAtlasType;
}
const ItemDetail: React.FC<Props> = (props: Props) => {
const ItemDetail: React.FC<Props> = (props) => {
const { lang, type } = props;
const location = useLocation();
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 doi = params.get("id") || "";
const doi = params.get('id') ?? '';
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 location = useLocation();
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;
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 location = useLocation();
const params = new URLSearchParams(location.search);
const op = params.get("op") || "";
const op = params.get('op') ?? '';
switch (op) {
case "itemtypesearch": {
const searchItemtype = params.get("search_itemtype") || "";
case 'itemtypesearch': {
const searchItemtype = params.get('search_itemtype') ?? '';
const match = searchItemtype.match(/^xnp([a-z]+)$/);
const itemType = match !== null ? match[1] : "";
return <DatabaseSearchByItemType lang={lang} itemType={itemType} subItemType="" type={type} />;
const itemType = match !== null ? match[1] : '';
return (
<DatabaseSearchByItemType lang={lang} itemType={itemType} subItemType="" type={type} />
);
}
case "itemsubtypesearch": {
const searchItemtype = params.get("search_itemtype") || "";
case 'itemsubtypesearch': {
const searchItemtype = params.get('search_itemtype') ?? '';
const match = searchItemtype.match(/^xnp([a-z]+)$/);
const itemType = match !== null ? match[1] : "";
const subItemtype = params.get("search_subitemtype") || "";
return <DatabaseSearchByItemType lang={lang} itemType={itemType} subItemType={subItemtype} type={type} />;
const itemType = match !== null ? match[1] : '';
const subItemtype = params.get('search_subitemtype') ?? '';
return (
<DatabaseSearchByItemType
lang={lang}
itemType={itemType}
subItemType={subItemtype}
type={type}
/>
);
}
case "quicksearch": {
case 'quicksearch': {
return <DatabaseSearchByKeyword lang={lang} type={type} />;
}
case "advanced": {
case 'advanced': {
return <DatabaseSearchByAdvancedKeyword lang={lang} type={type} />;
}
}
return <PageNotFound lang={lang} />;
};
const Database: React.FC<Props> = (props: Props) => {
const Database: React.FC<Props> = (props) => {
const { lang, type } = props;
return (
<div className={styles.database}>
<Helmet>
<title>
{Functions.mlang("[en]Database[/en][ja]データベース[/ja]", lang)} - {Functions.siteTitle(lang)}
{Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} -{' '}
{Functions.siteTitle(lang)}
</title>
</Helmet>
<Routes>
<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="listitem.php" element={<ItemList 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} />} />
</Routes>
</div>

View File

@ -1,63 +1,47 @@
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";
import React from 'react';
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;
type: BrainAtlasType;
}
interface Props extends PropsFC {
navigate: any;
}
const DatabaseAdvancedSearch: React.FC<Props> = (props) => {
const { lang, type } = props;
const query = new AdvancedSearchQuery();
const navigate = useNavigate();
class DatabaseAdvancedSearch extends React.Component<Props> {
private query: AdvancedSearchQuery = new AdvancedSearchQuery();
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);
const handleClickSearchButton = () => {
if (!query.empty()) {
const url = ItemUtil.getSearchByAdvancedKeywordsUrl(type, query);
navigate(url);
}
}
render() {
const { lang } = this.props;
};
return (
<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">
<button className="formButton" onClick={this.handleClickSearchButton}>
<button className="formButton" onClick={handleClickSearchButton}>
Search
</button>
</div>
{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">
<button className="formButton" onClick={this.handleClickSearchButton}>
<button className="formButton" onClick={handleClickSearchButton}>
Search
</button>
</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;

View File

@ -1,11 +1,12 @@
import React from "react";
import { Helmet } from "react-helmet-async";
import Loading from "../common/lib/Loading";
import PageNotFound from "../common/lib/PageNotFound";
import { BrainAtlasType, MultiLang } from "../config";
import Functions from "../functions";
import ItemType from "./item-type";
import ItemUtil, { Item } from "./lib/ItemUtil";
import React from 'react';
import { Helmet } from 'react-helmet-async';
import Loading from '../common/lib/Loading';
import PageNotFound from '../common/lib/PageNotFound';
import { BrainAtlasType, MultiLang } from '../config';
import Functions from '../functions';
import ItemType from './item-type';
import ItemUtil, { Item } from './lib/ItemUtil';
interface Props {
lang: MultiLang;
@ -14,65 +15,49 @@ interface Props {
doi: string;
}
interface State {
loading: boolean;
item: Item | null;
}
const DatabaseDetailItem: React.FC<Props> = (props) => {
const { lang, type, id, doi } = props;
class DatabaseDetailItem extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
loading: true,
item: null,
};
}
const [loading, setLoading] = React.useState<boolean>(true);
const [item, setItem] = React.useState<Item | null>(null);
componentDidMount() {
this.updateItem();
}
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 !== "") {
React.useEffect(() => {
if (doi !== '') {
ItemUtil.getByDoi(type, doi, (item) => {
this.setState({ loading: false, item });
setItem(item);
setLoading(false);
});
} else if (id !== 0) {
ItemUtil.get(type, id, (item) => {
this.setState({ loading: false, item });
setItem(item);
setLoading(false);
});
} else {
setLoading(true);
}
}
}, [type, id, doi]);
render() {
const { lang, type } = this.props;
if (this.state.loading) {
if (loading) {
return <Loading />;
}
if (this.state.item === null) {
if (item === null) {
return <PageNotFound lang={lang} />;
}
return (
<>
<Helmet>
<title>
{Functions.mlang(this.state.item.title, lang)} - {Functions.mlang("[en]Database[/en][ja]データベース[/ja]", lang)} - {Functions.siteTitle(lang)}
{Functions.mlang(item.title, lang)} -{' '}
{Functions.mlang('[en]Database[/en][ja]データベース[/ja]', lang)} -{' '}
{Functions.siteTitle(lang)}
</title>
</Helmet>
<h3>{Functions.mlang("[en]Detail[/en][ja]詳細[/ja]", lang)}</h3>
<h3>{Functions.mlang('[en]Detail[/en][ja]詳細[/ja]', lang)}</h3>
<br />
<ItemType.Detail lang={lang} item={this.state.item} type={type} />
<ItemType.Detail lang={lang} item={item} type={type} />
</>
);
}
}
};
export default DatabaseDetailItem;

View File

@ -1,67 +1,32 @@
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";
import React from 'react';
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;
type: BrainAtlasType;
}
interface Props extends PropsFC {
location: any;
}
const DatabaseSearchByAdvancedKeyword: React.FC<Props> = (props) => {
const { lang, type } = props;
const location = useLocation();
const query = ItemUtil.getAdvancedSearchQueryByQuery(location.search);
interface State {
search: string;
query: AdvancedSearchQuery;
}
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
ItemUtil.getListByAdvancedSearchQuery(type, query, condition, func);
};
class DatabaseSearchByAdvancedKeyword extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
const search = props.location.search;
const query = ItemUtil.getAdvancedSearchQueryByQuery(search);
this.state = { search, query };
this.searchFunc = this.searchFunc.bind(this);
}
const baseUrl = ItemUtil.getSearchByAdvancedKeywordsUrl(type, query);
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 (
<div className="list">
<h3>Listing item</h3>
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} type={type} />
<DatabaseListItem lang={lang} url={baseUrl} search={searchFunc} type={type} />
</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;

View File

@ -1,80 +1,92 @@
import React, { Fragment } 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";
import React from 'react';
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;
type: BrainAtlasType;
indexId: number;
}
class DatabaseSearchByIndexId extends React.Component<Props> {
constructor(props: Props) {
super(props);
this.searchFunc = this.searchFunc.bind(this);
}
const DatabaseSearchByIndexId: React.FC<Props> = (props) => {
const { lang, type, indexId } = props;
getUrl() {
const { type, indexId } = this.props;
if (indexId === 0) {
return "/";
}
return IndexUtil.getUrl(type, indexId);
}
const [notFound, setNotFound] = React.useState<boolean>(false);
const [index, setIndex] = React.useState<Index | null>(null);
const [parents, setParents] = React.useState<{ title: string; node: React.ReactNode }>({
title: '',
node: null,
});
searchFunc(condition: SortCondition, func: SearchCallbackFunc) {
const { type, indexId } = this.props;
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
if (indexId === 0) {
const res = { total: 0, data: [] };
func(res);
} else {
ItemUtil.getListByIndexId(type, indexId, condition, func);
}
}
};
render() {
const { lang, type, indexId } = this.props;
const index = IndexUtil.get(type, indexId);
if (index === null) {
return <PageNotFound lang={lang} />;
}
const baseUrl = this.getUrl();
const pIndexes = IndexUtil.getParents(type, indexId);
const parents = pIndexes.map((value: Index) => {
const url: string = IndexUtil.getUrl(type, value.id);
const title = Functions.mlang(value.title, lang);
React.useEffect(() => {
IndexUtil.get(type, indexId, (index) => {
setIndex(index);
if (index == null) {
setNotFound(true);
} else {
IndexUtil.getParents(type, indexId, (pIndexes) => {
const parents = pIndexes.map((index: Index) => {
const url: string = IndexUtil.getUrl(type, index.id);
const title = Functions.mlang(index.title, lang);
return (
<Fragment key={value.id}>
/ <Link to={url}>{title}</Link>{" "}
</Fragment>
<React.Fragment key={index.id}>
/ <Link to={url}>{title}</Link>{' '}
</React.Fragment>
);
});
const title = pIndexes
.map((value) => {
return "/" + Functions.mlang(value.title, lang);
.map((index) => {
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 (
<div className="list">
<Helmet>
<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>
</Helmet>
<h3>{Functions.mlang("[en]Listing item[/en][ja]アイテム一覧[/ja]", lang)}</h3>
<div>{parents}</div>
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
<div>{parents.node}</div>
<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>
);
}
}
};
export default DatabaseSearchByIndexId;

View File

@ -1,8 +1,9 @@
import React from "react";
import { BrainAtlasType, MultiLang } from "../config";
import Functions from "../functions";
import DatabaseListItem from "./lib/DatabaseListItem";
import ItemUtil, { SearchCallbackFunc, SortCondition } from "./lib/ItemUtil";
import React from 'react';
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;
@ -11,38 +12,26 @@ interface Props {
type: BrainAtlasType;
}
class DatabaseSearchByItemType extends React.Component<Props> {
constructor(props: Props) {
super(props);
this.searchFunc = this.searchFunc.bind(this);
}
const DatabaseSearchByItemType: React.FC<Props> = (props) => {
const { lang, itemType, subItemType, type } = props;
searchFunc(condition: SortCondition, func: SearchCallbackFunc) {
const { itemType, subItemType, type } = this.props;
if (itemType === "") {
const searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
if (itemType === '') {
const res = { total: 0, data: [] };
func(res);
} else {
ItemUtil.getListByItemType(type, itemType, subItemType, condition, func);
}
}
};
getUrl() {
const { itemType, subItemType, type } = this.props;
let url = ItemUtil.getItemTypeSearchUrl(type, itemType, subItemType);
return url;
}
const baseUrl = ItemUtil.getItemTypeSearchUrl(type, itemType, subItemType);
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>
<DatabaseListItem lang={lang} url={baseUrl} search={this.searchFunc} type={type} />
<h3>{Functions.mlang('[en]Listing item[/en][ja]アイテム一覧[/ja]', lang)}</h3>
<DatabaseListItem lang={lang} url={baseUrl} search={searchFunc} type={type} />
</div>
);
}
}
};
export default DatabaseSearchByItemType;

View File

@ -1,74 +1,41 @@
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";
import React from 'react';
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;
type: BrainAtlasType;
}
interface Props extends PropsFC {
location: any;
}
const DatabaseSearchByKeyword: React.FC<Props> = (props) => {
const { lang, type } = props;
interface State {
type: KeywordSearchType;
keyword: string;
}
const location = useLocation();
const query = ItemUtil.getSearchKeywordByQuery(location.search);
class DatabaseSearchByKeyword extends React.Component<Props, State> {
constructor(props: Props) {
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 searchFunc = (condition: SortCondition, func: SearchCallbackFunc) => {
if (query.keyword === '') {
const res = { total: 0, data: [] };
func(res);
} 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;

View File

@ -1,14 +1,15 @@
import React from "react";
import Config, { BrainAtlasType, MultiLang } from "../config";
import styles from "./DatabaseTop.module.css";
import ItemType from "./item-type";
import React from 'react';
import Config, { BrainAtlasType, MultiLang } from '../config';
import styles from './DatabaseTop.module.css';
import ItemType from './item-type';
interface Props {
lang: MultiLang;
type: BrainAtlasType;
}
const DatabaseTop: React.FC<Props> = (props: Props) => {
const DatabaseTop: React.FC<Props> = (props) => {
const { lang, type } = props;
const types: string[][] = [];
const len = Config.XOONIPS_ITEMTYPES.length;
@ -26,7 +27,9 @@ const DatabaseTop: React.FC<Props> = (props: Props) => {
{value.map((itemType, idx) => {
return (
<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>
);
})}

View File

@ -1,121 +1,123 @@
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
import PageNotFound from "../common/lib/PageNotFound";
import { MultiLang } from "../config";
import Functions from "../functions";
import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import PageNotFound from '../common/lib/PageNotFound';
import { MultiLang } from '../config';
import Functions from '../functions';
interface Props {
lang: MultiLang;
}
const DatabaseXoopsPathRedirect: React.FC<Props> = (props: Props) => {
const DatabaseXoopsPathRedirect: React.FC<Props> = (props) => {
const { lang } = props;
const location = useLocation();
const getRedirectUrl = (): string => {
const location = useLocation();
const pathname = location.pathname || "";
const pathname = location.pathname || '';
const query = new URLSearchParams(location.search);
const search = new RegExp("^/modules/xoonips(?:/+(.*))?$");
const search = new RegExp('^/modules/xoonips(?:/+(.*))?$');
const matches = pathname.match(search);
if (matches === null) {
return "";
return '';
}
const path = matches[1] || "";
const path = matches[1] || '';
switch (path) {
case "":
case "index.php": {
return "/database";
case '':
case 'index.php': {
return '/database';
}
case "detail.php": {
const id = query.get("id");
case 'detail.php': {
const id = query.get('id');
if (id !== null) {
return "/database/item/id/" + Functions.escape(id);
return '/database/item/id/' + Functions.escape(id);
}
const itemId = query.get("item_id");
if (itemId !== null && itemId.match(/^\d+$/) !== null) {
return "/database/item/" + Functions.escape(itemId);
const itemId = query.get('item_id');
if (itemId?.match(/^\d+$/) != null) {
return '/database/item/' + Functions.escape(itemId);
}
return "";
return '';
}
case "listitem.php": {
const indexId = query.get("index_id");
if (indexId !== null && indexId.match(/^\d+$/) !== null) {
case 'listitem.php': {
const indexId = query.get('index_id');
if (indexId?.match(/^\d+$/) != null) {
const params = new URLSearchParams();
const map: any = {
orderby: { key: "orderby", isNumber: false },
order_dir: { key: "order_dir", isNumber: true },
itemcount: { key: "itemcount", isNumber: true },
page: { key: "page", isNumber: true },
};
for (let k in map) {
const v = query.get(k);
if (v === null || v.length === 0) {
continue;
[
{ qKey: 'orderby', pKey: 'orderby', isNumber: false },
{ qKey: 'order_dir', pKey: 'order_dir', isNumber: true },
{ qKey: 'itemcount', pKey: 'itemcount', isNumber: true },
{ qKey: 'page', pKey: 'page', isNumber: true },
].forEach(({ qKey, pKey, isNumber }) => {
const v = query.get(qKey);
if (v == null || v.length === 0) {
return;
}
if (map[k].isNumber && v.match(/^\d+$/) !== null) {
continue;
}
params.set(map[k].key, v);
if (isNumber && v.match(/^\d+$/) != null) {
return;
}
params.set(pKey, v);
});
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;
}
case "itemselect.php": {
const op = query.get("op");
case 'itemselect.php': {
const op = query.get('op');
if (op === null) {
break;
}
switch (op) {
case "quicksearch": {
const keyword = query.get("keyword");
const itemType = query.get("search_itemtype");
if (keyword === null || itemType === null || keyword === "") {
return "";
case 'quicksearch': {
const keyword = query.get('keyword');
const itemType = query.get('search_itemtype');
if (keyword === null || itemType === null || keyword === '') {
return '';
}
const type = itemType.replace("xnp", "");
if (itemType !== "basic" && itemType !== "all" && itemType.match(/^xnp.+/) === null) {
return "";
const type = itemType.replace('xnp', '');
if (itemType !== 'basic' && itemType !== 'all' && itemType.match(/^xnp.+/) === null) {
return '';
}
const params = new URLSearchParams({ type, keyword });
const map: any = {
orderby: { key: "orderby", isNumber: false },
orderdir: { key: "order_dir", isNumber: true },
item_per_page: { key: "itemcount", isNumber: true },
page: { key: "page", isNumber: true },
};
for (let k in map) {
const v = query.get(k);
if (v === null || v.length === 0) {
continue;
[
{ qKey: 'orderby', pKey: 'orderby', isNumber: false },
{ qKey: 'orderdir', pKey: 'order_dir', isNumber: true },
{ qKey: 'item_per_page', pKey: 'itemcount', isNumber: true },
{ qKey: 'page', pKey: 'page', isNumber: true },
].forEach(({ qKey, pKey, isNumber }) => {
const v = query.get(qKey);
if (v == null || v.length === 0) {
return;
}
if (map[k].isNumber && v.match(/^\d+$/) !== null) {
continue;
if (isNumber && v.match(/^\d+$/) != null) {
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 itemType = query.get("search_itemtype");
if (itemType === null || itemType.match(/^xnp.+/) === null) {
return "";
const type = itemType.replace('xnp', '');
return '/database/search/itemtype/' + Functions.escape(type);
}
const type = itemType.replace("xnp", "");
return "/database/search/itemtype/" + Functions.escape(type);
}
case "itemsubtypesearch": {
let type = "";
let subtype = "";
case 'itemsubtypesearch': {
let type = '';
let subtype = '';
query.forEach((v, k) => {
if (k.match(/^xnp[a-z]+$/) !== null && !!v) {
type = k.replace("xnp", "");
type = k.replace('xnp', '');
return;
}
});
if (type === "") {
return "";
if (type === '') {
return '';
}
query.forEach((v, k) => {
if (k.match(`^xnp${type}_.+$`) !== null && !!v) {
@ -123,23 +125,28 @@ const DatabaseXoopsPathRedirect: React.FC<Props> = (props: Props) => {
return;
}
});
if (subtype === "") {
return "";
if (subtype === '') {
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": {
return "/database/advanced";
case 'advanced_search.php': {
return '/database/advanced';
}
}
return "";
return '';
};
const url = getRedirectUrl();
if (url === "") {
if (url === '') {
return <PageNotFound lang={lang} />;
}
return <Navigate to={url} />;

View File

@ -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":[]}]}]}]}]

View File

@ -41,13 +41,25 @@
width: 9px;
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;
}
.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;
}
.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;
}
@ -69,14 +81,20 @@
.indexTree:global(.rc-tree .rc-tree-treenode:first-child .rc-tree-switcher.rc-tree-switcher_close) {
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;
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;
}
.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;
}

View File

@ -1,136 +1,133 @@
import Tree from "rc-tree";
import { DataNode, EventDataNode } from "rc-tree/lib/interface";
import React, { Key } from "react";
import { useNavigate } from "react-router";
import { BrainAtlasType, MultiLang } from "../../config";
import Functions from "../../functions";
import IndexUtil, { Index, INDEX_ID_PUBLIC } from "../lib/IndexUtil";
import styles from "./IndexTree.module.css";
import React from 'react';
import Tree from 'rc-tree';
import { DataNode, EventDataNode } from 'rc-tree/lib/interface';
import { useNavigate } from 'react-router';
import Loading from '../../common/lib/Loading';
import { BrainAtlasType, MultiLang } from '../../config';
import Functions from '../../functions';
import IndexUtil, { INDEX_ID_PUBLIC, Index } from '../lib/IndexUtil';
import styles from './IndexTree.module.css';
interface Props {
lang: MultiLang;
type: BrainAtlasType;
}
interface State {
tree: DataNode[];
expandableKeys: string[];
expandedKeys: string[];
selectedKeys: number[];
}
const IndexTree: React.FC<Props> = (props) => {
const { lang, type } = props;
const navigate = useNavigate();
class IndexTree extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.handleClickOpenAll = this.handleClickOpenAll.bind(this);
this.handleClickCloseAll = this.handleClickCloseAll.bind(this);
this.handleExpand = this.handleExpand.bind(this);
this.handleSelect = this.handleSelect.bind(this);
const res = this.load();
this.state = {
tree: res.elements,
expandableKeys: res.keys,
expandedKeys: res.expandedKeys,
selectedKeys: [],
};
}
const [tree, setTree] = React.useState<DataNode[]>([]);
const [keys, setKeys] = React.useState<string[]>([]);
const [expandedKeys, setExpandedKeys] = React.useState<string[]>([]);
const [selectedKeys, setSelectedKeys] = React.useState<number[]>([]);
load() {
const { lang, type } = this.props;
let keys: string[] = [];
let eKeys: string[] = [];
const makeTreeNode = (index: Index, depth: number): DataNode => {
const title = Functions.mlang(index.title, lang) + (index.numOfItems > 0 ? " (" + index.numOfItems + ")" : "");
const children = IndexUtil.getChildren(type, index.id);
React.useEffect(() => {
const tree: DataNode[] = [];
const keys: string[] = [];
const eKeys: string[] = [];
const makeTreeNode = (index: Index, depth: number, func: (node: DataNode) => void): void => {
const title =
Functions.mlang(index.title, lang) +
(index.numOfItems > 0 ? ' (' + index.numOfItems + ')' : '');
IndexUtil.getChildren(type, index.id, (children) => {
if (children.length === 0) {
return { key: String(index.id), title: title };
}
const childTreeNodes = children.map((value: Index) => {
return makeTreeNode(value, depth + 1);
});
func({ key: String(index.id), title: title });
} else {
if (depth < 1) {
eKeys.push(String(index.id));
}
keys.push(String(index.id));
return { key: String(index.id), title: title, children: childTreeNodes };
};
let elements: DataNode[] = [];
const index = IndexUtil.get(type, INDEX_ID_PUBLIC);
if (index !== null) {
elements.push(makeTreeNode(index, 0));
const childTreeNodes: DataNode[] = [];
let called = 0;
children.forEach((value: Index) => {
makeTreeNode(value, depth + 1, (cNode) => {
called++;
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() {
this.setState({ expandedKeys: this.state.expandableKeys });
}
const handleClickOpenAll = () => {
setExpandedKeys(keys);
};
handleClickCloseAll() {
this.setState({ expandedKeys: [] });
}
const handleClickCloseAll = () => {
setExpandedKeys([]);
};
handleExpand(
expandedKeys: Key[],
const handleExpand: (
expandedKeys: React.Key[],
info: {
node: EventDataNode<DataNode>;
expanded: boolean;
nativeEvent: MouseEvent;
}
): void {
},
) => void = (expandedKeys) => {
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(
selectedKeys: Key[],
const handleSelect: (
selectedKeys: React.Key[],
info: {
event: "select";
event: 'select';
selected: boolean;
node: EventDataNode<DataNode>;
selectedNodes: DataNode[];
nativeEvent: MouseEvent;
}
): void {
const navigate = useNavigate();
const { type } = this.props;
const selectedKey = selectedKeys.shift() || 0;
const key = typeof selectedKey === "string" ? parseInt(selectedKey, 10) : selectedKey;
},
) => void = (selectedKeys) => {
const selectedKey = selectedKeys.shift() ?? 0;
const key = typeof selectedKey === 'string' ? parseInt(selectedKey, 10) : selectedKey;
const url = IndexUtil.getUrl(type, key);
navigate(url);
this.setState({ selectedKeys: [] });
setSelectedKeys([]);
};
if (tree.length === 0) {
return <Loading />;
}
render() {
return (
<div className={styles.container}>
<button className={styles.formButton} onClick={this.handleClickOpenAll}>
<button className={styles.formButton} onClick={handleClickOpenAll}>
open all
</button>
<button className={styles.formButton} onClick={this.handleClickCloseAll}>
<button className={styles.formButton} onClick={handleClickCloseAll}>
close all
</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>
);
}
}
};
export default IndexTree;

View File

@ -1,22 +1,28 @@
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
class BinderAdvancedSearch extends AdvancedSearchBase {
constructor(props: AdvancedSearchBaseProps) {
super(props);
this.type = "binder";
this.title = "Binder";
this.state.values["title"] = "";
this.state.values["keyword"] = "";
this.state.values["description"] = "";
this.state.values["doi"] = "";
this.type = 'binder';
this.title = 'Binder';
this.state.values.title = '';
this.state.values.keyword = '';
this.state.values.description = '';
this.state.values.doi = '';
}
getRows() {
const rows = [
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 50) },
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: this.renderFieldInputText("keyword", 50) },
{ label: "[en]Description[/en][ja]概要[/ja]", value: this.renderFieldInputText("description", 50) },
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) },
{
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
value: this.renderFieldInputText('keyword', 50),
},
{
label: '[en]Description[/en][ja]概要[/ja]',
value: this.renderFieldInputText('description', 50),
},
{ label: 'ID', value: this.renderFieldInputText('doi', 50) },
];
return rows;
}

View File

@ -1,10 +1,11 @@
import React from "react";
import ItemType from "..";
import { BrainAtlasType, MultiLang } from "../../../config";
import Functions from "../../../functions";
import ItemUtil, { Item, ItemBinder } from "../../lib/ItemUtil";
import DetailBase from "../lib/DetailBase";
import ItemTypeField from "../lib/field";
import React from 'react';
import ItemType from '..';
import { BrainAtlasType, MultiLang } from '../../../config';
import Functions from '../../../functions';
import ItemUtil, { Item, ItemBinder } from '../../lib/ItemUtil';
import DetailBase from '../lib/DetailBase';
import ItemTypeField from '../lib/field';
interface Props {
lang: MultiLang;
@ -12,46 +13,32 @@ interface Props {
type: BrainAtlasType;
}
interface State {
items: Item[];
}
const BinderLinkItems: React.FC<Props> = (props) => {
const { lang, item, type } = props;
const [items, setItems] = React.useState<Item[]>([]);
class BinderLinkItems extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
items: [],
const isMounted = React.useRef<boolean>(false);
React.useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}
}, []);
componentDidMount() {
this.updateItems();
}
componentDidUpdate(prevProps: Props, prevState: State) {
const prevItemIds = prevProps.item.item_link;
const nextItemIds = this.props.item.item_link;
if (prevItemIds.toString() !== nextItemIds.toString()) {
this.updateItems();
}
}
updateItems() {
const { item, type } = this.props;
React.useEffect(() => {
const itemIds = item.item_link;
ItemUtil.getList(type, itemIds, (results) => {
const items = results.data;
this.setState({ items });
});
if (isMounted.current) {
setItems(results.data);
}
});
}, [item.item_link, type]);
render() {
const { lang, type } = this.props;
return (
<table className="listTable">
<tbody>
{this.state.items.map((item, idx) => {
const evenodd = idx % 2 ? "even" : "odd";
{items.map((item, idx) => {
const evenodd = idx % 2 ? 'even' : 'odd';
return (
<tr key={item.item_id}>
<td className={evenodd}>
@ -63,24 +50,44 @@ class BinderLinkItems extends React.Component<Props, State> {
</tbody>
</table>
);
}
}
};
class BinderDetail extends DetailBase {
getFields() {
const { lang, type } = this.props;
const item = this.props.item as ItemBinder;
return [
{ label: "ID", value: item.doi },
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: Functions.mlang(item.title, lang) },
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: <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: "Index", value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} /> },
{ label: 'ID', value: item.doi },
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: Functions.mlang(item.title, lang) },
{
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
value: <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: 'Index',
value: <ItemTypeField.ItemIndex lang={lang} index={item.index} type={type} />,
},
];
}

View File

@ -1,14 +1,13 @@
import React from "react";
import { Link } from "react-router-dom";
import Functions from "../../../functions";
import iconFile from "../../assets/images/icon_binder.gif";
import { ItemBinder } from "../../lib/ItemUtil";
import ListBase, { ListBaseProps } from "../lib/ListBase";
import { Link } from 'react-router-dom';
import Functions from '../../../functions';
import iconFile from '../../assets/images/icon_binder.gif';
import { ItemBinder } from '../../lib/ItemUtil';
import ListBase, { ListBaseProps } from '../lib/ListBase';
class BinderList extends ListBase {
constructor(props: ListBaseProps) {
super(props);
this.label = "Binder";
this.label = 'Binder';
this.icon = iconFile;
}

View File

@ -1,13 +1,13 @@
import iconFile from "../../assets/images/icon_binder.gif";
import TopBase, { TopBaseProps } from "../lib/TopBase";
import iconFile from '../../assets/images/icon_binder.gif';
import TopBase, { TopBaseProps } from '../lib/TopBase';
class BinderTop extends TopBase {
constructor(props: TopBaseProps) {
super(props);
this.type = "binder";
this.label = "Binder";
this.type = 'binder';
this.label = 'Binder';
this.icon = iconFile;
this.description = "[en]Binder collection.[/en][ja]バインダー[/ja]";
this.description = '[en]Binder collection.[/en][ja]バインダー[/ja]';
}
}

View File

@ -1,7 +1,7 @@
import BinderAdvancedSearch from "./BinderAdvancedSearch";
import BinderDetail from "./BinderDetail";
import BinderList from "./BinderList";
import BinderTop from "./BinderTop";
import BinderAdvancedSearch from './BinderAdvancedSearch';
import BinderDetail from './BinderDetail';
import BinderList from './BinderList';
import BinderTop from './BinderTop';
const ItemTypeBinder = {
Top: BinderTop,

View File

@ -1,34 +1,52 @@
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
class BookAdvancedSearch extends AdvancedSearchBase {
constructor(props: AdvancedSearchBaseProps) {
super(props);
this.type = "book";
this.title = "Book";
this.state.values["title"] = "";
this.state.values["keyword"] = "";
this.state.values["description"] = "";
this.state.values["doi"] = "";
this.state.values["author"] = "";
this.state.values["editor"] = "";
this.state.values["publisher"] = "";
this.state.values["publication_year"] = "";
this.state.values["isbn"] = "";
this.state.values["file.book_pdf.original_file_name"] = "";
this.type = 'book';
this.title = 'Book';
this.state.values.title = '';
this.state.values.keyword = '';
this.state.values.description = '';
this.state.values.doi = '';
this.state.values.author = '';
this.state.values.editor = '';
this.state.values.publisher = '';
this.state.values.publication_year = '';
this.state.values.isbn = '';
this.state.values['file.book_pdf.original_file_name'] = '';
}
getRows() {
const rows = [
{ label: "[en]Book Title[/en][ja]著書名[/ja]", value: this.renderFieldInputText("title", 50) },
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: this.renderFieldInputText("keyword", 50) },
{ label: "[en]Description[/en][ja]概要[/ja]", value: this.renderFieldInputText("description", 50) },
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
{ label: "[en]Author[/en][ja]著者[/ja]", value: this.renderFieldInputText("author", 50) },
{ label: "[en]Editor[/en][ja]編集者[/ja]", value: this.renderFieldInputText("editor", 50) },
{ label: "[en]Publisher[/en][ja]出版社[/ja]", value: this.renderFieldInputText("publisher", 50) },
{ label: "[en]Publication Year[/en][ja]出版年[/ja]", value: this.renderFieldInputText("publication_year", 10) },
{ label: "ISBN", value: this.renderFieldInputText("isbn", 50) },
{ label: "[en]PDF File[/en][ja]PDF ファイル[/ja]", value: this.renderFieldInputText("file.book_pdf.original_file_name", 50) },
{
label: '[en]Book Title[/en][ja]著書名[/ja]',
value: this.renderFieldInputText('title', 50),
},
{
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
value: this.renderFieldInputText('keyword', 50),
},
{
label: '[en]Description[/en][ja]概要[/ja]',
value: this.renderFieldInputText('description', 50),
},
{ label: 'ID', value: this.renderFieldInputText('doi', 50) },
{ label: '[en]Author[/en][ja]著者[/ja]', value: this.renderFieldInputText('author', 50) },
{ label: '[en]Editor[/en][ja]編集者[/ja]', value: this.renderFieldInputText('editor', 50) },
{
label: '[en]Publisher[/en][ja]出版社[/ja]',
value: this.renderFieldInputText('publisher', 50),
},
{
label: '[en]Publication Year[/en][ja]出版年[/ja]',
value: this.renderFieldInputText('publication_year', 10),
},
{ label: 'ISBN', value: this.renderFieldInputText('isbn', 50) },
{
label: '[en]PDF File[/en][ja]PDF ファイル[/ja]',
value: this.renderFieldInputText('file.book_pdf.original_file_name', 50),
},
];
return rows;
}

View File

@ -1,39 +1,79 @@
import React from "react";
import Functions from "../../../functions";
import { ItemBook } from "../../lib/ItemUtil";
import DetailBase from "../lib/DetailBase";
import ItemTypeField from "../lib/field";
import Functions from '../../../functions';
import { ItemBook } from '../../lib/ItemUtil';
import DetailBase from '../lib/DetailBase';
import ItemTypeField from '../lib/field';
class BookDetail extends DetailBase {
getFields() {
const { lang, type } = this.props;
const item = this.props.item as ItemBook;
return [
{ 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: 'ID', value: item.doi },
{
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: (
<a href={item.url} target="_blank" rel="noopener noreferrer">
{item.url}
</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]Related to[/en][ja]関連アイテム[/ja]", value: <ItemTypeField.RelatedTo lang={lang} relatedTo={item.related_to} type={type} /> },
{
label: '[en]PDF File[/en][ja]PDF ファイル[/ja]',
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} />,
},
];
}
}

View File

@ -1,14 +1,14 @@
import React, { Fragment } from "react";
import { Link } from "react-router-dom";
import Functions from "../../../functions";
import iconFile from "../../assets/images/icon_book.gif";
import { ItemBook } from "../../lib/ItemUtil";
import ListBase, { ListBaseProps } from "../lib/ListBase";
import { Fragment } from 'react';
import { Link } from 'react-router-dom';
import Functions from '../../../functions';
import iconFile from '../../assets/images/icon_book.gif';
import { ItemBook } from '../../lib/ItemUtil';
import ListBase, { ListBaseProps } from '../lib/ListBase';
class BookList extends ListBase {
constructor(props: ListBaseProps) {
super(props);
this.label = "Book";
this.label = 'Book';
this.icon = iconFile;
}
@ -18,7 +18,7 @@ class BookList extends ListBase {
const authors = item.author.map((author, i) => {
return (
<Fragment key={i}>
{i > 0 && ", "}
{i > 0 && ', '}
{Functions.mlang(author, lang)}
</Fragment>
);

View File

@ -1,13 +1,13 @@
import iconFile from "../../assets/images/icon_book.gif";
import TopBase, { TopBaseProps } from "../lib/TopBase";
import iconFile from '../../assets/images/icon_book.gif';
import TopBase, { TopBaseProps } from '../lib/TopBase';
class BookTop extends TopBase {
constructor(props: TopBaseProps) {
super(props);
this.type = "book";
this.label = "Book";
this.type = 'book';
this.label = 'Book';
this.icon = iconFile;
this.description = "[en]Related book collection.[/en][ja]関連書籍[/ja]";
this.description = '[en]Related book collection.[/en][ja]関連書籍[/ja]';
}
}

View File

@ -1,7 +1,7 @@
import BookAdvancedSearch from "./BookAdvancedSearch";
import BookDetail from "./BookDetail";
import BookList from "./BookList";
import BookTop from "./BookTop";
import BookAdvancedSearch from './BookAdvancedSearch';
import BookDetail from './BookDetail';
import BookList from './BookList';
import BookTop from './BookTop';
const ItemTypeBook = {
Top: BookTop,

View File

@ -1,48 +1,67 @@
import React from "react";
import { ItemConferenceSubTypes } from "../../lib/ItemUtil";
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
import { ItemConferenceSubTypes } from '../../lib/ItemUtil';
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
class ConferenceAdvancedSearch extends AdvancedSearchBase {
constructor(props: AdvancedSearchBaseProps) {
super(props);
this.type = "conference";
this.title = "Conference";
this.type = 'conference';
this.title = 'Conference';
const now = new Date();
const year = String(now.getFullYear());
const month = String(now.getMonth() + 1);
const mday = String(now.getDate());
this.state.values["title"] = "";
this.state.values["presentation_type"] = "";
this.state.values["author"] = "";
this.state.values["conference_from_year"] = year;
this.state.values["conference_from_month"] = month;
this.state.values["conference_from_mday"] = mday;
this.state.values["conference_to_year"] = year;
this.state.values["conference_to_month"] = month;
this.state.values["conference_to_mday"] = mday;
this.setIgnoreKey("conference_from_year");
this.setIgnoreKey("conference_from_month");
this.setIgnoreKey("conference_from_mday");
this.setIgnoreKey("conference_to_year");
this.setIgnoreKey("conference_to_month");
this.setIgnoreKey("conference_to_mday");
this.state.values.title = '';
this.state.values.presentation_type = '';
this.state.values.author = '';
this.state.values.conference_from_year = year;
this.state.values.conference_from_month = month;
this.state.values.conference_from_mday = mday;
this.state.values.conference_to_year = year;
this.state.values.conference_to_month = month;
this.state.values.conference_to_mday = mday;
this.setIgnoreKey('conference_from_year');
this.setIgnoreKey('conference_from_month');
this.setIgnoreKey('conference_from_mday');
this.setIgnoreKey('conference_to_year');
this.setIgnoreKey('conference_to_month');
this.setIgnoreKey('conference_to_mday');
}
renderDate() {
return (
<>
<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>
<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() {
const rows = [
{ label: "[en]Presentation Title[/en][ja]発表議題[/ja]", value: this.renderFieldInputText("title", 50) },
{ label: "[en]Presentation Type[/en][ja]発表資料ファイル形式[/ja]", value: this.renderFieldSelect("presentation_type", ItemConferenceSubTypes) },
{ label: "[en]Author[/en][ja]発表者[/ja]", value: this.renderFieldInputText("author", 50) },
{ label: "[en]Date[/en][ja]日付[/ja]", value: this.renderDate() },
{
label: '[en]Presentation Title[/en][ja]発表議題[/ja]',
value: this.renderFieldInputText('title', 50),
},
{
label: '[en]Presentation Type[/en][ja]発表資料ファイル形式[/ja]',
value: this.renderFieldSelect('presentation_type', ItemConferenceSubTypes),
},
{ label: '[en]Author[/en][ja]発表者[/ja]', value: this.renderFieldInputText('author', 50) },
{ label: '[en]Date[/en][ja]日付[/ja]', value: this.renderDate() },
];
return rows;
}

View File

@ -1,33 +1,91 @@
import React from "react";
import Functions from "../../../functions";
import { ItemConference } from "../../lib/ItemUtil";
import DetailBase from "../lib/DetailBase";
import ItemTypeField from "../lib/field";
import ConferenceUtil from "./ConferenceUtil";
import Functions from '../../../functions';
import { ItemConference } from '../../lib/ItemUtil';
import DetailBase from '../lib/DetailBase';
import ItemTypeField from '../lib/field';
import ConferenceUtil from './ConferenceUtil';
class ConferenceDetail extends DetailBase {
getFields() {
const { lang, type } = this.props;
const item = this.props.item as ItemConference;
return [
{ 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]Place[/en][ja]開催地[/ja]", value: item.place },
{ 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]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]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} 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: "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: '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]Place[/en][ja]開催地[/ja]', value: item.place },
{
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]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} />,
},
];
}
}

View File

@ -1,15 +1,16 @@
import React, { Fragment } from "react";
import { Link } from "react-router-dom";
import Functions from "../../../functions";
import iconFile from "../../assets/images/icon_conference.gif";
import { ItemConference } from "../../lib/ItemUtil";
import ListBase, { ListBaseProps } from "../lib/ListBase";
import ConferenceUtil from "./ConferenceUtil";
import React from 'react';
import { Link } from 'react-router-dom';
import Functions from '../../../functions';
import iconFile from '../../assets/images/icon_conference.gif';
import { ItemConference } from '../../lib/ItemUtil';
import ListBase, { ListBaseProps } from '../lib/ListBase';
import ConferenceUtil from './ConferenceUtil';
class ConferenceList extends ListBase {
constructor(props: ListBaseProps) {
super(props);
this.label = "Conference";
this.label = 'Conference';
this.icon = iconFile;
}
@ -18,17 +19,18 @@ class ConferenceList extends ListBase {
const item = this.props.item as ItemConference;
const authors = item.author.map((author, i) => {
return (
<Fragment key={i}>
{i > 0 && ", "}
<React.Fragment key={i}>
{i > 0 && ', '}
{Functions.mlang(author, lang)}
</Fragment>
</React.Fragment>
);
});
return (
<>
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
<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}
</>
);

View File

@ -1,14 +1,14 @@
import iconFile from "../../assets/images/icon_conference.gif";
import { ItemConferenceSubTypes } from "../../lib/ItemUtil";
import TopBase, { TopBaseProps } from "../lib/TopBase";
import iconFile from '../../assets/images/icon_conference.gif';
import { ItemConferenceSubTypes } from '../../lib/ItemUtil';
import TopBase, { TopBaseProps } from '../lib/TopBase';
class ConferenceTop extends TopBase {
constructor(props: TopBaseProps) {
super(props);
this.type = "conference";
this.label = "Conference";
this.type = 'conference';
this.label = 'Conference';
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;
}
}

View File

@ -1,6 +1,6 @@
import React from "react";
import { MultiLang } from "../../../config";
import { ItemConference, ItemConferenceSubType, ItemConferenceSubTypes } from "../../lib/ItemUtil";
import React from 'react';
import { MultiLang } from '../../../config';
import { ItemConference, ItemConferenceSubType, ItemConferenceSubTypes } from '../../lib/ItemUtil';
interface PresentationTypeProps {
lang: MultiLang;
@ -12,7 +12,7 @@ const PresentationType: React.FC<PresentationTypeProps> = (props: PresentationTy
const subtype = ItemConferenceSubTypes.find((value) => {
return value.type === type;
});
if (typeof subtype === "undefined") {
if (typeof subtype === 'undefined') {
return null;
}
return <span>{subtype.label}</span>;
@ -25,9 +25,34 @@ interface ConferenceDateProps {
const ConferenceDate: React.FC<ConferenceDateProps> = (props: ConferenceDateProps) => {
const { item } = props;
const monthStr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const from = "From: " + monthStr[item.conference_from_month - 1] + " " + item.conference_from_mday + ", " + item.conference_from_year;
const to = "To: " + monthStr[item.conference_to_month - 1] + " " + item.conference_to_mday + ", " + item.conference_to_year;
const monthStr = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const from =
'From: ' +
monthStr[item.conference_from_month - 1] +
' ' +
item.conference_from_mday +
', ' +
item.conference_from_year;
const to =
'To: ' +
monthStr[item.conference_to_month - 1] +
' ' +
item.conference_to_mday +
', ' +
item.conference_to_year;
return (
<span>
{from} {to}

View File

@ -1,7 +1,7 @@
import ConferenceAdvancedSearch from "./ConferenceAdvancedSearch";
import ConferenceDetail from "./ConferenceDetail";
import ConferenceList from "./ConferenceList";
import ConferenceTop from "./ConferenceTop";
import ConferenceAdvancedSearch from './ConferenceAdvancedSearch';
import ConferenceDetail from './ConferenceDetail';
import ConferenceList from './ConferenceList';
import ConferenceTop from './ConferenceTop';
const ItemTypeConference = {
Top: ConferenceTop,

View File

@ -1,42 +1,68 @@
import { ItemDataSubTypes } from "../../lib/ItemUtil";
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
import { ItemDataSubTypes } from '../../lib/ItemUtil';
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
class DataAdvancedSearch extends AdvancedSearchBase {
constructor(props: AdvancedSearchBaseProps) {
super(props);
this.type = "data";
this.title = "Data";
this.type = 'data';
this.title = 'Data';
const now = new Date();
const year = String(now.getFullYear());
const month = String(now.getMonth() + 1);
const mday = String(now.getDate());
this.state.values["title"] = "";
this.state.values["keyword"] = "";
this.state.values["description"] = "";
this.state.values["doi"] = "";
this.state.values["data_type"] = "";
this.state.values["experimenter"] = "";
this.state.values["publication_year"] = year;
this.state.values["publication_month"] = month;
this.state.values["publication_mday"] = mday;
this.state.values["file.preview.caption"] = "";
this.state.values["file.data_file.original_file_name"] = "";
this.setIgnoreKey("publication_year");
this.setIgnoreKey("publication_month");
this.setIgnoreKey("publication_mday");
this.state.values.title = '';
this.state.values.keyword = '';
this.state.values.description = '';
this.state.values.doi = '';
this.state.values.data_type = '';
this.state.values.experimenter = '';
this.state.values.publication_year = year;
this.state.values.publication_month = month;
this.state.values.publication_mday = mday;
this.state.values['file.preview.caption'] = '';
this.state.values['file.data_file.original_file_name'] = '';
this.setIgnoreKey('publication_year');
this.setIgnoreKey('publication_month');
this.setIgnoreKey('publication_mday');
}
getRows() {
const rows = [
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 50) },
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: this.renderFieldInputText("keyword", 50) },
{ label: "[en]Description[/en][ja]概要[/ja]", value: this.renderFieldInputText("description", 50) },
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
{ label: "[en]Data Type[/en][ja]データタイプ[/ja]", value: this.renderFieldSelect("data_type", ItemDataSubTypes) },
{ label: "[en]Experimenter[/en][ja]実験者[/ja]", value: this.renderFieldInputText("experimenter", 50) },
{ label: "[en]Date[/en][ja]日付[/ja]", value: this.renderFieldDate("", "publication_year", "publication_month", "publication_mday") },
{ label: "[en]Caption[/en][ja]キャプション[/ja]", value: this.renderFieldInputText("file.preview.caption", 50) },
{ label: "[en]Data File[/en][ja]データファイル[/ja]", value: this.renderFieldInputText("file.data_file.original_file_name", 50) },
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) },
{
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
value: this.renderFieldInputText('keyword', 50),
},
{
label: '[en]Description[/en][ja]概要[/ja]',
value: this.renderFieldInputText('description', 50),
},
{ label: 'ID', value: this.renderFieldInputText('doi', 50) },
{
label: '[en]Data Type[/en][ja]データタイプ[/ja]',
value: this.renderFieldSelect('data_type', ItemDataSubTypes),
},
{
label: '[en]Experimenter[/en][ja]実験者[/ja]',
value: this.renderFieldInputText('experimenter', 50),
},
{
label: '[en]Date[/en][ja]日付[/ja]',
value: this.renderFieldDate(
'',
'publication_year',
'publication_month',
'publication_mday',
),
},
{
label: '[en]Caption[/en][ja]キャプション[/ja]',
value: this.renderFieldInputText('file.preview.caption', 50),
},
{
label: '[en]Data File[/en][ja]データファイル[/ja]',
value: this.renderFieldInputText('file.data_file.original_file_name', 50),
},
];
return rows;
}

View File

@ -1,39 +1,113 @@
import React from "react";
import Functions from "../../../functions";
import ItemUtil, { ItemData } from "../../lib/ItemUtil";
import DetailBase from "../lib/DetailBase";
import ItemTypeField from "../lib/field";
import SimPFLinkIcon from "../lib/field/SimPFLinkIcon";
import DataUtil from "./DataUtil";
import Functions from '../../../functions';
import ItemUtil, { ItemData } from '../../lib/ItemUtil';
import DetailBase from '../lib/DetailBase';
import ItemTypeField from '../lib/field';
import SimPFLinkIcon from '../lib/field/SimPFLinkIcon';
import DataUtil from './DataUtil';
class DataDetail extends DetailBase {
getFields() {
const { lang, type } = this.props;
const item = this.props.item as ItemData;
const fields = [
{ 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]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]Date[/en][ja]日付[/ja]", value: <ItemTypeField.PublicationDate 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.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]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} 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: "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} /> },
{ 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]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]Date[/en][ja]日付[/ja]',
value: (
<ItemTypeField.PublicationDate
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);
if (simpfLinkUrl !== "") {
const field = { label: "Online Simulation", value: <SimPFLinkIcon lang={lang} url={simpfLinkUrl} isDetail={true} /> };
if (simpfLinkUrl !== '') {
const field = {
label: 'Online Simulation',
value: <SimPFLinkIcon lang={lang} url={simpfLinkUrl} isDetail={true} />,
};
fields.splice(14, 0, field);
}
return fields;

View File

@ -1,14 +1,15 @@
import React, { Fragment } from "react";
import { Link } from "react-router-dom";
import Functions from "../../../functions";
import iconFile from "../../assets/images/icon_data.gif";
import { ItemData } from "../../lib/ItemUtil";
import ListBase, { ListBaseProps } from "../lib/ListBase";
import React from 'react';
import { Link } from 'react-router-dom';
import Functions from '../../../functions';
import iconFile from '../../assets/images/icon_data.gif';
import { ItemData } from '../../lib/ItemUtil';
import ListBase, { ListBaseProps } from '../lib/ListBase';
class DataList extends ListBase {
constructor(props: ListBaseProps) {
super(props);
this.label = "Data";
this.label = 'Data';
this.icon = iconFile;
}
@ -17,10 +18,10 @@ class DataList extends ListBase {
const item = this.props.item as ItemData;
const authors = item.experimenter.map((author, i) => {
return (
<Fragment key={i}>
{i > 0 && ", "}
<React.Fragment key={i}>
{i > 0 && ', '}
{Functions.mlang(author, lang)}
</Fragment>
</React.Fragment>
);
});
return (

View File

@ -1,14 +1,15 @@
import iconFile from "../../assets/images/icon_data.gif";
import { ItemDataSubTypes } from "../../lib/ItemUtil";
import TopBase, { TopBaseProps } from "../lib/TopBase";
import iconFile from '../../assets/images/icon_data.gif';
import { ItemDataSubTypes } from '../../lib/ItemUtil';
import TopBase, { TopBaseProps } from '../lib/TopBase';
class DataTop extends TopBase {
constructor(props: TopBaseProps) {
super(props);
this.type = "data";
this.label = "Data";
this.type = 'data';
this.label = 'Data';
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;
}
}

View File

@ -1,6 +1,6 @@
import React from "react";
import { MultiLang } from "../../../config";
import { ItemDataSubType, ItemDataSubTypes } from "../../lib/ItemUtil";
import React from 'react';
import { MultiLang } from '../../../config';
import { ItemDataSubType, ItemDataSubTypes } from '../../lib/ItemUtil';
interface DataTypeProps {
lang: MultiLang;
@ -12,7 +12,7 @@ const DataType: React.FC<DataTypeProps> = (props: DataTypeProps) => {
const subtype = ItemDataSubTypes.find((value) => {
return value.type === type;
});
if (typeof subtype === "undefined") {
if (typeof subtype === 'undefined') {
return null;
}
return <span>{subtype.label}</span>;

View File

@ -1,7 +1,7 @@
import DataAdvancedSearch from "./DataAdvancedSearch";
import DataDetail from "./DataDetail";
import DataList from "./DataList";
import DataTop from "./DataTop";
import DataAdvancedSearch from './DataAdvancedSearch';
import DataDetail from './DataDetail';
import DataList from './DataList';
import DataTop from './DataTop';
const ItemTypeData = {
Top: DataTop,

View File

@ -1,26 +1,41 @@
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
class FilesAdvancedSearch extends AdvancedSearchBase {
constructor(props: AdvancedSearchBaseProps) {
super(props);
this.type = "files";
this.title = "Files";
this.state.values["title"] = "";
this.state.values["data_file_name"] = "";
this.state.values["data_file_mimetype"] = "";
this.state.values["data_file_filetype"] = "";
this.state.values["keyword"] = "";
this.state.values["description"] = "";
this.type = 'files';
this.title = 'Files';
this.state.values.title = '';
this.state.values.data_file_name = '';
this.state.values.data_file_mimetype = '';
this.state.values.data_file_filetype = '';
this.state.values.keyword = '';
this.state.values.description = '';
}
getRows() {
const rows = [
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 50) },
{ label: "- [en]File Name[/en][ja]ファイル名[/ja]", value: this.renderFieldInputText("data_file_name", 50) },
{ label: "- [en]MIME Type[/en][ja]MIMEタイプ[/ja]", value: this.renderFieldInputText("data_file_mimetype", 50) },
{ label: "- [en]File Type[/en][ja]ファイルタイプ[/ja]", value: this.renderFieldInputText("data_file_filetype", 20) },
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: this.renderFieldInputText("keyword", 50) },
{ label: "[en]Description[/en][ja]概要[/ja]", value: this.renderFieldInputText("description", 50) },
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) },
{
label: '- [en]File Name[/en][ja]ファイル名[/ja]',
value: this.renderFieldInputText('data_file_name', 50),
},
{
label: '- [en]MIME Type[/en][ja]MIMEタイプ[/ja]',
value: this.renderFieldInputText('data_file_mimetype', 50),
},
{
label: '- [en]File Type[/en][ja]ファイルタイプ[/ja]',
value: this.renderFieldInputText('data_file_filetype', 20),
},
{
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
value: this.renderFieldInputText('keyword', 50),
},
{
label: '[en]Description[/en][ja]概要[/ja]',
value: this.renderFieldInputText('description', 50),
},
];
return rows;
}

View File

@ -1,30 +1,61 @@
import React from "react";
import Functions from "../../../functions";
import { ItemFiles } from "../../lib/ItemUtil";
import DetailBase from "../lib/DetailBase";
import ItemTypeField from "../lib/field";
import Functions from '../../../functions';
import { ItemFiles } from '../../lib/ItemUtil';
import DetailBase from '../lib/DetailBase';
import ItemTypeField from '../lib/field';
class FilesDetail extends DetailBase {
getFields() {
const { lang, type } = this.props;
const item = this.props.item as ItemFiles;
return [
{ 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]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]Data File[/en][ja]データファイル[/ja]", value: <ItemTypeField.ItemFile lang={lang} file={item.file} ftype="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} /> },
{ 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]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 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} />,
},
];
}
}

View File

@ -1,15 +1,14 @@
import React from "react";
import { Link } from "react-router-dom";
import Functions from "../../../functions";
import iconFile from "../../assets/images/icon_files.gif";
import { ItemFiles } from "../../lib/ItemUtil";
import Contributer from "../lib/field/Contributer";
import ListBase, { ListBaseProps } from "../lib/ListBase";
import { Link } from 'react-router-dom';
import Functions from '../../../functions';
import iconFile from '../../assets/images/icon_files.gif';
import { ItemFiles } from '../../lib/ItemUtil';
import ListBase, { ListBaseProps } from '../lib/ListBase';
import Contributor from '../lib/field/Contributor';
class FilesList extends ListBase {
constructor(props: ListBaseProps) {
super(props);
this.label = "Files";
this.label = 'Files';
this.icon = iconFile;
}
@ -20,7 +19,7 @@ class FilesList extends ListBase {
<>
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>
<br />
<Contributer lang={lang} uname={item.uname} name={item.name} />
<Contributor lang={lang} uname={item.uname} name={item.name} />
<br />
{item.data_file_mimetype}
</>

View File

@ -1,14 +1,14 @@
import iconFile from "../../assets/images/icon_files.gif";
import { ItemFilesSubTypes } from "../../lib/ItemUtil";
import TopBase, { TopBaseProps } from "../lib/TopBase";
import iconFile from '../../assets/images/icon_files.gif';
import { ItemFilesSubTypes } from '../../lib/ItemUtil';
import TopBase, { TopBaseProps } from '../lib/TopBase';
class FilesTop extends TopBase {
constructor(props: TopBaseProps) {
super(props);
this.type = "files";
this.label = "Files";
this.type = 'files';
this.label = 'Files';
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;
}
}

View File

@ -1,7 +1,7 @@
import FilesAdvancedSearch from "./FilesAdvancedSearch";
import FilesDetail from "./FilesDetail";
import FilesList from "./FilesList";
import FilesTop from "./FilesTop";
import FilesAdvancedSearch from './FilesAdvancedSearch';
import FilesDetail from './FilesDetail';
import FilesList from './FilesList';
import FilesTop from './FilesTop';
const ItemTypeFiles = {
Top: FilesTop,

View File

@ -1,7 +1,21 @@
import React from 'react';
import { MultiLang, BrainAtlasType } from '../../config';
import { BrainAtlasType, MultiLang } from '../../config';
import AdvancedSearchQuery from '../lib/AdvancedSearchQuery';
import { Item, ItemBinder, ItemBook, ItemConference, ItemData, ItemFiles, ItemModel, ItemPaper, ItemPresentation, ItemSimulator, ItemStimulus, ItemTool, ItemUrl, ItemMemo } from '../lib/ItemUtil';
import {
Item,
ItemBinder,
ItemBook,
ItemConference,
ItemData,
ItemFiles,
ItemMemo,
ItemModel,
ItemPaper,
ItemPresentation,
ItemSimulator,
ItemStimulus,
ItemTool,
ItemUrl,
} from '../lib/ItemUtil';
import ItemTypeBinder from './binder';
import ItemTypeBook from './book';
import ItemTypeConference from './conference';
@ -53,7 +67,7 @@ const Top = (props: TopProps) => {
default:
return null;
}
}
};
interface ListProps {
lang: MultiLang;
@ -92,7 +106,7 @@ const List = (props: ListProps) => {
default:
return null;
}
}
};
interface DetailProps {
lang: MultiLang;
@ -119,7 +133,9 @@ const Detail = (props: DetailProps) => {
case 'xnppaper':
return <ItemTypePaper.Detail lang={lang} item={item as ItemPaper} type={type} />;
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':
return <ItemTypeSimulator.Detail lang={lang} item={item as ItemSimulator} type={type} />;
case 'xnpstimulus':
@ -131,7 +147,7 @@ const Detail = (props: DetailProps) => {
default:
return null;
}
}
};
interface AdvancedSearchProps {
lang: MultiLang;
@ -170,13 +186,13 @@ const AdvancedSearch = (props: AdvancedSearchProps) => {
default:
return null;
}
}
};
const ItemType = {
Top,
List,
Detail,
AdvancedSearch
}
AdvancedSearch,
};
export default ItemType;

View File

@ -1,8 +1,8 @@
import React, { ChangeEvent } from "react";
import { MultiLang } from "../../../config";
import Functions from "../../../functions";
import AdvancedSearchQuery from "../../lib/AdvancedSearchQuery";
import { ItemSubTypes } from "../../lib/ItemUtil";
import React from 'react';
import { MultiLang } from '../../../config';
import Functions from '../../../functions';
import AdvancedSearchQuery from '../../lib/AdvancedSearchQuery';
import { ItemSubTypesAll } from '../../lib/ItemUtil';
export interface AdvancedSearchBaseProps {
lang: MultiLang;
@ -11,12 +11,12 @@ export interface AdvancedSearchBaseProps {
interface State {
show: boolean;
values: any;
values: Record<string, string>;
}
class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State> {
protected type: string = "base";
protected title: string = "Base";
protected type = 'base';
protected title = 'Base';
protected query: AdvancedSearchQuery;
protected ignoreKeys: string[] = [];
@ -55,13 +55,13 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
}
updateField(key: string, value: string) {
let values = Object.assign({}, this.state.values);
const values = Object.assign({}, this.state.values);
values[key] = value;
this.updateQuery(key, value);
this.setState({ values });
}
handleChangeTitleCheck(e: ChangeEvent<HTMLInputElement>) {
handleChangeTitleCheck(e: React.ChangeEvent<HTMLInputElement>) {
const show = e.target.checked;
if (show) {
Object.keys(this.state.values).forEach((key) => {
@ -79,14 +79,22 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
}
renderFieldInputText(key: string, size: number) {
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
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>) {
const onChange = (e: ChangeEvent<HTMLSelectElement>) => {
renderFieldSelect(key: string, values: ItemSubTypesAll) {
const onChange: React.ChangeEventHandler<HTMLSelectElement> = (e) => {
this.updateField(key, e.target.value);
};
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) {
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
if (e.target.checked) {
this.deleteIgnoreKey(keyYear);
keyMonth !== "" && this.deleteIgnoreKey(keyMonth);
keyMday !== "" && this.deleteIgnoreKey(keyMday);
keyMonth !== '' && this.deleteIgnoreKey(keyMonth);
keyMday !== '' && this.deleteIgnoreKey(keyMday);
} else {
this.setIgnoreKey(keyYear);
keyMonth !== "" && this.setIgnoreKey(keyMonth);
keyMday !== "" && this.setIgnoreKey(keyMday);
keyMonth !== '' && this.setIgnoreKey(keyMonth);
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) => {
return (
<option key={i} value={i + 1}>
@ -124,29 +145,40 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
</option>
);
});
let mdayOptions: JSX.Element[] = [];
const mdayOptions: JSX.Element[] = [];
for (let i = 1; i <= 31; i++) {
mdayOptions.push(
<option key={i} value={i}>
{i}
</option>
</option>,
);
}
return (
<div className="fieldDate">
<input type="checkbox" onChange={onChange} />
{label.length !== 0 && <label className="fieldDateLabel">{label}</label>}
{keyMonth !== "" && (
<select value={this.state.values[keyMonth]} onChange={(e) => this.updateField(keyMonth, e.target.value)}>
{keyMonth !== '' && (
<select
value={this.state.values[keyMonth]}
onChange={(e) => this.updateField(keyMonth, e.target.value)}
>
{monthOptions}
</select>
)}
{keyMday !== "" && (
<select value={this.state.values[keyMday]} onChange={(e) => this.updateField(keyMday, e.target.value)}>
{keyMday !== '' && (
<select
value={this.state.values[keyMday]}
onChange={(e) => this.updateField(keyMday, e.target.value)}
>
{mdayOptions}
</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>
);
}
@ -158,7 +190,7 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
}
const rows = this.getRows();
const fields = rows.map((value, idx) => {
const evenodd = idx % 2 === 0 ? "even" : "odd";
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
return (
<tr key={idx}>
<td className="head">{Functions.mlang(value.label, lang)}</td>
@ -180,7 +212,11 @@ class AdvancedSearchBase extends React.Component<AdvancedSearchBaseProps, State>
<tbody>
<tr>
<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}
</th>
</tr>

View File

@ -1,11 +1,12 @@
import React, { ReactNode } from "react";
import { BrainAtlasType, MultiLang } from "../../../config";
import Functions from "../../../functions";
import { Item } from "../../lib/ItemUtil";
import React from 'react';
import { BrainAtlasType, MultiLang } from '../../../config';
import Functions from '../../../functions';
import { Item } from '../../lib/ItemUtil';
export interface DetailBaseField {
label: string;
value: ReactNode;
value: React.ReactNode;
}
export interface DetailBaseProps {
@ -22,7 +23,7 @@ class DetailBase extends React.Component<DetailBaseProps> {
render() {
const { lang } = this.props;
const elements = this.getFields().map((value, idx) => {
const evenodd = idx % 2 === 0 ? "even" : "odd";
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
return (
<tr key={idx}>
<td className="head">{Functions.mlang(value.label, lang)}</td>

View File

@ -1,7 +1,8 @@
import React from "react";
import { BrainAtlasType, MultiLang } from "../../../config";
import ItemUtil, { Item } from "../../lib/ItemUtil";
import SimPFLinkIcon from "./field/SimPFLinkIcon";
import React from 'react';
import { BrainAtlasType, MultiLang } from '../../../config';
import ItemUtil, { Item } from '../../lib/ItemUtil';
import SimPFLinkIcon from './field/SimPFLinkIcon';
export interface ListBaseProps {
lang: MultiLang;
@ -10,8 +11,8 @@ export interface ListBaseProps {
}
class ListBase extends React.Component<ListBaseProps> {
protected label = "";
protected icon = "";
protected label = '';
protected icon = '';
protected url: string;
protected simpfLinkUrl: string;

View File

@ -1,8 +1,9 @@
import React, { Fragment } from "react";
import { Link } from "react-router-dom";
import { BrainAtlasType, MultiLang } from "../../../config";
import Functions from "../../../functions";
import ItemUtil, { ItemSubTypes } from "../../lib/ItemUtil";
import React from 'react';
import { Link } from 'react-router-dom';
import { BrainAtlasType, MultiLang } from '../../../config';
import Functions from '../../../functions';
import ItemUtil, { ItemSubTypesAll } from '../../lib/ItemUtil';
export interface TopBaseProps {
lang: MultiLang;
@ -10,22 +11,22 @@ export interface TopBaseProps {
}
class TopBase extends React.Component<TopBaseProps> {
protected type: string = "";
protected label: string = "";
protected icon: string = "";
protected description: string = "";
protected subTypes: ItemSubTypes<any> = [];
protected type = '';
protected label = '';
protected icon = '';
protected description = '';
protected subTypes: ItemSubTypesAll = [];
render() {
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 url = ItemUtil.getItemTypeSearchUrl(type, this.type, subtype.type);
return (
<Fragment key={i}>
{i > 0 && " / "}
<React.Fragment key={i}>
{i > 0 && ' / '}
<Link to={url}>{subtype.label}</Link>
</Fragment>
</React.Fragment>
);
});
return (

View File

@ -1,18 +1,19 @@
import React from "react";
import { MultiLang } from "../../../../config";
import React from 'react';
import { MultiLang } from '../../../../config';
interface Props {
lang: MultiLang;
author: string[];
}
const Author: React.FC<Props> = (props: Props) => {
const Author: React.FC<Props> = (props) => {
const { author } = props;
if (author.length === 0) {
return null;
}
const elements = author.map((value, idx) => {
const evenodd = idx % 2 === 0 ? "even" : "odd";
const evenodd = idx % 2 === 0 ? 'even' : 'odd';
return (
<tr key={idx}>
<td className={evenodd}>{value}</td>

View File

@ -1,15 +1,16 @@
import React from "react";
import { MultiLang } from "../../../../config";
import Functions from "../../../../functions";
import { ItemBasicChangeLog } from "../../../lib/ItemUtil";
import DateTime from "./DateTime";
import React from 'react';
import { MultiLang } from '../../../../config';
import Functions from '../../../../functions';
import { ItemBasicChangeLog } from '../../../lib/ItemUtil';
import DateTime from './DateTime';
interface Props {
lang: MultiLang;
changelog: ItemBasicChangeLog[];
}
const ChangeLog: React.FC<Props> = (props: Props) => {
const ChangeLog: React.FC<Props> = (props) => {
const { lang, changelog } = props;
if (changelog.length === 0) {
return null;

View File

@ -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;

View 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;

View File

@ -1,51 +1,57 @@
import React from "react";
import { MultiLang } from "../../../../config";
import React from 'react';
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;
switch (cc) {
case 0:
return "by-nc-nd";
return 'by-nc-nd';
case 1:
return "by-nc-sa";
return 'by-nc-sa';
case 2:
return "by-nc";
return 'by-nc';
case 10:
return "by-nd";
return 'by-nd';
case 11:
return "by-sa";
return 'by-sa';
case 12:
default:
return "by";
return 'by';
}
};
interface Props {
lang: MultiLang;
type: CreativeCommonsType;
ccCommercialUse: number;
ccModification: number;
}
const CreativeCommons: React.FC<Props> = (props: Props) => {
const { type } = props;
const url = "http://creativecommons.org/licenses/" + type + "/4.0/";
const logoUrl = "https://i.creativecommons.org/l/" + type + "/4.0/88x31.png";
const CreativeCommons: React.FC<Props> = (props) => {
const { ccCommercialUse, ccModification } = props;
const type = getCreativeCommonsType(ccCommercialUse, ccModification);
const url = 'http://creativecommons.org/licenses/' + type + '/4.0/';
const logoUrl = 'https://i.creativecommons.org/l/' + type + '/4.0/88x31.png';
const labels = {
by: "Attribution",
nc: "NonCommercial",
nd: "NoDerivatives",
sa: "ShareAlike",
by: 'Attribution',
nc: 'NonCommercial',
nd: 'NoDerivatives',
sa: 'ShareAlike',
};
const label = type
.split("-")
.split('-')
.map((value) => {
const prop = value as "by" | "nc" | "nd" | "sa";
const prop = value as 'by' | 'nc' | 'nd' | 'sa';
return labels[prop];
})
.join("-");
.join('-');
return (
<table style={{ borderCollapse: "separate", borderSpacing: "5px" }}>
<table style={{ borderCollapse: 'separate', borderSpacing: '5px' }}>
<tbody>
<tr>
<td>
@ -54,9 +60,9 @@ const CreativeCommons: React.FC<Props> = (props: Props) => {
</a>
</td>
<td>
This work is licensed under a{" "}
This work is licensed under a{' '}
<a href={url} target="_blank" rel="license noopener noreferrer">
Criative Commons {label} 4.0 International License
Creative Commons {label} 4.0 International License
</a>
.
</td>

View File

@ -1,6 +1,7 @@
import moment from "moment";
import React from "react";
import { MultiLang } from "../../../../config";
import React from 'react';
import moment from 'moment';
import { MultiLang } from '../../../../config';
interface Props {
lang: MultiLang;
@ -8,12 +9,12 @@ interface Props {
onlyDate?: boolean;
}
const DateTime: React.FC<Props> = (props: Props) => {
const DateTime: React.FC<Props> = (props) => {
const { date, onlyDate } = props;
const d = moment(new Date(date * 1000));
let format = "MMM D, Y";
if (typeof onlyDate === "undefined" || !onlyDate) {
format += " HH:mm:ss";
let format = 'MMM D, Y';
if (typeof onlyDate === 'undefined' || !onlyDate) {
format += ' HH:mm:ss';
}
return <span>{d.format(format)}</span>;
};

View File

@ -1,6 +1,7 @@
import React from "react";
import XoopsCode from "../../../../common/lib/XoopsCode";
import { MultiLang } from "../../../../config";
import React from 'react';
import XoopsCode from '../../../../common/lib/XoopsCode';
import { MultiLang } from '../../../../config';
interface Props {
lang: MultiLang;
@ -8,10 +9,10 @@ interface Props {
className?: string;
}
const Description: React.FC<Props> = (props: Props) => {
const Description: React.FC<Props> = (props) => {
const { lang, description, className } = props;
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>;
};

View File

@ -1,8 +1,9 @@
import React from "react";
import { BrainAtlasType, MultiLang } from "../../../../config";
import ItemUtil, { ItemBasicFile } from "../../../lib/ItemUtil";
import styles from "./FileDownloadButton.module.css";
import LicenseAgreementDialog from "./LicenseAgreementDialog";
import React from 'react';
import { BrainAtlasType, MultiLang } from '../../../../config';
import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil';
import styles from './FileDownloadButton.module.css';
import LicenseAgreementDialog from './LicenseAgreementDialog';
interface Props {
lang: MultiLang;
@ -14,44 +15,45 @@ interface Props {
type: BrainAtlasType;
}
interface State {
show: boolean;
}
const FileDownloadButton: React.FC<Props> = (props) => {
const { lang, file, rights, useCc, ccCommercialUse, ccModification, type } = props;
class FileDownloadButton extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
show: false,
};
this.handleClickDownload = this.handleClickDownload.bind(this);
this.unsetShow = this.unsetShow.bind(this);
}
const [show, setShow] = React.useState<boolean>(false);
handleClickDownload(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
if (this.props.rights !== "") {
const handleClickDownload: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
if (rights !== '') {
e.stopPropagation();
e.preventDefault();
this.setState({ show: true });
}
setShow(true);
}
};
unsetShow() {
this.setState({ show: false });
}
render() {
const { lang, file, rights, useCc, ccCommercialUse, ccModification, type } = this.props;
const url = ItemUtil.getFileUrl(type, this.props.file);
const url = ItemUtil.getFileUrl(type, file);
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
</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;

View File

@ -1,16 +1,17 @@
import React from "react";
import { MultiLang } from "../../../../config";
import React from 'react';
import { MultiLang } from '../../../../config';
interface Props {
lang: MultiLang;
size: number;
}
const FileSize: React.FC<Props> = (props: Props) => {
const FileSize: React.FC<Props> = (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 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>;
};

View File

@ -1,17 +1,18 @@
import React from "react";
import { MultiLang } from "../../../../config";
import React from 'react';
import { MultiLang } from '../../../../config';
interface Props {
lang: MultiLang;
keyword: string[];
}
const FreeKeyword: React.FC<Props> = (props: Props) => {
const FreeKeyword: React.FC<Props> = (props) => {
const { keyword } = props;
if (keyword.length === 0) {
return null;
}
const label = keyword.join(", ");
const label = keyword.join(', ');
return <span>{label}</span>;
};

View File

@ -1,15 +1,16 @@
import React from "react";
import { BrainAtlasType, MultiLang } from "../../../../config";
import Functions from "../../../../functions";
import { ItemBasicFile } from "../../../lib/ItemUtil";
import DateTime from "./DateTime";
import FileDownloadButton from "./FileDownloadButton";
import FileSize from "./FileSize";
import React from 'react';
import { BrainAtlasType, MultiLang } from '../../../../config';
import Functions from '../../../../functions';
import { ItemBasicFile } from '../../../lib/ItemUtil';
import DateTime from './DateTime';
import FileDownloadButton from './FileDownloadButton';
import FileSize from './FileSize';
interface Props {
lang: MultiLang;
file: ItemBasicFile[];
ftype: string;
fileType: string;
rights?: string;
useCc?: number;
ccCommercialUse?: number;
@ -18,17 +19,24 @@ interface Props {
type: BrainAtlasType;
}
const ItemFile: React.FC<Props> = (props: Props) => {
const { lang, file, ftype, type } = props;
const rights = typeof props.rights === "undefined" ? "" : props.rights;
const useCc = typeof props.useCc === "undefined" ? 0 : props.useCc;
const ccCommercialUse = typeof props.ccCommercialUse === "undefined" ? 0 : props.ccCommercialUse;
const ccModification = typeof props.ccModification === "undefined" ? 0 : props.ccModification;
const downloadLimit = typeof props.downloadLimit === "undefined" ? 0 : props.downloadLimit;
const ItemFile: React.FC<Props> = (props) => {
const {
lang,
file,
fileType,
type,
rights = '',
useCc = 0,
ccCommercialUse = 0,
ccModification = 0,
downloadLimit = 0,
} = props;
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;
}
const date = new Date(data.timestamp);
@ -42,7 +50,19 @@ const ItemFile: React.FC<Props> = (props: Props) => {
<tr>
<td>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>
<td>Size</td>
@ -60,7 +80,9 @@ const ItemFile: React.FC<Props> = (props: Props) => {
</table>
{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>

View File

@ -1,9 +1,10 @@
import React from "react";
import { Link } from "react-router-dom";
import { BrainAtlasType, MultiLang } from "../../../../config";
import Functions from "../../../../functions";
import IndexUtil from "../../../lib/IndexUtil";
import { ItemBasicIndex } from "../../../lib/ItemUtil";
import React from 'react';
import { Link } from 'react-router-dom';
import { BrainAtlasType, MultiLang } from '../../../../config';
import Functions from '../../../../functions';
import IndexUtil from '../../../lib/IndexUtil';
import { ItemBasicIndex } from '../../../lib/ItemUtil';
interface Props {
lang: MultiLang;
@ -11,13 +12,13 @@ interface Props {
type: BrainAtlasType;
}
const ItemIndex: React.FC<Props> = (props: Props) => {
const ItemIndex: React.FC<Props> = (props) => {
const { lang, index, type } = props;
if (index.length === 0) {
return null;
}
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);
return (
<tr key={value.index_id}>

View File

@ -1,30 +1,30 @@
import React from "react";
import { MultiLang } from "../../../../config";
import Functions from "../../../../functions";
import { ItemBasicLang } from "../../../lib/ItemUtil";
import React from 'react';
import { MultiLang } from '../../../../config';
import Functions from '../../../../functions';
import { ItemBasicLang } from '../../../lib/ItemUtil';
interface Props {
lang: MultiLang;
itemLang: ItemBasicLang;
}
const Language: React.FC<Props> = (props: Props) => {
const Language: React.FC<Props> = (props) => {
const { lang, itemLang } = props;
const langStr = {
eng: "[en]English[/en][ja]英語[/ja]",
jpn: "[en]Japanese[/en][ja]日本語[/ja]",
fra: "[en]French[/en][ja]フランス語[/ja]",
deu: "[en]German[/en][ja]ドイツ語[/ja]",
esl: "[en]Spanish[/en][ja]スペイン語[/ja]",
ita: "[en]Italian[/en][ja]イタリア語[/ja]",
dut: "[en]Dutch[/en][ja]オランダ語[/ja]",
sve: "[en]Swedish[/en][ja]スウェーデン語[/ja]",
nor: "[en]Norwegian[/en][ja]ノルウェー語[/ja]",
dan: "[en]Danish[/en][ja]デンマーク語[/ja]",
fin: "[en]Finnish[/en][ja]フィンランド語[/ja]",
por: "[en]Portuguese[/en][ja]ポルトガル語[/ja]",
chi: "[en]Chinese[/en][ja]中国語[/ja]",
kor: "[en]Korean[/en][ja]韓国語[/ja]",
eng: '[en]English[/en][ja]英語[/ja]',
jpn: '[en]Japanese[/en][ja]日本語[/ja]',
fra: '[en]French[/en][ja]フランス語[/ja]',
deu: '[en]German[/en][ja]ドイツ語[/ja]',
esl: '[en]Spanish[/en][ja]スペイン語[/ja]',
ita: '[en]Italian[/en][ja]イタリア語[/ja]',
dut: '[en]Dutch[/en][ja]オランダ語[/ja]',
sve: '[en]Swedish[/en][ja]スウェーデン語[/ja]',
nor: '[en]Norwegian[/en][ja]ノルウェー語[/ja]',
dan: '[en]Danish[/en][ja]デンマーク語[/ja]',
fin: '[en]Finnish[/en][ja]フィンランド語[/ja]',
por: '[en]Portuguese[/en][ja]ポルトガル語[/ja]',
chi: '[en]Chinese[/en][ja]中国語[/ja]',
kor: '[en]Korean[/en][ja]韓国語[/ja]',
};
if (!(itemLang in langStr)) {
return null;

View File

@ -1,12 +1,14 @@
import React, { ChangeEvent, MouseEvent } from "react";
import { Modal } from "react-overlays";
import { BrainAtlasType, MultiLang } from "../../../../config";
import Functions from "../../../../functions";
import ItemUtil, { ItemBasicFile } from "../../../lib/ItemUtil";
import DateTime from "./DateTime";
import FileSize from "./FileSize";
import styles from "./LicenseAgreementDialog.module.css";
import Rights from "./Rights";
import React from 'react';
import { Modal } from 'react-overlays';
import { RenderModalBackdropProps } from 'react-overlays/cjs/Modal';
import { BrainAtlasType, MultiLang } from '../../../../config';
import Functions from '../../../../functions';
import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil';
import DateTime from './DateTime';
import FileSize from './FileSize';
import styles from './LicenseAgreementDialog.module.css';
import Rights from './Rights';
interface Props {
lang: MultiLang;
@ -20,72 +22,67 @@ interface Props {
type: BrainAtlasType;
}
interface State {
show: boolean;
disabled: boolean;
}
const LicenseAgreementDialog: React.FC<Props> = (props) => {
const { lang, file, rights, useCc, ccCommercialUse, ccModification, show, unsetShow, type } =
props;
class LicenseAgreementDialog extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
show: props.show,
disabled: false,
const [isShow, setIsShow] = React.useState<boolean>(show);
const [disabled, setDisabled] = React.useState<boolean>(false);
React.useEffect(() => {
if (show) {
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) {
if (nextProps.show && !prevState.show) {
return { disabled: true, show: nextProps.show };
}
return null;
}
const handleClickDownload: React.MouseEventHandler<HTMLButtonElement> = () => {
unsetShow();
setIsShow(false);
};
handleChangeCheckbox(e: ChangeEvent<HTMLInputElement>) {
const disabled = e.target.value === "0";
this.setState({ disabled });
}
const handleClickCancel = () => {
unsetShow();
setIsShow(false);
};
handleClickDownload(e: MouseEvent<HTMLButtonElement>) {
this.props.unsetShow();
this.setState({ show: false });
}
handleClickCancel() {
this.props.unsetShow();
this.setState({ show: false });
}
renderBackdrop(props: any) {
const renderBackdrop = (props: RenderModalBackdropProps) => {
return <div className={styles.overlay} {...props} />;
}
};
render() {
const { lang, type } = this.props;
const date = new Date(this.props.file.timestamp);
const date = new Date(file.timestamp);
const timestamp = Math.floor(date.valueOf() / 1000);
const url = ItemUtil.getFileUrl(type, this.props.file);
const url = ItemUtil.getFileUrl(type, file);
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>
{Functions.mlang("[en]Download file information[/en][ja]ダウンロードするファイルの情報[/ja]", lang)}
{Functions.mlang(
'[en]Download file information[/en][ja]ダウンロードするファイルの情報[/ja]',
lang,
)}
<div className={styles.box}>
{this.props.file.original_file_name}
{file.original_file_name}
<br />
<table>
<tbody>
<tr>
<td>Type</td>
<td>: {this.props.file.mime_type}</td>
<td>: {file.mime_type}</td>
</tr>
<tr>
<td>Size</td>
<td>
: <FileSize lang={lang} size={this.props.file.file_size} />
: <FileSize lang={lang} size={file.file_size} />
</td>
</tr>
<tr>
@ -100,16 +97,43 @@ class LicenseAgreementDialog extends React.Component<Props, State> {
</div>
<br />
<div>
{Functions.mlang("[en]License agreement[/en][ja]ファイルのライセンス[/ja]", lang)}
{Functions.mlang('[en]License agreement[/en][ja]ファイルのライセンス[/ja]', lang)}
<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>
<Rights lang={lang} rights={this.props.rights} useCc={this.props.useCc} ccCommercialUse={this.props.ccCommercialUse} ccModification={this.props.ccModification} />
<input type="radio" name="radio_license" value="1" onChange={this.handleChangeCheckbox} checked={!this.state.disabled} />
{Functions.mlang("[en]I accept the terms in the license agreement.[/en][ja]ライセンスに同意します。[/ja]", lang)}
<Rights
lang={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 />
<input type="radio" name="radio_license" value="0" onChange={this.handleChangeCheckbox} checked={this.state.disabled} />
{Functions.mlang("[en]I do not accept the terms in the license agreement.[/en][ja]ライセンスに同意しません。[/ja]", lang)}
<input
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 />
</div>
</div>
@ -118,19 +142,18 @@ class LicenseAgreementDialog extends React.Component<Props, State> {
<div className={styles.download}>
Acceptance is needed to download this file.
<br />
<a href={url} download={this.props.file.original_file_name}>
<button className="formButton" onClick={this.handleClickDownload} disabled={this.state.disabled}>
<a href={url} download={file.original_file_name}>
<button className="formButton" onClick={handleClickDownload} disabled={disabled}>
Download
</button>
</a>
<button className="formButton" onClick={this.handleClickCancel}>
<button className="formButton" onClick={handleClickCancel}>
Cancel
</button>
</div>
</div>
</Modal>
);
}
}
};
export default LicenseAgreementDialog;

View File

@ -4,7 +4,7 @@
}
.previewBox::after {
content: "";
content: '';
display: block;
clear: both;
}

View File

@ -1,10 +1,12 @@
import React from "react";
import Lightbox from "react-image-lightbox";
import "react-image-lightbox/style.css";
import { BrainAtlasType, MultiLang } from "../../../../config";
import Functions from "../../../../functions";
import ItemUtil, { ItemBasicFile } from "../../../lib/ItemUtil";
import styles from "./Preview.module.css";
import React from 'react';
import Lightbox, { SlideImage } from 'yet-another-react-lightbox';
import { BrainAtlasType, MultiLang } from '../../../../config';
import Functions from '../../../../functions';
import ItemUtil, { ItemBasicFile } from '../../../lib/ItemUtil';
import 'yet-another-react-lightbox/styles.css';
import styles from './Preview.module.css';
interface Props {
lang: MultiLang;
@ -12,34 +14,25 @@ interface Props {
type: BrainAtlasType;
}
interface State {
isOpen: boolean;
imageIndex: number;
}
const Preview: React.FC<Props> = (props) => {
const { lang, file, type } = props;
class Preview extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isOpen: false,
imageIndex: 0,
};
}
const [isOpen, setIsOpen] = React.useState<boolean>(false);
const [imageIndex, setImageIndex] = React.useState<number>(0);
render() {
const { lang, file, type } = this.props;
const data = file.filter((value) => {
return value.file_type_name === "preview";
return value.file_type_name === 'preview';
});
if (data.length === 0) {
return null;
}
let imageUrls: string[] = [];
const slides: SlideImage[] = [];
const previews = data.map((value, idx) => {
const fileUrl = ItemUtil.getFileUrl(type, value);
const previewUrl = ItemUtil.getPreviewFileUrl(type, value);
const caption = Functions.mlang(value.caption, lang);
imageUrls.push(fileUrl);
slides.push({ src: fileUrl });
return (
<figure key={value.file_id} className={styles.preview}>
<a
@ -47,7 +40,8 @@ class Preview extends React.Component<Props, State> {
download={value.original_file_name}
onClick={(e) => {
e.preventDefault();
this.setState({ isOpen: true, imageIndex: idx });
setIsOpen(true);
setImageIndex(idx);
}}
>
<img src={previewUrl} alt={caption} />
@ -56,31 +50,13 @@ class Preview extends React.Component<Props, State> {
</figure>
);
});
const { isOpen, imageIndex } = this.state;
return (
<>
<div className={styles.previewBox}>{previews}</div>
{isOpen && (
<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,
})
}
/>
)}
{isOpen && <Lightbox index={imageIndex} slides={slides} close={() => setIsOpen(false)} />}
</>
);
}
}
};
export default Preview;

View File

@ -1,6 +1,7 @@
import React from "react";
import { MultiLang } from "../../../../config";
import DateTime from "./DateTime";
import React from 'react';
import { MultiLang } from '../../../../config';
import DateTime from './DateTime';
interface Props {
lang: MultiLang;
@ -9,9 +10,9 @@ interface Props {
mday: number;
}
const PublicationDate: React.FC<Props> = (props: Props) => {
const PublicationDate: React.FC<Props> = (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);
return <DateTime lang={lang} date={timestamp} onlyDate={true} />;
};

View File

@ -1,13 +1,14 @@
import React from "react";
import { MultiLang } from "../../../../config";
import Description from "./Description";
import React from 'react';
import { MultiLang } from '../../../../config';
import Description from './Description';
interface Props {
lang: MultiLang;
readme: string;
}
const Readme: React.FC<Props> = (props: Props) => {
const Readme: React.FC<Props> = (props) => {
const { lang, readme } = props;
return <Description lang={lang} description={readme} className="readme" />;
};

View File

@ -1,7 +1,8 @@
import React from "react";
import { BrainAtlasType, MultiLang } from "../../../../config";
import ItemType from "../../../item-type";
import ItemUtil from "../../../lib/ItemUtil";
import React from 'react';
import { BrainAtlasType, MultiLang } from '../../../../config';
import ItemType from '../../../item-type';
import ItemUtil from '../../../lib/ItemUtil';
interface Props {
lang: MultiLang;
@ -9,44 +10,26 @@ interface Props {
type: BrainAtlasType;
}
interface State {
elements: JSX.Element[];
}
const RelatedTo: React.FC<Props> = (props) => {
const { lang, relatedTo, type } = props;
const isMounted = React.useRef<boolean>(false);
class RelatedTo extends React.Component<Props, State> {
private isActive: boolean;
const [elements, setElements] = React.useState<React.ReactNode[]>([]);
constructor(props: Props) {
super(props);
this.state = {
elements: [],
React.useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
this.isActive = false;
}
}, []);
componentDidMount() {
this.isActive = true;
this.updateElements(this.props.relatedTo);
}
componentDidUpdate(prevProps: Props) {
if (JSON.stringify(this.props.relatedTo) !== JSON.stringify(prevProps.relatedTo)) {
this.updateElements(this.props.relatedTo);
}
}
componentWillUnmount() {
this.isActive = false;
}
updateElements(relatedTo: number[]) {
const { lang, type } = this.props;
React.useEffect(() => {
if (relatedTo.length === 0) {
this.setState({ elements: [] });
setElements([]);
} else {
ItemUtil.getList(type, relatedTo, (results) => {
const elements = results.data.map((item, idx) => {
const evenodd = idx % 0 ? "even" : "odd";
const evenodd = idx % 0 ? 'even' : 'odd';
return (
<tr key={item.item_id}>
<td className={evenodd}>
@ -55,15 +38,14 @@ class RelatedTo extends React.Component<Props, State> {
</tr>
);
});
if (this.isActive) {
this.setState({ elements });
if (isMounted.current) {
setElements(elements);
}
});
}
}
}, [lang, relatedTo, type]);
render() {
if (this.state.elements.length === 0) {
if (elements.length === 0) {
return null;
}
return (
@ -72,11 +54,10 @@ class RelatedTo extends React.Component<Props, State> {
<tr>
<th>Item summary</th>
</tr>
{this.state.elements}
{elements}
</tbody>
</table>
);
}
}
};
export default RelatedTo;

View File

@ -1,7 +1,8 @@
import React from "react";
import { MultiLang } from "../../../../config";
import CreativeCommons, { getCreativeCommonsType } from "./CreativeCommons";
import Description from "./Description";
import React from 'react';
import { MultiLang } from '../../../../config';
import CreativeCommons from './CreativeCommons';
import Description from './Description';
interface Props {
lang: MultiLang;
@ -11,13 +12,18 @@ interface Props {
ccModification: number;
}
const Rights: React.FC<Props> = (props: Props) => {
const Rights: React.FC<Props> = (props) => {
const { lang, rights, useCc, ccCommercialUse, ccModification } = props;
if (useCc === 0) {
return <Description lang={lang} description={rights} className="rights" />;
}
const ccType = getCreativeCommonsType(ccCommercialUse, ccModification);
return <CreativeCommons lang={lang} type={ccType} />;
return (
<CreativeCommons
lang={lang}
ccCommercialUse={ccCommercialUse}
ccModification={ccModification}
/>
);
};
export default Rights;

View File

@ -1,6 +1,6 @@
import React from "react";
import { MultiLang } from "../../../../config";
import imageButton from "../../../assets/images/simpf_button.png";
import React from 'react';
import { MultiLang } from '../../../../config';
import imageButton from '../../../assets/images/simpf_button.png';
interface Props {
lang: MultiLang;
@ -8,11 +8,11 @@ interface Props {
isDetail: boolean;
}
const SimPFLinkIcon: React.FC<Props> = (props: Props) => {
const SimPFLinkIcon: React.FC<Props> = (props) => {
const { url, isDetail } = props;
const title = "Online Simulation";
const title = 'Online Simulation';
const size = isDetail ? 64 : 35;
if (url === "") {
if (url === '') {
return null;
}
return (

View File

@ -1,25 +1,25 @@
import Author from "./Author";
import ChangeLog from "./ChangeLog";
import Contributer from "./Contributer";
import CreativeCommons from "./CreativeCommons";
import DateTime from "./DateTime";
import Description from "./Description";
import FileDownloadButton from "./FileDownloadButton";
import FileSize from "./FileSize";
import FreeKeyword from "./FreeKeyword";
import ItemFile from "./ItemFile";
import ItemIndex from "./ItemIndex";
import Language from "./Language";
import Preview from "./Preview";
import PublicationDate from "./PublicationDate";
import Readme from "./Readme";
import RelatedTo from "./RelatedTo";
import Rights from "./Rights";
import Author from './Author';
import ChangeLog from './ChangeLog';
import Contributor from './Contributor';
import CreativeCommons from './CreativeCommons';
import DateTime from './DateTime';
import Description from './Description';
import FileDownloadButton from './FileDownloadButton';
import FileSize from './FileSize';
import FreeKeyword from './FreeKeyword';
import ItemFile from './ItemFile';
import ItemIndex from './ItemIndex';
import Language from './Language';
import Preview from './Preview';
import PublicationDate from './PublicationDate';
import Readme from './Readme';
import RelatedTo from './RelatedTo';
import Rights from './Rights';
const ItemTypeField = {
Author,
ChangeLog,
Contributer,
Contributor,
CreativeCommons,
DateTime,
Description,

View File

@ -1,24 +1,33 @@
import AdvancedSearchBase, { AdvancedSearchBaseProps } from "../lib/AdvancedSearchBase";
import AdvancedSearchBase, { AdvancedSearchBaseProps } from '../lib/AdvancedSearchBase';
class MemoAdvancedSearch extends AdvancedSearchBase {
constructor(props: AdvancedSearchBaseProps) {
super(props);
this.type = "memo";
this.title = "Memo";
this.state.values["title"] = "";
this.state.values["keyword"] = "";
this.state.values["description"] = "";
this.state.values["doi"] = "";
this.state.values["item_link"] = "";
this.type = 'memo';
this.title = 'Memo';
this.state.values.title = '';
this.state.values.keyword = '';
this.state.values.description = '';
this.state.values.doi = '';
this.state.values.item_link = '';
}
getRows() {
const rows = [
{ label: "[en]Title[/en][ja]タイトル[/ja]", value: this.renderFieldInputText("title", 50) },
{ label: "[en]Free Keywords[/en][ja]フリーキーワード[/ja]", value: this.renderFieldInputText("keyword", 50) },
{ label: "[en]Description[/en][ja]概要[/ja]", value: this.renderFieldInputText("description", 50) },
{ label: "ID", value: this.renderFieldInputText("doi", 50) },
{ label: "[en]Item Link[/en][ja]リンク[/ja]", value: this.renderFieldInputText("item_link", 50) },
{ label: '[en]Title[/en][ja]タイトル[/ja]', value: this.renderFieldInputText('title', 50) },
{
label: '[en]Free Keywords[/en][ja]フリーキーワード[/ja]',
value: this.renderFieldInputText('keyword', 50),
},
{
label: '[en]Description[/en][ja]概要[/ja]',
value: this.renderFieldInputText('description', 50),
},
{ label: 'ID', value: this.renderFieldInputText('doi', 50) },
{
label: '[en]Item Link[/en][ja]リンク[/ja]',
value: this.renderFieldInputText('item_link', 50),
},
];
return rows;
}

View File

@ -1,29 +1,63 @@
import React from "react";
import XoopsCode from "../../../common/lib/XoopsCode";
import Functions from "../../../functions";
import { ItemMemo } from "../../lib/ItemUtil";
import DetailBase from "../lib/DetailBase";
import ItemTypeField from "../lib/field";
import XoopsCode from '../../../common/lib/XoopsCode';
import Functions from '../../../functions';
import { ItemMemo } from '../../lib/ItemUtil';
import DetailBase from '../lib/DetailBase';
import ItemTypeField from '../lib/field';
class MemoDetail extends DetailBase {
getFields() {
const { lang, type } = this.props;
const item = this.props.item as ItemMemo;
const fields = [
{ 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]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]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: "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: '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]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]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;
}

View File

@ -1,22 +1,21 @@
import React from "react";
import { Link } from "react-router-dom";
import XoopsCode from "../../../common/lib/XoopsCode";
import Functions from "../../../functions";
import iconFile from "../../assets/images/icon_memo.gif";
import { ItemMemo } from "../../lib/ItemUtil";
import ListBase, { ListBaseProps } from "../lib/ListBase";
import { Link } from 'react-router-dom';
import XoopsCode from '../../../common/lib/XoopsCode';
import Functions from '../../../functions';
import iconFile from '../../assets/images/icon_memo.gif';
import { ItemMemo } from '../../lib/ItemUtil';
import ListBase, { ListBaseProps } from '../lib/ListBase';
class MemoList extends ListBase {
constructor(props: ListBaseProps) {
super(props);
this.label = "Memo";
this.label = 'Memo';
this.icon = iconFile;
}
renderBody() {
const { lang } = this.props;
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 (
<>
<Link to={this.url}>{Functions.mlang(item.title, lang)}</Link>

View File

@ -1,13 +1,13 @@
import iconFile from "../../assets/images/icon_memo.gif";
import TopBase, { TopBaseProps } from "../lib/TopBase";
import iconFile from '../../assets/images/icon_memo.gif';
import TopBase, { TopBaseProps } from '../lib/TopBase';
class MemoTop extends TopBase {
constructor(props: TopBaseProps) {
super(props);
this.type = "memo";
this.label = "Memo";
this.type = 'memo';
this.label = 'Memo';
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