Merge branch 'develop'
This commit is contained in:
commit
701ee2e6c8
32
data_migration_tools/client/.devcontainer/Dockerfile
Normal file
32
data_migration_tools/client/.devcontainer/Dockerfile
Normal file
@ -0,0 +1,32 @@
|
||||
FROM node:18.13.0-buster
|
||||
|
||||
RUN /bin/cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
|
||||
echo "Asia/Tokyo" > /etc/timezone
|
||||
|
||||
# Options for setup script
|
||||
ARG INSTALL_ZSH="true"
|
||||
ARG UPGRADE_PACKAGES="false"
|
||||
ARG USERNAME=vscode
|
||||
# 1000 はnodeで使われているためずらす
|
||||
ARG USER_UID=1001
|
||||
ARG USER_GID=$USER_UID
|
||||
|
||||
# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
|
||||
COPY library-scripts/common-debian.sh /tmp/library-scripts/
|
||||
RUN bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \
|
||||
&& apt-get install default-jre -y \
|
||||
&& apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
|
||||
|
||||
# Install mob
|
||||
RUN curl -sL install.mob.sh | sh
|
||||
|
||||
# 以下 ユーザー権限で実施
|
||||
USER $USERNAME
|
||||
|
||||
# copy init-script
|
||||
COPY --chown=$USERNAME:$USERNAME init.sh /home/${USERNAME}/
|
||||
RUN chmod +x /home/${USERNAME}/init.sh
|
||||
|
||||
# 初期化を行う
|
||||
# node imageのデフォルトENTRYPOINTが邪魔するため上書き
|
||||
ENTRYPOINT /home/vscode/init.sh
|
||||
43
data_migration_tools/client/.devcontainer/devcontainer.json
Normal file
43
data_migration_tools/client/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,43 @@
|
||||
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.137.0/containers/go
|
||||
{
|
||||
"name": "data_migration_tools client",
|
||||
"dockerComposeFile": ["./docker-compose.yml"],
|
||||
"service": "client",
|
||||
// コンテナを自動停止させない
|
||||
"shutdownAction": "none",
|
||||
"workspaceFolder": "/app/data_migration_tools/client",
|
||||
"runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true, // eslint
|
||||
"source.fixAll.stylelint": true // Stylelint
|
||||
},
|
||||
// formatter
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode", // デフォルトフォーマッターをPrettier
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.insertSpaces": false,
|
||||
"editor.renderLineHighlight": "all"
|
||||
},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"salbert.comment-ts",
|
||||
"gruntfuggly.todo-tree",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vsliveshare.vsliveshare",
|
||||
"albymor.increment-selection",
|
||||
"eamodio.gitlens",
|
||||
"wmaurer.change-case"
|
||||
],
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "yarn install",
|
||||
"postCreateCommand": "sudo npm install @openapitools/openapi-generator-cli -g && sudo chown -R vscode:vscode /app/data_migration_tools/client",
|
||||
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode"
|
||||
}
|
||||
20
data_migration_tools/client/.devcontainer/docker-compose.yml
Normal file
20
data_migration_tools/client/.devcontainer/docker-compose.yml
Normal file
@ -0,0 +1,20 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
client:
|
||||
env_file: ../.env
|
||||
build: .
|
||||
working_dir: /app/data_migration_tools/client
|
||||
ports:
|
||||
- "127.0.0.1:3100:3100"
|
||||
volumes:
|
||||
- ../../../:/app
|
||||
- data_migration_tools_client_node_modules:/app/data_migration_tools/client/node_modules
|
||||
expose:
|
||||
- "3100"
|
||||
environment:
|
||||
- CHOKIDAR_USEPOLLING=true
|
||||
|
||||
# Data Volume として永続化する
|
||||
volumes:
|
||||
data_migration_tools_client_node_modules:
|
||||
22
data_migration_tools/client/.devcontainer/init.sh
Normal file
22
data_migration_tools/client/.devcontainer/init.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Init Script for client Container
|
||||
#
|
||||
|
||||
echo [init.sh] client initialize.
|
||||
|
||||
# /app の権限がデフォルトでは node ユーザーになっているため、
|
||||
# 権限確認し、vscode ユーザでない場合付け替える
|
||||
ls -ld /app | grep vscode
|
||||
if [ $? -ne 0 ]; then
|
||||
echo [init.sh] change /app owner to vscode.
|
||||
sudo chown -R vscode:vscode /app
|
||||
fi
|
||||
|
||||
cd /app/data_migration_tools/client
|
||||
echo [init.sh] \"npm ci\" start.
|
||||
npm ci
|
||||
|
||||
echo [init.sh] initialize completed!
|
||||
|
||||
sleep infinity
|
||||
@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env bash
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag]
|
||||
|
||||
INSTALL_ZSH=${1:-"true"}
|
||||
USERNAME=${2:-"vscode"}
|
||||
USER_UID=${3:-1000}
|
||||
USER_GID=${4:-1000}
|
||||
UPGRADE_PACKAGES=${5:-"true"}
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Treat a user name of "none" as root
|
||||
if [ "${USERNAME}" = "none" ] || [ "${USERNAME}" = "root" ]; then
|
||||
USERNAME=root
|
||||
USER_UID=0
|
||||
USER_GID=0
|
||||
fi
|
||||
|
||||
# Load markers to see which steps have already run
|
||||
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
|
||||
if [ -f "${MARKER_FILE}" ]; then
|
||||
echo "Marker file found:"
|
||||
cat "${MARKER_FILE}"
|
||||
source "${MARKER_FILE}"
|
||||
fi
|
||||
|
||||
# Ensure apt is in non-interactive to avoid prompts
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Function to call apt-get if needed
|
||||
apt-get-update-if-needed()
|
||||
{
|
||||
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
|
||||
echo "Running apt-get update..."
|
||||
apt-get update
|
||||
else
|
||||
echo "Skipping apt-get update."
|
||||
fi
|
||||
}
|
||||
|
||||
# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
|
||||
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
apt-get-update-if-needed
|
||||
|
||||
PACKAGE_LIST="apt-utils \
|
||||
git \
|
||||
openssh-client \
|
||||
less \
|
||||
iproute2 \
|
||||
procps \
|
||||
curl \
|
||||
wget \
|
||||
unzip \
|
||||
zip \
|
||||
nano \
|
||||
jq \
|
||||
lsb-release \
|
||||
ca-certificates \
|
||||
apt-transport-https \
|
||||
dialog \
|
||||
gnupg2 \
|
||||
libc6 \
|
||||
libgcc1 \
|
||||
libgssapi-krb5-2 \
|
||||
libicu[0-9][0-9] \
|
||||
liblttng-ust0 \
|
||||
libstdc++6 \
|
||||
zlib1g \
|
||||
locales \
|
||||
sudo"
|
||||
|
||||
# Install libssl1.1 if available
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
|
||||
PACKAGE_LIST="${PACKAGE_LIST} libssl1.1"
|
||||
fi
|
||||
|
||||
# Install appropriate version of libssl1.0.x if available
|
||||
LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
|
||||
if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
|
||||
# Debian 9
|
||||
PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.2"
|
||||
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
|
||||
# Ubuntu 18.04, 16.04, earlier
|
||||
PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.0"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Packages to verify are installed: ${PACKAGE_LIST}"
|
||||
apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
|
||||
|
||||
PACKAGES_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
# Get to latest versions of all packages
|
||||
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
|
||||
apt-get-update-if-needed
|
||||
apt-get -y upgrade --no-install-recommends
|
||||
apt-get autoremove -y
|
||||
fi
|
||||
|
||||
# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
|
||||
# Common need for both applications and things like the agnoster ZSH theme.
|
||||
if [ "${LOCALE_ALREADY_SET}" != "true" ]; then
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
|
||||
locale-gen
|
||||
LOCALE_ALREADY_SET="true"
|
||||
fi
|
||||
|
||||
# Create or update a non-root user to match UID/GID - see https://aka.ms/vscode-remote/containers/non-root-user.
|
||||
if id -u $USERNAME > /dev/null 2>&1; then
|
||||
# User exists, update if needed
|
||||
if [ "$USER_GID" != "$(id -G $USERNAME)" ]; then
|
||||
groupmod --gid $USER_GID $USERNAME
|
||||
usermod --gid $USER_GID $USERNAME
|
||||
fi
|
||||
if [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
|
||||
usermod --uid $USER_UID $USERNAME
|
||||
fi
|
||||
else
|
||||
# Create user
|
||||
groupadd --gid $USER_GID $USERNAME
|
||||
useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME
|
||||
fi
|
||||
|
||||
# Add add sudo support for non-root user
|
||||
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
|
||||
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
|
||||
chmod 0440 /etc/sudoers.d/$USERNAME
|
||||
EXISTING_NON_ROOT_USER="${USERNAME}"
|
||||
fi
|
||||
|
||||
# .bashrc/.zshrc snippet
|
||||
RC_SNIPPET="$(cat << EOF
|
||||
export USER=\$(whoami)
|
||||
|
||||
export PATH=\$PATH:\$HOME/.local/bin
|
||||
|
||||
if [[ \$(which code-insiders 2>&1) && ! \$(which code 2>&1) ]]; then
|
||||
alias code=code-insiders
|
||||
fi
|
||||
EOF
|
||||
)"
|
||||
|
||||
# Ensure ~/.local/bin is in the PATH for root and non-root users for bash. (zsh is later)
|
||||
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
|
||||
echo "${RC_SNIPPET}" | tee -a /root/.bashrc >> /etc/skel/.bashrc
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
echo "${RC_SNIPPET}" >> /home/$USERNAME/.bashrc
|
||||
chown $USER_UID:$USER_GID /home/$USERNAME/.bashrc
|
||||
fi
|
||||
RC_SNIPPET_ALREADY_ADDED="true"
|
||||
fi
|
||||
|
||||
# Optionally install and configure zsh
|
||||
if [ "${INSTALL_ZSH}" = "true" ] && [ ! -d "/root/.oh-my-zsh" ] && [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
|
||||
apt-get-update-if-needed
|
||||
apt-get install -y zsh
|
||||
curl -fsSLo- https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash 2>&1
|
||||
echo -e "${RC_SNIPPET}\nDEFAULT_USER=\$USER\nprompt_context(){}" >> /root/.zshrc
|
||||
cp -fR /root/.oh-my-zsh /etc/skel
|
||||
cp -f /root/.zshrc /etc/skel
|
||||
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/\$(whoami)\/.oh-my-zsh/g" /etc/skel/.zshrc
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
cp -fR /etc/skel/.oh-my-zsh /etc/skel/.zshrc /home/$USERNAME
|
||||
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc
|
||||
fi
|
||||
ZSH_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
# Write marker file
|
||||
mkdir -p "$(dirname "${MARKER_FILE}")"
|
||||
echo -e "\
|
||||
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
|
||||
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
|
||||
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
|
||||
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
|
||||
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
|
||||
|
||||
echo "Done!"
|
||||
0
data_migration_tools/client/.env
Normal file
0
data_migration_tools/client/.env
Normal file
1
data_migration_tools/client/.env.local.example
Normal file
1
data_migration_tools/client/.env.local.example
Normal file
@ -0,0 +1 @@
|
||||
VITE_STAGE=local
|
||||
6
data_migration_tools/client/.eslintignore
Normal file
6
data_migration_tools/client/.eslintignore
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules/
|
||||
build/
|
||||
.eslintrc.js
|
||||
jest.config.js
|
||||
vite.config.ts
|
||||
.env.local
|
||||
149
data_migration_tools/client/.eslintrc.js
Normal file
149
data_migration_tools/client/.eslintrc.js
Normal file
@ -0,0 +1,149 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
extends: [
|
||||
"airbnb",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"prettier",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
project: "./tsconfig.json",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: [
|
||||
"react",
|
||||
"@typescript-eslint",
|
||||
"prettier",
|
||||
"react-hooks",
|
||||
"prefer-arrow",
|
||||
],
|
||||
rules: {
|
||||
"react/jsx-uses-react": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/function-component-definition": [
|
||||
"error",
|
||||
{
|
||||
namedComponents: "arrow-function",
|
||||
unnamedComponents: "arrow-function",
|
||||
},
|
||||
],
|
||||
"react/jsx-filename-extension": [
|
||||
"error",
|
||||
{
|
||||
extensions: ["jsx", "tsx"],
|
||||
},
|
||||
],
|
||||
"import/extensions": [
|
||||
"error",
|
||||
"ignorePackages",
|
||||
{
|
||||
js: "never",
|
||||
jsx: "never",
|
||||
ts: "never",
|
||||
tsx: "never",
|
||||
},
|
||||
],
|
||||
"import/no-unresolved": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"no-use-before-define": 0,
|
||||
"prettier/prettier": "error",
|
||||
"no-param-reassign": 0,
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/prefer-interface": "off",
|
||||
"@typescript-eslint/indent": "off",
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
// Checks rules of Hooks
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
// Checks effect dependencies
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
devDependencies: [
|
||||
"**/*.test.js",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.tsx",
|
||||
"**/setupTests.ts",
|
||||
],
|
||||
},
|
||||
],
|
||||
camelcase: "off",
|
||||
"prefer-arrow/prefer-arrow-functions": [
|
||||
"error",
|
||||
{
|
||||
disallowPrototype: true,
|
||||
singleReturnOnly: false,
|
||||
classPropertiesAllowed: false,
|
||||
},
|
||||
],
|
||||
"func-style": [
|
||||
"error",
|
||||
"expression",
|
||||
{
|
||||
allowArrowFunctions: true,
|
||||
},
|
||||
],
|
||||
"react/no-multi-comp": ["error"],
|
||||
"react/jsx-pascal-case": ["error"],
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error", // default config
|
||||
{
|
||||
selector: "default",
|
||||
format: ["camelCase"],
|
||||
leadingUnderscore: "allow",
|
||||
trailingUnderscore: "allow",
|
||||
},
|
||||
{
|
||||
selector: "variable",
|
||||
format: ["camelCase", "UPPER_CASE"],
|
||||
leadingUnderscore: "allow",
|
||||
trailingUnderscore: "allow",
|
||||
},
|
||||
{
|
||||
selector: "typeLike",
|
||||
format: ["PascalCase"],
|
||||
}, // custom config
|
||||
{
|
||||
selector: ["property"],
|
||||
format: ["camelCase", "PascalCase"],
|
||||
},
|
||||
{
|
||||
selector: ["variable"],
|
||||
types: ["function"],
|
||||
format: ["camelCase", "PascalCase"],
|
||||
},
|
||||
{
|
||||
selector: "interface",
|
||||
format: ["PascalCase"],
|
||||
custom: {
|
||||
regex: "^I[A-Z]",
|
||||
match: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
"max-lines": ["error", 3000],
|
||||
},
|
||||
settings: {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [".ts", ".tsx"],
|
||||
},
|
||||
"import/resolver": {
|
||||
node: {
|
||||
extensions: [".js", "jsx", ".ts", ".tsx"],
|
||||
paths: ["src"],
|
||||
},
|
||||
},
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
};
|
||||
24
data_migration_tools/client/.gitignore
vendored
Normal file
24
data_migration_tools/client/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.env.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
.eslintcache
|
||||
|
||||
# credentials
|
||||
credentials
|
||||
14
data_migration_tools/client/index.html
Normal file
14
data_migration_tools/client/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
1
data_migration_tools/client/localdeploy.sh
Normal file
1
data_migration_tools/client/localdeploy.sh
Normal file
@ -0,0 +1 @@
|
||||
cp -r build /app/data_migration_tools/server
|
||||
14043
data_migration_tools/client/package-lock.json
generated
Normal file
14043
data_migration_tools/client/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
93
data_migration_tools/client/package.json
Normal file
93
data_migration_tools/client/package.json
Normal file
@ -0,0 +1,93 @@
|
||||
{
|
||||
"name": "client",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"build:prod": "tsc && vite build",
|
||||
"build:local": "tsc && vite build && sh localdeploy.sh",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"codegen": "sh codegen.sh",
|
||||
"lint": "eslint --cache . --ext .js,.ts,.tsx",
|
||||
"lint:fix": "npm run lint -- --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "^12.14.0",
|
||||
"@reduxjs/toolkit": "^1.8.3",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
"@testing-library/user-event": "^14.2.1",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^17.0.45",
|
||||
"@types/react": "^18.0.14",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@types/redux-mock-store": "^1.0.3",
|
||||
"axios": "^0.27.2",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^3.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-google-recaptcha-v3": "^1.10.0",
|
||||
"react-paginate": "^8.1.3",
|
||||
"react-redux": "^8.0.2",
|
||||
"react-router-dom": "^6.4.1",
|
||||
"redux-mock-store": "^1.5.4",
|
||||
"redux-thunk": "^2.4.1",
|
||||
"styled-components": "^5.3.5",
|
||||
"typescript": "^4.7.4",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.18.6",
|
||||
"@mdx-js/react": "^2.1.2",
|
||||
"@openapitools/openapi-generator-cli": "^2.5.2",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/luxon": "^3.2.0",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@types/redux-mock-store": "^1.0.3",
|
||||
"@types/styled-components": "^5.1.25",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"@vitejs/plugin-react": "^1.3.2",
|
||||
"babel-loader": "^8.2.5",
|
||||
"eslint": "^8.19.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.30.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"license-checker": "^25.0.1",
|
||||
"prettier": "^2.7.1",
|
||||
"redux-mock-store": "^1.5.4",
|
||||
"typescript": "^4.7.4",
|
||||
"vite": "^2.9.9",
|
||||
"vite-plugin-env-compatible": "^1.1.1",
|
||||
"vite-tsconfig-paths": "^3.5.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"**/*.stories.*"
|
||||
],
|
||||
"rules": {
|
||||
"import/no-anonymous-default-export": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
11
data_migration_tools/client/src/App.tsx
Normal file
11
data_migration_tools/client/src/App.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import AppRouter from "AppRouter";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import "./styles/GlobalStyle.css";
|
||||
|
||||
const App = (): JSX.Element => (
|
||||
<BrowserRouter>
|
||||
<AppRouter />
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
||||
export default App;
|
||||
9
data_migration_tools/client/src/AppRouter.tsx
Normal file
9
data_migration_tools/client/src/AppRouter.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
|
||||
const AppRouter: React.FC = () => (
|
||||
<Routes>
|
||||
<Route path="/" element={<div />} />
|
||||
</Routes>
|
||||
);
|
||||
|
||||
export default AppRouter;
|
||||
16
data_migration_tools/client/src/app/store.ts
Normal file
16
data_migration_tools/client/src/app/store.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
},
|
||||
});
|
||||
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export type AppThunk<ReturnType = void> = ThunkAction<
|
||||
ReturnType,
|
||||
RootState,
|
||||
unknown,
|
||||
Action<string>
|
||||
>;
|
||||
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
6
data_migration_tools/client/src/common/getBasePath.ts
Normal file
6
data_migration_tools/client/src/common/getBasePath.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export const getBasePath = () => {
|
||||
if (import.meta.env.VITE_STAGE === "local") {
|
||||
return "http://localhost:8180";
|
||||
}
|
||||
return window.location.origin;
|
||||
};
|
||||
3
data_migration_tools/client/src/common/index.ts
Normal file
3
data_migration_tools/client/src/common/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export interface ErrorObject {
|
||||
message: string;
|
||||
}
|
||||
33
data_migration_tools/client/src/components/SnackBar.css
Normal file
33
data_migration_tools/client/src/components/SnackBar.css
Normal file
@ -0,0 +1,33 @@
|
||||
.snackbar {
|
||||
position: fixed;
|
||||
top: -100px; /* 上から現れるための初期位置 */
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background-color: #323232;
|
||||
color: #ffffff;
|
||||
border-radius: 5px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-width: 300px;
|
||||
max-width: 80%;
|
||||
z-index: 1000;
|
||||
transition: top 0.5s ease-in-out; /* アニメーション効果の追加 */
|
||||
}
|
||||
|
||||
.snackbar.show {
|
||||
top: 20px; /* 最終的な表示位置 */
|
||||
}
|
||||
|
||||
.snackbar button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.snackbar p {
|
||||
margin: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
19
data_migration_tools/client/src/components/SnackBar.tsx
Normal file
19
data_migration_tools/client/src/components/SnackBar.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React, { FC } from "react";
|
||||
import "./SnackBar.css";
|
||||
|
||||
interface SnackBarProps {
|
||||
message: string;
|
||||
show: boolean;
|
||||
closeSnackBar: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
}
|
||||
|
||||
const SnackBar: FC<SnackBarProps> = ({ message, show, closeSnackBar }) => (
|
||||
<div className={`snackbar${show ? " show" : ""}`}>
|
||||
<p>{message}</p>
|
||||
<button type="button" onClick={closeSnackBar}>
|
||||
閉じる
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default SnackBar;
|
||||
15
data_migration_tools/client/src/favicon.svg
Normal file
15
data_migration_tools/client/src/favicon.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<svg width="410" height="404" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
|
||||
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#41D1FF"/>
|
||||
<stop offset="1" stop-color="#BD34FE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFEA83"/>
|
||||
<stop offset="0.0833333" stop-color="#FFDD35"/>
|
||||
<stop offset="1" stop-color="#FFA800"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
23
data_migration_tools/client/src/main.tsx
Normal file
23
data_migration_tools/client/src/main.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { store } from "app/store";
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Provider } from "react-redux";
|
||||
import App from "./App";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
|
||||
const container = document.getElementById("root");
|
||||
if (container) {
|
||||
const root = createRoot(container);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
||||
148
data_migration_tools/client/src/serviceWorker.ts
Normal file
148
data_migration_tools/client/src/serviceWorker.ts
Normal file
@ -0,0 +1,148 @@
|
||||
/* eslint-disable */
|
||||
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === "localhost" ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === "[::1]" ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
type Config = {
|
||||
onSuccess?: (registration: ServiceWorkerRegistration) => void;
|
||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
||||
};
|
||||
|
||||
export function register(config?: Config) {
|
||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
"This web app is being served cache-first by a service " +
|
||||
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl: string, config?: Config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === "installed") {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
"New content is available and will be used when all " +
|
||||
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log("Content is cached for offline use.");
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { "Service-Worker": "script" },
|
||||
})
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
"No internet connection found. App is running in offline mode."
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
37
data_migration_tools/client/src/types/index.d.ts
vendored
Normal file
37
data_migration_tools/client/src/types/index.d.ts
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* bring from react-scripts/lib/react-app.d.ts
|
||||
*/
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
// local環境はdevelopment、staging環境は production になる
|
||||
readonly NODE_ENV: "development" | "develop" | "production" | "test";
|
||||
readonly PUBLIC_URL: string;
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
}
|
||||
|
||||
declare module "*.gif" {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module "*.jpg" {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module "*.jpeg" {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module "*.png" {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module "*.svg" {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
11
data_migration_tools/client/src/vite-env.d.ts
vendored
Normal file
11
data_migration_tools/client/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
// 環境変数のコード補完
|
||||
/// <reference types="vite/client" />
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_STAGE: string;
|
||||
readonly VITE_ODMS_CLOUD_BASE_PATH: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
22
data_migration_tools/client/tsconfig.json
Normal file
22
data_migration_tools/client/tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2019",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"baseUrl": "src",
|
||||
"plugins": [{ "name": "typescript-styled-plugin" }]
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
18
data_migration_tools/client/vite.config.ts
Normal file
18
data_migration_tools/client/vite.config.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import env from "vite-plugin-env-compatible";
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
host: true,
|
||||
port: 3100,
|
||||
open: true,
|
||||
},
|
||||
build: {
|
||||
outDir: "build",
|
||||
sourcemap: true,
|
||||
minify: false,
|
||||
},
|
||||
plugins: [env(), tsconfigPaths(), react()],
|
||||
});
|
||||
31
data_migration_tools/server/.devcontainer/Dockerfile
Normal file
31
data_migration_tools/server/.devcontainer/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
||||
FROM node:18.13.0-buster
|
||||
|
||||
RUN /bin/cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
|
||||
echo "Asia/Tokyo" > /etc/timezone
|
||||
|
||||
# Options for setup script
|
||||
ARG INSTALL_ZSH="true"
|
||||
ARG UPGRADE_PACKAGES="false"
|
||||
ARG USERNAME=vscode
|
||||
# 1000 はnodeで使われているためずらす
|
||||
ARG USER_UID=1001
|
||||
ARG USER_GID=$USER_UID
|
||||
|
||||
# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
|
||||
COPY library-scripts/common-debian.sh /tmp/library-scripts/
|
||||
RUN bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \
|
||||
&& apt-get install default-jre -y \
|
||||
&& apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
|
||||
|
||||
# Install NestJS
|
||||
RUN npm i -g @nestjs/cli
|
||||
|
||||
# 以下 ユーザー権限で実施
|
||||
USER $USERNAME
|
||||
# copy init-script
|
||||
COPY --chown=$USERNAME:$USERNAME init.sh /home/${USERNAME}/
|
||||
RUN chmod +x /home/${USERNAME}/init.sh
|
||||
|
||||
# 初期化を行う
|
||||
# node imageのデフォルトENTRYPOINTが邪魔するため上書き
|
||||
ENTRYPOINT /home/vscode/init.sh
|
||||
56
data_migration_tools/server/.devcontainer/devcontainer.json
Normal file
56
data_migration_tools/server/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,56 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/javascript-node
|
||||
{
|
||||
"name": "data_migration_tools server",
|
||||
"dockerComposeFile": [
|
||||
"./docker-compose.yml"
|
||||
],
|
||||
"service": "server",
|
||||
// コンテナを自動停止させない
|
||||
"shutdownAction": "none",
|
||||
"workspaceFolder": "/app/data_migration_tools/server",
|
||||
"runArgs": [
|
||||
"--cap-add=SYS_PTRACE",
|
||||
"--security-opt",
|
||||
"seccomp=unconfined"
|
||||
],
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"eslint.format.enable": false,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
// formatter
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.insertSpaces": false,
|
||||
"editor.renderLineHighlight": "all"
|
||||
},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"salbert.comment-ts",
|
||||
"gruntfuggly.todo-tree",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vsliveshare.vsliveshare",
|
||||
"albymor.increment-selection",
|
||||
"eamodio.gitlens",
|
||||
"wmaurer.change-case"
|
||||
],
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "yarn install",
|
||||
"postCreateCommand": "sudo chown -R vscode:vscode /app/data_migration_tools/server",
|
||||
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode"
|
||||
}
|
||||
18
data_migration_tools/server/.devcontainer/docker-compose.yml
Normal file
18
data_migration_tools/server/.devcontainer/docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
server:
|
||||
env_file: ../.env
|
||||
build: .
|
||||
working_dir: /app/data_migration_tools/server
|
||||
ports:
|
||||
- "127.0.0.1:8280:8280"
|
||||
volumes:
|
||||
- ../../../:/app
|
||||
- data_migration_tools_server_node_modules:/app/data_migration_tools/server/node_modules
|
||||
expose:
|
||||
- "8280"
|
||||
environment:
|
||||
- CHOKIDAR_USEPOLLING=true
|
||||
volumes:
|
||||
data_migration_tools_server_node_modules:
|
||||
20
data_migration_tools/server/.devcontainer/init.sh
Normal file
20
data_migration_tools/server/.devcontainer/init.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Init Script for server Container
|
||||
#
|
||||
|
||||
echo [init.sh] server initialize.
|
||||
|
||||
# /app の権限がデフォルトでは node ユーザーになっているため、
|
||||
# 権限確認し、vscode ユーザでない場合付け替える
|
||||
ls -ld /app | grep vscode
|
||||
if [ $? -ne 0 ]; then
|
||||
echo [init.sh] change /app owner to vscode.
|
||||
sudo chown -R vscode:vscode /app
|
||||
fi
|
||||
|
||||
cd /app/server
|
||||
|
||||
echo [init.sh] initialize completed!
|
||||
|
||||
sleep infinity
|
||||
@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env bash
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag]
|
||||
|
||||
INSTALL_ZSH=${1:-"true"}
|
||||
USERNAME=${2:-"vscode"}
|
||||
USER_UID=${3:-1000}
|
||||
USER_GID=${4:-1000}
|
||||
UPGRADE_PACKAGES=${5:-"true"}
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Treat a user name of "none" as root
|
||||
if [ "${USERNAME}" = "none" ] || [ "${USERNAME}" = "root" ]; then
|
||||
USERNAME=root
|
||||
USER_UID=0
|
||||
USER_GID=0
|
||||
fi
|
||||
|
||||
# Load markers to see which steps have already run
|
||||
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
|
||||
if [ -f "${MARKER_FILE}" ]; then
|
||||
echo "Marker file found:"
|
||||
cat "${MARKER_FILE}"
|
||||
source "${MARKER_FILE}"
|
||||
fi
|
||||
|
||||
# Ensure apt is in non-interactive to avoid prompts
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Function to call apt-get if needed
|
||||
apt-get-update-if-needed()
|
||||
{
|
||||
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
|
||||
echo "Running apt-get update..."
|
||||
apt-get update
|
||||
else
|
||||
echo "Skipping apt-get update."
|
||||
fi
|
||||
}
|
||||
|
||||
# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
|
||||
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
apt-get-update-if-needed
|
||||
|
||||
PACKAGE_LIST="apt-utils \
|
||||
git \
|
||||
openssh-client \
|
||||
less \
|
||||
iproute2 \
|
||||
procps \
|
||||
curl \
|
||||
wget \
|
||||
unzip \
|
||||
zip \
|
||||
nano \
|
||||
jq \
|
||||
lsb-release \
|
||||
ca-certificates \
|
||||
apt-transport-https \
|
||||
dialog \
|
||||
gnupg2 \
|
||||
libc6 \
|
||||
libgcc1 \
|
||||
libgssapi-krb5-2 \
|
||||
libicu[0-9][0-9] \
|
||||
liblttng-ust0 \
|
||||
libstdc++6 \
|
||||
zlib1g \
|
||||
locales \
|
||||
sudo"
|
||||
|
||||
# Install libssl1.1 if available
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
|
||||
PACKAGE_LIST="${PACKAGE_LIST} libssl1.1"
|
||||
fi
|
||||
|
||||
# Install appropriate version of libssl1.0.x if available
|
||||
LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
|
||||
if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
|
||||
# Debian 9
|
||||
PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.2"
|
||||
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
|
||||
# Ubuntu 18.04, 16.04, earlier
|
||||
PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.0"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Packages to verify are installed: ${PACKAGE_LIST}"
|
||||
apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
|
||||
|
||||
PACKAGES_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
# Get to latest versions of all packages
|
||||
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
|
||||
apt-get-update-if-needed
|
||||
apt-get -y upgrade --no-install-recommends
|
||||
apt-get autoremove -y
|
||||
fi
|
||||
|
||||
# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
|
||||
# Common need for both applications and things like the agnoster ZSH theme.
|
||||
if [ "${LOCALE_ALREADY_SET}" != "true" ]; then
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
|
||||
locale-gen
|
||||
LOCALE_ALREADY_SET="true"
|
||||
fi
|
||||
|
||||
# Create or update a non-root user to match UID/GID - see https://aka.ms/vscode-remote/containers/non-root-user.
|
||||
if id -u $USERNAME > /dev/null 2>&1; then
|
||||
# User exists, update if needed
|
||||
if [ "$USER_GID" != "$(id -G $USERNAME)" ]; then
|
||||
groupmod --gid $USER_GID $USERNAME
|
||||
usermod --gid $USER_GID $USERNAME
|
||||
fi
|
||||
if [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
|
||||
usermod --uid $USER_UID $USERNAME
|
||||
fi
|
||||
else
|
||||
# Create user
|
||||
groupadd --gid $USER_GID $USERNAME
|
||||
useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME
|
||||
fi
|
||||
|
||||
# Add add sudo support for non-root user
|
||||
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
|
||||
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
|
||||
chmod 0440 /etc/sudoers.d/$USERNAME
|
||||
EXISTING_NON_ROOT_USER="${USERNAME}"
|
||||
fi
|
||||
|
||||
# .bashrc/.zshrc snippet
|
||||
RC_SNIPPET="$(cat << EOF
|
||||
export USER=\$(whoami)
|
||||
|
||||
export PATH=\$PATH:\$HOME/.local/bin
|
||||
|
||||
if [[ \$(which code-insiders 2>&1) && ! \$(which code 2>&1) ]]; then
|
||||
alias code=code-insiders
|
||||
fi
|
||||
EOF
|
||||
)"
|
||||
|
||||
# Ensure ~/.local/bin is in the PATH for root and non-root users for bash. (zsh is later)
|
||||
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
|
||||
echo "${RC_SNIPPET}" | tee -a /root/.bashrc >> /etc/skel/.bashrc
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
echo "${RC_SNIPPET}" >> /home/$USERNAME/.bashrc
|
||||
chown $USER_UID:$USER_GID /home/$USERNAME/.bashrc
|
||||
fi
|
||||
RC_SNIPPET_ALREADY_ADDED="true"
|
||||
fi
|
||||
|
||||
# Optionally install and configure zsh
|
||||
if [ "${INSTALL_ZSH}" = "true" ] && [ ! -d "/root/.oh-my-zsh" ] && [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
|
||||
apt-get-update-if-needed
|
||||
apt-get install -y zsh
|
||||
curl -fsSLo- https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash 2>&1
|
||||
echo -e "${RC_SNIPPET}\nDEFAULT_USER=\$USER\nprompt_context(){}" >> /root/.zshrc
|
||||
cp -fR /root/.oh-my-zsh /etc/skel
|
||||
cp -f /root/.zshrc /etc/skel
|
||||
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/\$(whoami)\/.oh-my-zsh/g" /etc/skel/.zshrc
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
cp -fR /etc/skel/.oh-my-zsh /etc/skel/.zshrc /home/$USERNAME
|
||||
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc
|
||||
fi
|
||||
ZSH_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
# Write marker file
|
||||
mkdir -p "$(dirname "${MARKER_FILE}")"
|
||||
echo -e "\
|
||||
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
|
||||
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
|
||||
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
|
||||
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
|
||||
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
|
||||
|
||||
echo "Done!"
|
||||
0
data_migration_tools/server/.env
Normal file
0
data_migration_tools/server/.env
Normal file
0
data_migration_tools/server/.env.local.example
Normal file
0
data_migration_tools/server/.env.local.example
Normal file
25
data_migration_tools/server/.eslintrc.js
Normal file
25
data_migration_tools/server/.eslintrc.js
Normal file
@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
tsconfigRootDir : __dirname,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js'],
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
},
|
||||
};
|
||||
8
data_migration_tools/server/.gitignore
vendored
Normal file
8
data_migration_tools/server/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/dist*
|
||||
/node_modules
|
||||
/dump.rdb
|
||||
/build
|
||||
/openapi/build
|
||||
|
||||
|
||||
.env.local
|
||||
14
data_migration_tools/server/.vscode/launch.json
vendored
Normal file
14
data_migration_tools/server/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["run", "start:debug"],
|
||||
"envFile": "${workspaceFolder}/.env",
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
data_migration_tools/server/.vscode/settings.json
vendored
Normal file
21
data_migration_tools/server/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.format.enable": false,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.insertSpaces": false,
|
||||
"editor.renderLineHighlight": "all"
|
||||
}
|
||||
5
data_migration_tools/server/nest-cli.json
Normal file
5
data_migration_tools/server/nest-cli.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src"
|
||||
}
|
||||
15586
data_migration_tools/server/package-lock.json
generated
Normal file
15586
data_migration_tools/server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
80
data_migration_tools/server/package.json
Normal file
80
data_migration_tools/server/package.json
Normal file
@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "data_migration_tool",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "nest build && cp -r build dist",
|
||||
"build:exe": "nest build && cp -r build dist && sh ./buildTool.sh",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"start": "nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
|
||||
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "^12.14.0",
|
||||
"@nestjs/common": "^9.3.9",
|
||||
"@nestjs/config": "^2.3.1",
|
||||
"@nestjs/core": "^9.3.9",
|
||||
"@nestjs/platform-express": "^9.4.1",
|
||||
"@nestjs/serve-static": "^3.0.1",
|
||||
"@nestjs/swagger": "^6.2.1",
|
||||
"@nestjs/testing": "^9.3.9",
|
||||
"@openapitools/openapi-generator-cli": "^2.5.2",
|
||||
"@vercel/ncc": "^0.36.1",
|
||||
"axios": "^1.3.4",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.8.0",
|
||||
"swagger-cli": "^4.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "^20.2.3",
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "28.0.3",
|
||||
"license-checker": "^25.0.1",
|
||||
"prettier": "^2.3.2",
|
||||
"source-map-support": "^0.5.20",
|
||||
"supertest": "^6.1.3",
|
||||
"swagger-ui-express": "^4.5.0",
|
||||
"ts-jest": "28.0.1",
|
||||
"ts-loader": "^9.2.3",
|
||||
"ts-node": "^10.0.0",
|
||||
"tsconfig-paths": "4.0.0",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
||||
24
data_migration_tools/server/src/app.module.ts
Normal file
24
data_migration_tools/server/src/app.module.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { MiddlewareConsumer, Module } from "@nestjs/common";
|
||||
import { ServeStaticModule } from "@nestjs/serve-static";
|
||||
import { ConfigModule } from "@nestjs/config";
|
||||
import { join } from "path";
|
||||
import { LoggerMiddleware } from "./common/loggerMiddleware";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ServeStaticModule.forRoot({
|
||||
rootPath: join(__dirname, ".", "build"),
|
||||
}),
|
||||
ConfigModule.forRoot({
|
||||
envFilePath: [".env.local", ".env"],
|
||||
isGlobal: true,
|
||||
}),
|
||||
],
|
||||
controllers: [],
|
||||
providers: [],
|
||||
})
|
||||
export class AppModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(LoggerMiddleware).forRoutes("");
|
||||
}
|
||||
}
|
||||
6
data_migration_tools/server/src/common/errors/utils.ts
Normal file
6
data_migration_tools/server/src/common/errors/utils.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { AxiosError } from "axios";
|
||||
|
||||
export const isAxiosError = (e: unknown): e is AxiosError => {
|
||||
const error = e as AxiosError;
|
||||
return error?.isAxiosError ?? false;
|
||||
};
|
||||
28
data_migration_tools/server/src/common/loggerMiddleware.ts
Normal file
28
data_migration_tools/server/src/common/loggerMiddleware.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { Injectable, Logger, NestMiddleware } from "@nestjs/common";
|
||||
import { Request, Response } from "express";
|
||||
|
||||
@Injectable()
|
||||
export class LoggerMiddleware implements NestMiddleware {
|
||||
private readonly logger = new Logger(LoggerMiddleware.name);
|
||||
|
||||
use(req: Request, res: Response, next: () => void): void {
|
||||
this.logger.log(this.createReqMsg(req));
|
||||
|
||||
res.on("close", () => {
|
||||
this.logger.log(this.createResMsg(res));
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
private createReqMsg(req: Request): string {
|
||||
const message = `Request [url=${req.url}, method=${req.method}]`;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private createResMsg(res: Response): string {
|
||||
const message = `Response [statusCode=${res.statusCode}, message=${res.statusMessage}]`;
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
35
data_migration_tools/server/src/main.ts
Normal file
35
data_migration_tools/server/src/main.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { NestFactory } from "@nestjs/core";
|
||||
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
|
||||
import { AppModule } from "./app.module";
|
||||
import { ValidationPipe } from "@nestjs/common";
|
||||
import { LoggerMiddleware } from "./common/loggerMiddleware";
|
||||
import cookieParser from "cookie-parser";
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule, {
|
||||
cors: process.env.CORS === "TRUE",
|
||||
});
|
||||
app.use(new LoggerMiddleware(), cookieParser());
|
||||
|
||||
// バリデーター(+型の自動変換機能)を適用
|
||||
app.useGlobalPipes(
|
||||
new ValidationPipe({ transform: true, forbidUnknownValues: false })
|
||||
);
|
||||
|
||||
if (process.env.STAGE === "local") {
|
||||
const options = new DocumentBuilder()
|
||||
.setTitle("data_migration_toolsOpenAPI")
|
||||
.setVersion("1.0.0")
|
||||
.addBearerAuth({
|
||||
type: "http",
|
||||
scheme: "bearer",
|
||||
bearerFormat: "JWT",
|
||||
})
|
||||
.build();
|
||||
const document = SwaggerModule.createDocument(app, options);
|
||||
SwaggerModule.setup("api", app, document);
|
||||
}
|
||||
|
||||
await app.listen(process.env.PORT || 8180);
|
||||
}
|
||||
bootstrap();
|
||||
4
data_migration_tools/server/tsconfig.build.json
Normal file
4
data_migration_tools/server/tsconfig.build.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
}
|
||||
22
data_migration_tools/server/tsconfig.json
Normal file
22
data_migration_tools/server/tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "es2022",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "./",
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
@ -43,14 +43,18 @@ const App = (): JSX.Element => {
|
||||
|
||||
// Language読み取り
|
||||
useLayoutEffect(() => {
|
||||
const language = document.cookie
|
||||
.trim()
|
||||
.split(";")
|
||||
.map((x) => x.split("="))
|
||||
.find((x) => x.length === 2 && x[0] === "language");
|
||||
const { cookie } = document;
|
||||
|
||||
if (language) {
|
||||
i18n.changeLanguage(language[1]);
|
||||
if (cookie) {
|
||||
const cookieArray = cookie.split(";");
|
||||
const language = cookieArray.find((x) =>
|
||||
// 先頭の空白を削除してから判定
|
||||
x.trim().startsWith("language=")
|
||||
);
|
||||
|
||||
if (language) {
|
||||
i18n.changeLanguage(language.split("=")[1]);
|
||||
}
|
||||
}
|
||||
}, [i18n]);
|
||||
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import styles from "styles/app.module.scss";
|
||||
import { getTranslationID } from "translation";
|
||||
|
||||
const Footer: React.FC = () => (
|
||||
<footer className={`${styles.footer}`}>
|
||||
<div>© OM Digital Solutions 2023</div>
|
||||
</footer>
|
||||
);
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
const [t] = useTranslation();
|
||||
return (
|
||||
<footer className={`${styles.footer}`}>
|
||||
<div>{t(getTranslationID("common.label.copyRight"))}</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
export default Footer;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import type { RoleType } from "./types";
|
||||
|
||||
// LicenseStatusTypeの値を定数オブジェクトにする
|
||||
export const LICENSE_STATUS = {
|
||||
NORMAL: "Normal",
|
||||
@ -17,3 +19,10 @@ export const NO_LICENSE = "No License" as const;
|
||||
|
||||
// ライセンスが割り当てられている場合の表示
|
||||
export const LICENSE_NORMAL = "License Assigned" as const;
|
||||
|
||||
// Roleの表示名
|
||||
export const ROLE_DISPLAY_NAME: Record<RoleType, string> = {
|
||||
author: "Author",
|
||||
typist: "Transcriptionist",
|
||||
none: "None",
|
||||
} as const;
|
||||
|
||||
@ -9,7 +9,11 @@ import {
|
||||
isLicenseStatusType,
|
||||
isRoleType,
|
||||
} from "./types";
|
||||
import { LICENSE_STATUS, LICENSE_ALLOCATE_STATUS } from "./constants";
|
||||
import {
|
||||
LICENSE_STATUS,
|
||||
LICENSE_ALLOCATE_STATUS,
|
||||
ROLE_DISPLAY_NAME,
|
||||
} from "./constants";
|
||||
|
||||
export const selectInputValidationErrors = (state: RootState) => {
|
||||
const { name, email, role, authorId, encryption, encryptionPassword } =
|
||||
@ -176,8 +180,8 @@ export const selectUserViews = (state: RootState): UserView[] => {
|
||||
prompt: convertedValues.prompt,
|
||||
encryption: convertedValues.encryption,
|
||||
authorId: convertedValues.authorId,
|
||||
// roleの一文字目を大文字に変換する
|
||||
role: role.charAt(0).toUpperCase() + role.slice(1),
|
||||
// roleに応じて表示名を変更する
|
||||
role: ROLE_DISPLAY_NAME[role],
|
||||
licenseStatus: convertedLicenseStatus,
|
||||
expiration: convertedExpiration,
|
||||
remaining: convertedRemaining,
|
||||
|
||||
@ -45,7 +45,7 @@ export const worktypeSlice = createSlice({
|
||||
action: PayloadAction<{ worktypeId: string }>
|
||||
) => {
|
||||
const { worktypeId } = action.payload;
|
||||
state.apps.worktypeId = worktypeId;
|
||||
state.apps.worktypeId = worktypeId.toUpperCase();
|
||||
},
|
||||
changeDescription: (
|
||||
state,
|
||||
@ -65,7 +65,12 @@ export const worktypeSlice = createSlice({
|
||||
optionItem.defaultValueType !== OPTION_ITEMS_DEFAULT_VALUE_TYPE.DEFAULT
|
||||
) {
|
||||
optionItem.initialValue = "";
|
||||
} else {
|
||||
// defaultValueTypeがDefaultの場合はinitialValueを大文字にする
|
||||
optionItem.initialValue = optionItem.initialValue.toUpperCase();
|
||||
}
|
||||
// itemLabelを大文字にする
|
||||
optionItem.itemLabel = optionItem.itemLabel.toUpperCase();
|
||||
|
||||
// idが一致するoptionItemを削除して、新しいoptionItemを追加する。一致するidがない場合は何もしない
|
||||
const optionItems = state.apps.optionItems?.filter(
|
||||
|
||||
@ -383,15 +383,6 @@ const AccountPage: React.FC = (): JSX.Element => {
|
||||
className={styles.icLoading}
|
||||
alt="Loading"
|
||||
/>
|
||||
{isTier5 && (
|
||||
<p className={styles.formComment}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"accountPage.text.dealerManagementAnnotation"
|
||||
)
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{isTier5 && (
|
||||
|
||||
@ -50,16 +50,6 @@ export const FilePropertyPopup: React.FC<FilePropertyPopupProps> = (props) => {
|
||||
<dd>{selectedFileTask?.fileSize ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.fileLength"))}</dt>
|
||||
<dd>{selectedFileTask?.audioDuration ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.authorId"))}</dt>
|
||||
<dd>{selectedFileTask?.authorId ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.workType"))}</dt>
|
||||
<dd>{selectedFileTask?.workType ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.priority"))}</dt>
|
||||
<dd>
|
||||
{selectedFileTask?.priority === "01"
|
||||
? PRIORITY.HIGH
|
||||
: PRIORITY.NORMAL}
|
||||
</dd>
|
||||
<dt>
|
||||
{t(getTranslationID("dictationPage.label.recordingStartedDate"))}
|
||||
</dt>
|
||||
@ -68,8 +58,6 @@ export const FilePropertyPopup: React.FC<FilePropertyPopupProps> = (props) => {
|
||||
{t(getTranslationID("dictationPage.label.recordingFinishedDate"))}
|
||||
</dt>
|
||||
<dd>{selectedFileTask?.audioFinishedDate ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.uploadDate"))}</dt>
|
||||
<dd>{selectedFileTask?.audioUploadedDate ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.encryption"))}</dt>
|
||||
<dd>
|
||||
{selectedFileTask?.isEncrypted ? (
|
||||
@ -78,6 +66,16 @@ export const FilePropertyPopup: React.FC<FilePropertyPopupProps> = (props) => {
|
||||
""
|
||||
)}
|
||||
</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.priority"))}</dt>
|
||||
<dd>
|
||||
{selectedFileTask?.priority === "01"
|
||||
? PRIORITY.HIGH
|
||||
: PRIORITY.NORMAL}
|
||||
</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.authorId"))}</dt>
|
||||
<dd>{selectedFileTask?.authorId ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.workType"))}</dt>
|
||||
<dd>{selectedFileTask?.workType ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.optionItem1"))}</dt>
|
||||
<dd>{selectedFileTask?.optionItemList[0].optionItemValue}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.optionItem2"))}</dt>
|
||||
@ -107,6 +105,10 @@ export const FilePropertyPopup: React.FC<FilePropertyPopupProps> = (props) => {
|
||||
<dd>{selectedFileTask?.jobNumber ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.status"))}</dt>
|
||||
<dd>{selectedFileTask?.status ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.uploadDate"))}</dt>
|
||||
<dd>{selectedFileTask?.audioUploadedDate ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.transcriptionist"))}</dt>
|
||||
<dd>{selectedFileTask?.typist?.name ?? ""}</dd>
|
||||
<dt>
|
||||
{t(
|
||||
getTranslationID("dictationPage.label.transcriptionStartedDate")
|
||||
@ -119,8 +121,6 @@ export const FilePropertyPopup: React.FC<FilePropertyPopupProps> = (props) => {
|
||||
)}
|
||||
</dt>
|
||||
<dd>{selectedFileTask?.transcriptionFinishedDate ?? ""}</dd>
|
||||
<dt>{t(getTranslationID("dictationPage.label.transcriptionist"))}</dt>
|
||||
<dd>{selectedFileTask?.typist?.name ?? ""}</dd>
|
||||
<dd className={`${styles.full} ${styles.alignRight}`}>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a onClick={closePopup} className={`${styles.buttonText}`}>
|
||||
|
||||
@ -136,17 +136,22 @@ export const EditOptionItemsPopup: React.FC<EditOptionItemsPopupProps> = (
|
||||
getTranslationID("worktypeIdSetting.label.itemLabel")
|
||||
)}
|
||||
</th>
|
||||
{
|
||||
// https://so-net.backlog.jp/board/OMDS_IS?selectedIssueKey=OMDS_IS-289
|
||||
// initialValueとdefaultValueの項目名を入れ替え
|
||||
// その結果 initialValueの項目名がdefaultValueになり、defaultValueの項目名がinitialValueになる
|
||||
}
|
||||
<th className={styles.noLine}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"worktypeIdSetting.label.defaultValue"
|
||||
"worktypeIdSetting.label.initialValue"
|
||||
)
|
||||
)}
|
||||
</th>
|
||||
<th>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"worktypeIdSetting.label.initialValue"
|
||||
"worktypeIdSetting.label.defaultValue"
|
||||
)
|
||||
)}
|
||||
</th>
|
||||
|
||||
@ -129,13 +129,13 @@
|
||||
"roleChangeError": "Die Benutzerrolle kann nicht geändert werden. Die angezeigten Informationen sind möglicherweise veraltet. Aktualisieren Sie daher bitte den Bildschirm, um den neuesten Status anzuzeigen.",
|
||||
"encryptionPasswordCorrectError": "Das Verschlüsselungskennwort entspricht nicht den Regeln.",
|
||||
"alreadyLicenseDeallocatedError": "Die zugewiesene Lizenz wurde bereits storniert. Die angezeigten Informationen sind möglicherweise veraltet. Aktualisieren Sie daher bitte den Bildschirm, um den neuesten Status anzuzeigen.",
|
||||
"UserDeletionLicenseActiveError": "(de)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"TypistDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"AdminUserDeletionError": "(de)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"TypistUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"AuthorUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"TypistUserDeletionTranscriptionistGroupError": "(de)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"AuthorDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
"userDeletionLicenseActiveError": "(de)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"typistDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"adminUserDeletionError": "(de)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"typistUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"authorUserDeletionTranscriptionTaskError": "(de)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"typistUserDeletionTranscriptionistGroupError": "(de)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"authorDeletionRoutingRuleError": "(de)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Benutzer",
|
||||
@ -220,7 +220,7 @@
|
||||
},
|
||||
"label": {
|
||||
"title": "Diktate",
|
||||
"displayInfomation": "Informations sur l'affichage",
|
||||
"displayInfomation": "Informationen anzeigen",
|
||||
"jobNumber": "Aufgabennummer",
|
||||
"status": "Status",
|
||||
"priority": "Priorität",
|
||||
@ -258,7 +258,7 @@
|
||||
"changeTranscriptionist": "Transkriptionist ändern",
|
||||
"deleteDictation": "Diktat löschen",
|
||||
"selectedTranscriptionist": "Ausgewählter transkriptionist",
|
||||
"poolTranscriptionist": "Transkriptionsliste",
|
||||
"poolTranscriptionist": "Liste der Transkriptionisten",
|
||||
"fileBackup": "Dateisicherung",
|
||||
"downloadForBackup": "Zur Sicherung herunterladen",
|
||||
"applications": "Desktopanwendung",
|
||||
@ -397,7 +397,7 @@
|
||||
"templateOptional": "Vorlage (Optional)",
|
||||
"editRule": "Regel bearbeiten",
|
||||
"selected": "Ausgewählter transkriptionist",
|
||||
"pool": "Transkriptionsliste",
|
||||
"pool": "Liste der Transkriptionisten",
|
||||
"selectAuthor": "Autoren-ID auswählen",
|
||||
"selectWorktypeId": "Aufgabentypkennung auswählen",
|
||||
"selectTemplate": "Vorlage auswählen"
|
||||
@ -411,13 +411,13 @@
|
||||
},
|
||||
"typistGroupSetting": {
|
||||
"label": {
|
||||
"title": "Transkriptionistengruppe",
|
||||
"title": "Gruppeneinstellung für Transkriptionisten",
|
||||
"addGroup": "Gruppe hinzufügen",
|
||||
"groupName": "Gruppenname",
|
||||
"addTypistGroup": "Transkriptionist Gruppe hinzufügen",
|
||||
"transcriptionist": "Transkriptionist",
|
||||
"selected": "Ausgewählter transkriptionist",
|
||||
"pool": "Transkriptionsliste",
|
||||
"pool": "Liste der Transkriptionisten",
|
||||
"add": "Hinzufügen",
|
||||
"remove": "Entfernen",
|
||||
"editTypistGroup": "Transkriptionistengruppe bearbeiten"
|
||||
@ -467,7 +467,7 @@
|
||||
},
|
||||
"templateFilePage": {
|
||||
"label": {
|
||||
"title": "Vorlagenliste",
|
||||
"title": "Vorlageneinstellung",
|
||||
"addTemplate": "Vorlage hinzufügen",
|
||||
"fileName": "Dateiname",
|
||||
"chooseFile": "Datei aussuchen",
|
||||
@ -475,6 +475,10 @@
|
||||
"fileSizeTerms": "Die maximale Dateigröße, die gespeichert werden kann, beträgt 5 MB.",
|
||||
"fileSizeError": "Die ausgewählte Dateigröße ist zu groß. Bitte wählen Sie eine Datei mit einer Größe von 5 MB oder weniger aus.",
|
||||
"fileEmptyError": "Dateiauswahl ist erforderlich. Bitte wählen Sie eine Datei aus."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "(de)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "(de)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
@ -515,7 +519,8 @@
|
||||
"emailAddress": "E-Mail-Addresse",
|
||||
"selectSecondaryAdministrator": "Sekundäradministrator auswählen",
|
||||
"saveChanges": "Änderungen speichern",
|
||||
"deleteAccount": "Konto löschen"
|
||||
"deleteAccount": "Konto löschen",
|
||||
"fileRetentionDays": "(de)自動ファイル削除までの保持日数"
|
||||
},
|
||||
"message": {
|
||||
"updateAccountFailedError": "Kontoinformationen konnten nicht gespeichert werden. Bitte aktualisieren Sie den Bildschirm und versuchen Sie es erneut."
|
||||
@ -570,5 +575,15 @@
|
||||
"job": "Aufgabe",
|
||||
"close": "Schließen"
|
||||
}
|
||||
},
|
||||
"fileDeleteSettingPopup": {
|
||||
"label": {
|
||||
"title": "(de)Auto File Delete Setting",
|
||||
"autoFileDeleteCheck": "(de)Auto file delete",
|
||||
"daysAnnotation": "(de)Number of days from transcription finished to delete the files.",
|
||||
"days": "(de)Days",
|
||||
"saveButton": "(de)Save Settings",
|
||||
"daysValidationError": "(de)Daysには1~999の数字を入力してください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,13 +129,13 @@
|
||||
"roleChangeError": "Unable to change the User Role. The displayed information may be outdated, so please refresh the screen to see the latest status.",
|
||||
"encryptionPasswordCorrectError": "Encryption password does not meet the rules.",
|
||||
"alreadyLicenseDeallocatedError": "Assigned license has already been canceled. The displayed information may be outdated, so please refresh the screen to see the latest status.",
|
||||
"UserDeletionLicenseActiveError": "ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"TypistDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"AdminUserDeletionError": "ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"TypistUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"AuthorUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"TypistUserDeletionTranscriptionistGroupError": "ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"AuthorDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
"userDeletionLicenseActiveError": "ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"typistDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"adminUserDeletionError": "ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"typistUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"authorUserDeletionTranscriptionTaskError": "ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"typistUserDeletionTranscriptionistGroupError": "ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"authorDeletionRoutingRuleError": "ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "User",
|
||||
@ -258,7 +258,7 @@
|
||||
"changeTranscriptionist": "Change Transcriptionist",
|
||||
"deleteDictation": "Delete Dictation",
|
||||
"selectedTranscriptionist": "Selected Transcriptionist",
|
||||
"poolTranscriptionist": "Transcription List",
|
||||
"poolTranscriptionist": "Transcriptionist List",
|
||||
"fileBackup": "File Backup",
|
||||
"downloadForBackup": "Download for backup",
|
||||
"applications": "Desktop Application",
|
||||
@ -397,7 +397,7 @@
|
||||
"templateOptional": "Template (Optional)",
|
||||
"editRule": "Edit Rule",
|
||||
"selected": "Selected Transcriptionist",
|
||||
"pool": "Transcription List",
|
||||
"pool": "Transcriptionist List",
|
||||
"selectAuthor": "Select Author ID",
|
||||
"selectWorktypeId": "Select Worktype ID",
|
||||
"selectTemplate": "Select Template"
|
||||
@ -411,13 +411,13 @@
|
||||
},
|
||||
"typistGroupSetting": {
|
||||
"label": {
|
||||
"title": "Transcriptionist Group",
|
||||
"title": "Transcriptionist Group Setting",
|
||||
"addGroup": "Add Group",
|
||||
"groupName": "Group Name",
|
||||
"addTypistGroup": "Add Transcriptionist Group",
|
||||
"transcriptionist": "Transcriptionist",
|
||||
"selected": "Selected Transcriptionist",
|
||||
"pool": "Transcription List",
|
||||
"pool": "Transcriptionist List",
|
||||
"add": "Add",
|
||||
"remove": "Remove",
|
||||
"editTypistGroup": "Edit Transcriptionist Group"
|
||||
@ -467,7 +467,7 @@
|
||||
},
|
||||
"templateFilePage": {
|
||||
"label": {
|
||||
"title": "Template List",
|
||||
"title": "Template Setting",
|
||||
"addTemplate": "Add Template",
|
||||
"fileName": "File Name",
|
||||
"chooseFile": "Select file",
|
||||
@ -475,6 +475,10 @@
|
||||
"fileSizeTerms": "The maximum file size that can be saved is 5MB.",
|
||||
"fileSizeError": "The selected file size is too large. Please select a file that is 5MB or less in size.",
|
||||
"fileEmptyError": "File selection is required. Please select a file."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
@ -515,7 +519,8 @@
|
||||
"emailAddress": "Email Address",
|
||||
"selectSecondaryAdministrator": "Select Secondary Administrator",
|
||||
"saveChanges": "Save Changes",
|
||||
"deleteAccount": "Delete Account"
|
||||
"deleteAccount": "Delete Account",
|
||||
"fileRetentionDays": "自動ファイル削除までの保持日数"
|
||||
},
|
||||
"message": {
|
||||
"updateAccountFailedError": "Failed to save account information. Please refresh the screen and try again."
|
||||
@ -570,5 +575,15 @@
|
||||
"job": "Job",
|
||||
"close": "Close"
|
||||
}
|
||||
},
|
||||
"fileDeleteSettingPopup": {
|
||||
"label": {
|
||||
"title": "Auto File Delete Setting",
|
||||
"autoFileDeleteCheck": "Auto file delete",
|
||||
"daysAnnotation": "Number of days from transcription finished to delete the files.",
|
||||
"days": "Days",
|
||||
"saveButton": "Save Settings",
|
||||
"daysValidationError": "Daysには1~999の数字を入力してください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,13 +129,13 @@
|
||||
"roleChangeError": "No se puede cambiar la función de usuario. La información mostrada puede estar desactualizada, así que actualice la pantalla para ver el estado más reciente.",
|
||||
"encryptionPasswordCorrectError": "La contraseña de cifrado no cumple con las reglas.",
|
||||
"alreadyLicenseDeallocatedError": "La licencia asignada ya ha sido cancelada. La información mostrada puede estar desactualizada, así que actualice la pantalla para ver el estado más reciente.",
|
||||
"UserDeletionLicenseActiveError": "(es)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"TypistDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"AdminUserDeletionError": "(es)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"TypistUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"AuthorUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"TypistUserDeletionTranscriptionistGroupError": "(es)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"AuthorDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
"userDeletionLicenseActiveError": "(es)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"typistDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"adminUserDeletionError": "(es)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"typistUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"authorUserDeletionTranscriptionTaskError": "(es)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"typistUserDeletionTranscriptionistGroupError": "(es)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"authorDeletionRoutingRuleError": "(es)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Usuario",
|
||||
@ -220,7 +220,7 @@
|
||||
},
|
||||
"label": {
|
||||
"title": "Dictado",
|
||||
"displayInfomation": "Informationen anzeigen",
|
||||
"displayInfomation": "Mostrar información",
|
||||
"jobNumber": "Número de trabajo",
|
||||
"status": "Estado",
|
||||
"priority": "Prioridad",
|
||||
@ -258,7 +258,7 @@
|
||||
"changeTranscriptionist": "Cambiar transcriptor",
|
||||
"deleteDictation": "Borrar dictado",
|
||||
"selectedTranscriptionist": "Transcriptor seleccionado",
|
||||
"poolTranscriptionist": "Lista de transcriptor",
|
||||
"poolTranscriptionist": "Lista de transcriptores",
|
||||
"fileBackup": "Copia de seguridad de archivos",
|
||||
"downloadForBackup": "Descargar para respaldo",
|
||||
"applications": "Aplicación de escritorio",
|
||||
@ -397,7 +397,7 @@
|
||||
"templateOptional": "Plantilla (Opcional)",
|
||||
"editRule": "Editar regla",
|
||||
"selected": "Transcriptor seleccionado",
|
||||
"pool": "Lista de transcriptor",
|
||||
"pool": "Lista de transcriptores",
|
||||
"selectAuthor": "Seleccionar ID de autor",
|
||||
"selectWorktypeId": "Seleccionar ID de tipo de trabajo",
|
||||
"selectTemplate": "Seleccionar Plantilla"
|
||||
@ -411,13 +411,13 @@
|
||||
},
|
||||
"typistGroupSetting": {
|
||||
"label": {
|
||||
"title": "Grupo de transcriptor",
|
||||
"title": "Configuración del grupo transcriptor",
|
||||
"addGroup": "Agregar grupo",
|
||||
"groupName": "Nombre del grupo",
|
||||
"addTypistGroup": "Agregar grupo transcriptor",
|
||||
"transcriptionist": "Transcriptor",
|
||||
"selected": "Transcriptor seleccionado",
|
||||
"pool": "Lista de transcriptor",
|
||||
"pool": "Lista de transcriptores",
|
||||
"add": "Añadir",
|
||||
"remove": "Eliminar",
|
||||
"editTypistGroup": "Editar grupo transcriptor"
|
||||
@ -467,7 +467,7 @@
|
||||
},
|
||||
"templateFilePage": {
|
||||
"label": {
|
||||
"title": "Lista de plantillas",
|
||||
"title": "Configuración de plantilla",
|
||||
"addTemplate": "Agregar plantilla",
|
||||
"fileName": "Nombre del archivo",
|
||||
"chooseFile": "Seleccione Archivo",
|
||||
@ -475,6 +475,10 @@
|
||||
"fileSizeTerms": "El tamaño máximo de archivo que se puede guardar es de 5 MB.",
|
||||
"fileSizeError": "El tamaño del archivo seleccionado es demasiado grande. Seleccione un archivo que tenga un tamaño de 5 MB o menos.",
|
||||
"fileEmptyError": "Se requiere selección de archivos. Por favor seleccione un archivo."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "(es)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "(es)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
@ -515,7 +519,8 @@
|
||||
"emailAddress": "Dirección de correo electrónico",
|
||||
"selectSecondaryAdministrator": "Seleccionar administrador secundario",
|
||||
"saveChanges": "Guardar cambios",
|
||||
"deleteAccount": "Borrar cuenta"
|
||||
"deleteAccount": "Borrar cuenta",
|
||||
"fileRetentionDays": "(es)自動ファイル削除までの保持日数"
|
||||
},
|
||||
"message": {
|
||||
"updateAccountFailedError": "No se pudo guardar la información de la cuenta. Actualice la pantalla e inténtelo de nuevo."
|
||||
@ -570,5 +575,15 @@
|
||||
"job": "Trabajo",
|
||||
"close": "Cerrar"
|
||||
}
|
||||
},
|
||||
"fileDeleteSettingPopup": {
|
||||
"label": {
|
||||
"title": "(es)Auto File Delete Setting",
|
||||
"autoFileDeleteCheck": "(es)Auto file delete",
|
||||
"daysAnnotation": "(es)Number of days from transcription finished to delete the files.",
|
||||
"days": "(es)Days",
|
||||
"saveButton": "(es)Save Settings",
|
||||
"daysValidationError": "(es)Daysには1~999の数字を入力してください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,13 +129,13 @@
|
||||
"roleChangeError": "Impossible de modifier le rôle de l'utilisateur. Les informations affichées peuvent être obsolètes, veuillez donc actualiser l'écran pour voir le dernier statut.",
|
||||
"encryptionPasswordCorrectError": "Le mot de passe de cryptage n'est pas conforme aux règles.",
|
||||
"alreadyLicenseDeallocatedError": "La licence attribuée a déjà été annulée. Les informations affichées peuvent être obsolètes, veuillez donc actualiser l'écran pour voir le dernier statut.",
|
||||
"UserDeletionLicenseActiveError": "(fr)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"TypistDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"AdminUserDeletionError": "(fr)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"TypistUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"AuthorUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"TypistUserDeletionTranscriptionistGroupError": "(fr)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"AuthorDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
"userDeletionLicenseActiveError": "(fr)ユーザーの削除に失敗しました。対象ユーザーのライセンス割り当てを解除してください。",
|
||||
"typistDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象Transcriptionistを外してください。",
|
||||
"adminUserDeletionError": "(fr)ユーザーの削除に失敗しました。アカウント画面で対象ユーザーをPrimary/Secondary Administratorから外してください。",
|
||||
"typistUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面でタスクのルーティングから対象Transcriptionistを外してください。",
|
||||
"authorUserDeletionTranscriptionTaskError": "(fr)ユーザーの削除に失敗しました。Dictation画面で対象AuthorのAuthorIDが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。",
|
||||
"typistUserDeletionTranscriptionistGroupError": "(fr)ユーザーの削除に失敗しました。Workflow画面でTranscriptionistGroupから対象Transcriptionistを外してください。",
|
||||
"authorDeletionRoutingRuleError": "(fr)ユーザーの削除に失敗しました。Workflow画面でルーティングルールから対象AuthorのAuthorIDを外してください。"
|
||||
},
|
||||
"label": {
|
||||
"title": "Utilisateur",
|
||||
@ -258,7 +258,7 @@
|
||||
"changeTranscriptionist": "Changer de transcriptionniste ",
|
||||
"deleteDictation": "Supprimer la dictée",
|
||||
"selectedTranscriptionist": "Transcriptionniste sélectionné",
|
||||
"poolTranscriptionist": "Liste de transcriptionniste",
|
||||
"poolTranscriptionist": "Liste des transcripteurs",
|
||||
"fileBackup": "Sauvegarde de fichiers",
|
||||
"downloadForBackup": "Télécharger pour sauvegarde",
|
||||
"applications": "Application de bureau",
|
||||
@ -397,7 +397,7 @@
|
||||
"templateOptional": "Masque (Facultatif)",
|
||||
"editRule": "Modifier la règle",
|
||||
"selected": "Transcriptionniste sélectionné",
|
||||
"pool": "Liste de transcriptionniste",
|
||||
"pool": "Liste des transcripteurs",
|
||||
"selectAuthor": "Sélectionner le Identifiant Auteur",
|
||||
"selectWorktypeId": "Sélectionner le Identifiant du Type de travail",
|
||||
"selectTemplate": "Sélectionner le Masque"
|
||||
@ -411,13 +411,13 @@
|
||||
},
|
||||
"typistGroupSetting": {
|
||||
"label": {
|
||||
"title": "Groupe de transcriptionniste",
|
||||
"title": "Paramètre de groupe de transcriptionniste",
|
||||
"addGroup": "Ajouter groupe",
|
||||
"groupName": "Nom de groupe",
|
||||
"addTypistGroup": "Ajouter un groupe de transcripteurs",
|
||||
"transcriptionist": "Transcriptionniste",
|
||||
"selected": "Transcriptionniste sélectionné",
|
||||
"pool": "Liste de transcriptionniste",
|
||||
"pool": "Liste des transcripteurs",
|
||||
"add": "Ajouter",
|
||||
"remove": "Supprimer",
|
||||
"editTypistGroup": "Modifier le groupe de transcripteurs"
|
||||
@ -467,7 +467,7 @@
|
||||
},
|
||||
"templateFilePage": {
|
||||
"label": {
|
||||
"title": "Liste des modèles",
|
||||
"title": "Paramètre de modèle",
|
||||
"addTemplate": "Ajouter un modèle",
|
||||
"fileName": "Nom de fichier",
|
||||
"chooseFile": "Choisir le fichier",
|
||||
@ -475,6 +475,10 @@
|
||||
"fileSizeTerms": "La taille maximale du fichier pouvant être enregistré est de 5 Mo.",
|
||||
"fileSizeError": "La taille du fichier sélectionné est trop grande. Veuillez sélectionner un fichier d'une taille maximale de 5 Mo.",
|
||||
"fileEmptyError": "La sélection de fichiers est requise. Veuillez sélectionner un fichier."
|
||||
},
|
||||
"message": {
|
||||
"deleteFailedWorkflowAssigned": "(fr)テンプレートファイルの削除に失敗しました。Workflow画面でルーティングルールから対象テンプレートファイルを外してください。",
|
||||
"deleteFailedTaskAssigned": "(fr)テンプレートファイルの削除に失敗しました。Dictation画面で対象テンプレートファイルが設定されているタスクの中で、文字起こしが未完了のタスクを削除またはFinishedにしてください。"
|
||||
}
|
||||
},
|
||||
"partnerPage": {
|
||||
@ -515,7 +519,8 @@
|
||||
"emailAddress": "Adresse e-mail",
|
||||
"selectSecondaryAdministrator": "Sélectionner le administrateur secondaire",
|
||||
"saveChanges": "Sauvegarder les modifications",
|
||||
"deleteAccount": "Supprimer le compte"
|
||||
"deleteAccount": "Supprimer le compte",
|
||||
"fileRetentionDays": "(fr)自動ファイル削除までの保持日数"
|
||||
},
|
||||
"message": {
|
||||
"updateAccountFailedError": "Échec de l'enregistrement des informations du compte. Veuillez actualiser l'écran et réessayer."
|
||||
@ -570,5 +575,15 @@
|
||||
"job": "Tâches",
|
||||
"close": "Fermer"
|
||||
}
|
||||
},
|
||||
"fileDeleteSettingPopup": {
|
||||
"label": {
|
||||
"title": "(fr)Auto File Delete Setting",
|
||||
"autoFileDeleteCheck": "(fr)Auto file delete",
|
||||
"daysAnnotation": "(fr)Number of days from transcription finished to delete the files.",
|
||||
"days": "(fr)Days",
|
||||
"saveButton": "(fr)Save Settings",
|
||||
"daysValidationError": "(fr)Daysには1~999の数字を入力してください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
dictation_server/src/common/validators/authorId.validator.ts
Normal file
36
dictation_server/src/common/validators/authorId.validator.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import {
|
||||
ValidatorConstraint,
|
||||
ValidatorConstraintInterface,
|
||||
ValidationArguments,
|
||||
ValidationOptions,
|
||||
registerDecorator,
|
||||
} from 'class-validator';
|
||||
|
||||
// 大文字英数字とアンダースコアのみを許可するバリデータ
|
||||
@ValidatorConstraint({ name: 'IsAuthorId', async: false })
|
||||
export class IsAuthorId implements ValidatorConstraintInterface {
|
||||
validate(value: any, args: ValidationArguments) {
|
||||
return /^[A-Z0-9_]*$/.test(value);
|
||||
}
|
||||
defaultMessage(args: ValidationArguments) {
|
||||
return `${args.property} should be uppercase alphanumeric and underscore only`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 大文字英数字のみを許可するバリデータ
|
||||
* @param [validationOptions]
|
||||
* @returns
|
||||
*/
|
||||
export function IsAuthorIdValid(validationOptions?: ValidationOptions) {
|
||||
return function (object: object, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: 'IsAuthorId',
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
constraints: [],
|
||||
options: validationOptions,
|
||||
validator: IsAuthorId,
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -19,7 +19,7 @@ export class IsRecorderAllowedCharacters
|
||||
}
|
||||
|
||||
// 正規表現でWorktypeIDのチェックを行う
|
||||
// 以下の禁則文字を除く半角英数記号
|
||||
// 以下の禁則文字を除く大文字英数記号
|
||||
// \ (backslash)
|
||||
// / (forward slash)
|
||||
// : (colon)
|
||||
@ -31,7 +31,7 @@ export class IsRecorderAllowedCharacters
|
||||
// | (vertical bar)
|
||||
// . (period)
|
||||
const regex =
|
||||
/^(?!.*\\)(?!.*\/)(?!.*:)(?!.*\*)(?!.*\?)(?!.*")(?!.*<)(?!.*>)(?!.*\|)(?!.*\.)[ -~]+$/;
|
||||
/^(?!.*\\)(?!.*\/)(?!.*:)(?!.*\*)(?!.*\?)(?!.*")(?!.*<)(?!.*>)(?!.*\|)(?!.*\.)[A-Z0-9 !#$%&'()+,\-;=@\[\]^_`{}~]*$/;
|
||||
return regex.test(value);
|
||||
}
|
||||
|
||||
|
||||
@ -134,8 +134,8 @@ describe('createAccount', () => {
|
||||
},
|
||||
});
|
||||
|
||||
let _subject: string = "";
|
||||
let _url: string | undefined = "";
|
||||
let _subject: string = '';
|
||||
let _url: string | undefined = '';
|
||||
overrideSendgridService(service, {
|
||||
sendMail: async (
|
||||
context: Context,
|
||||
@ -197,7 +197,9 @@ describe('createAccount', () => {
|
||||
|
||||
// 想定通りのメールが送られているか確認
|
||||
expect(_subject).toBe('User Registration Notification [U-102]');
|
||||
expect(_url?.startsWith('http://localhost:8081/mail-confirm?verify=')).toBeTruthy();
|
||||
expect(
|
||||
_url?.startsWith('http://localhost:8081/mail-confirm?verify='),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('アカウントを作成がAzure AD B2Cへの通信失敗によって失敗すると500エラーが発生する', async () => {
|
||||
@ -5727,8 +5729,8 @@ describe('アカウント情報更新', () => {
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
let _subject: string = "";
|
||||
let _url: string | undefined = "";
|
||||
let _subject: string = '';
|
||||
let _url: string | undefined = '';
|
||||
overrideSendgridService(service, {
|
||||
sendMail: async (
|
||||
context: Context,
|
||||
|
||||
@ -18,14 +18,21 @@ import {
|
||||
} from './test/utility';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { Context, makeContext } from '../../common/log';
|
||||
import { ADB2C_SIGN_IN_TYPE, LICENSE_ALLOCATED_STATUS, LICENSE_TYPE } from '../../constants';
|
||||
import {
|
||||
ADB2C_SIGN_IN_TYPE,
|
||||
LICENSE_ALLOCATED_STATUS,
|
||||
LICENSE_TYPE,
|
||||
} from '../../constants';
|
||||
import {
|
||||
makeHierarchicalAccounts,
|
||||
makeTestSimpleAccount,
|
||||
makeTestUser,
|
||||
} from '../../common/test/utility';
|
||||
import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service';
|
||||
import { overrideAdB2cService, overrideSendgridService } from '../../common/test/overrides';
|
||||
import {
|
||||
overrideAdB2cService,
|
||||
overrideSendgridService,
|
||||
} from '../../common/test/overrides';
|
||||
import { truncateAllTable } from '../../common/test/init';
|
||||
|
||||
describe('ライセンス注文', () => {
|
||||
@ -672,7 +679,10 @@ describe('ライセンス割り当て', () => {
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: dealerId } = await makeTestSimpleAccount(source, { company_name: "DEALER_COMPANY", tier: 4 });
|
||||
const { id: dealerId } = await makeTestSimpleAccount(source, {
|
||||
company_name: 'DEALER_COMPANY',
|
||||
tier: 4,
|
||||
});
|
||||
const { id: dealerAdminId } = await makeTestUser(source, {
|
||||
account_id: dealerId,
|
||||
external_id: 'userId_admin',
|
||||
@ -682,7 +692,7 @@ describe('ライセンス割り当て', () => {
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source, {
|
||||
parent_account_id: dealerId,
|
||||
tier: 5
|
||||
tier: 5,
|
||||
});
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -740,7 +750,7 @@ describe('ライセンス割り当て', () => {
|
||||
},
|
||||
],
|
||||
}));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
overrideSendgridService(service, {
|
||||
|
||||
@ -138,9 +138,8 @@ export const createTask = async (
|
||||
label: `label${i}:audio_file_id${audioFileIdentifiers[0].id}`,
|
||||
value: `value${i}:audio_file_id${audioFileIdentifiers[0].id}`,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
await datasource.getRepository(AudioOptionItem).insert(audioOptionItems);
|
||||
|
||||
const audioFile = audioFileIdentifiers.pop() as AudioFile;
|
||||
@ -161,7 +160,7 @@ export const createTask = async (
|
||||
return { taskId: task.id, audioFileId: audioFile.id };
|
||||
};
|
||||
|
||||
export const createAudioFile = async(
|
||||
export const createAudioFile = async (
|
||||
datasource: DataSource,
|
||||
account_id: number,
|
||||
owner_user_id: number,
|
||||
@ -189,7 +188,7 @@ export const createAudioFile = async(
|
||||
});
|
||||
const audioFile = audioFileIdentifiers.pop() as AudioFile;
|
||||
return { audioFileId: audioFile.id };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
} from '../../../common/validators/encryptionPassword.validator';
|
||||
import { IsRoleAuthorDataValid } from '../../../common/validators/roleAuthor.validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsAuthorIdValid } from '../../../common/validators/authorId.validator';
|
||||
|
||||
export class ConfirmRequest {
|
||||
@ApiProperty()
|
||||
@ -90,6 +91,7 @@ export class SignupRequest {
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsRoleAuthorDataValid()
|
||||
@IsAuthorIdValid()
|
||||
authorId?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@ -225,6 +227,7 @@ export class PostUpdateUserRequest {
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsRoleAuthorDataValid()
|
||||
@IsAuthorIdValid()
|
||||
authorId?: string;
|
||||
|
||||
@ApiProperty()
|
||||
|
||||
@ -18,4 +18,4 @@ export class TypistGroupNameAlreadyExistError extends Error {
|
||||
super(message);
|
||||
this.name = 'TypistGroupNameAlreadyExistError';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user