Merge branch 'develop'
This commit is contained in:
commit
bea541ed24
@ -2,20 +2,11 @@
|
||||
# FROM mcr.microsoft.com/azure-functions/node:4-node18-appservice
|
||||
FROM mcr.microsoft.com/azure-functions/node:4-node18
|
||||
|
||||
RUN /bin/cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
|
||||
echo "Asia/Tokyo" > /etc/timezone
|
||||
|
||||
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
|
||||
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
|
||||
|
||||
RUN apt-get -y update
|
||||
RUN apt-get install -y \
|
||||
curl \
|
||||
gnupg
|
||||
RUN apt-get install -y nodejs
|
||||
COPY . /home/site/wwwroot
|
||||
|
||||
WORKDIR /home/site/wwwroot
|
||||
RUN cd /home/site/wwwroot
|
||||
COPY ./ /home/site/wwwroot
|
||||
|
||||
RUN npm install -g npm
|
||||
RUN cd /home/site/wwwroot && \
|
||||
npm install && \
|
||||
npm run build
|
||||
@ -42,7 +42,6 @@ jobs:
|
||||
resourceGroupName: 'odms-prod-rg'
|
||||
slotName: 'staging'
|
||||
containers: 'crodmsregistrymaintenance.azurecr.io/odmscloud/staging/dictation:$(Build.SourceVersion)'
|
||||
# TODO: stagingパイプライン実装時、staging用のイメージに変更する
|
||||
- job: frontend_deploy
|
||||
dependsOn: backend_deploy
|
||||
condition: succeeded('backend_deploy')
|
||||
@ -134,12 +133,12 @@ jobs:
|
||||
inputs:
|
||||
script: >2
|
||||
# DB接続情報書き換え
|
||||
sed -i -e "s/DB_NAME/$(db-name)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_PASS/$(db-pass)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_USERNAME/$(db-user)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_PORT/$(db-port)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_HOST/$(db-host)/g" ./dictation_server/db/dbconfig.yml
|
||||
sql-migrate --version
|
||||
cat ./dictation_server/db/dbconfig.yml
|
||||
# migration実行
|
||||
sql-migrate up -config=./dictation_server/db/dbconfig.yml -env=ci
|
||||
sed -i -e "s/DB_NAME/$(db-name)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_PASS/$(admin-db-pass)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_USERNAME/$(admin-db-user)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_PORT/$(db-port)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_HOST/$(db-host)/g" ./dictation_server/db/dbconfig.yml
|
||||
sql-migrate --version
|
||||
cat ./dictation_server/db/dbconfig.yml
|
||||
# migration実行
|
||||
sql-migrate up -config=./dictation_server/db/dbconfig.yml -env=ci
|
||||
@ -198,29 +198,93 @@ jobs:
|
||||
condition: succeeded('frontend_build_production')
|
||||
displayName: Backend Deploy
|
||||
pool:
|
||||
name: odms-deploy-pipeline
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
# TODO: Productionと同様にデプロイを行う
|
||||
- task: AzureWebAppContainer@1
|
||||
inputs:
|
||||
azureSubscription: 'omds-service-connection-stg'
|
||||
appName: 'app-odms-dictation-stg'
|
||||
deployToSlotOrASE: true
|
||||
resourceGroupName: 'stg-application-rg'
|
||||
slotName: 'staging'
|
||||
containers: 'crodmsregistrymaintenance.azurecr.io/odmscloud/staging/dictation:$(Build.SourceVersion)'
|
||||
- job: frontend_deploy
|
||||
dependsOn: backend_deploy
|
||||
condition: succeeded('backend_deploy')
|
||||
displayName: Deploy Frontend Files
|
||||
variables:
|
||||
storageAccountName: saomdspipeline
|
||||
containerName: staging
|
||||
environment: staging
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: AzureCLI@2
|
||||
inputs:
|
||||
azureSubscription: 'omds-service-connection-stg'
|
||||
scriptType: 'bash'
|
||||
scriptLocation: 'inlineScript'
|
||||
inlineScript: |
|
||||
az storage blob download \
|
||||
--auth-mode login \
|
||||
--account-name $(storageAccountName) \
|
||||
--container-name $(environment) \
|
||||
--name $(Build.SourceVersion).zip \
|
||||
--file $(Build.SourcesDirectory)/$(Build.SourceVersion).zip
|
||||
- task: Bash@3
|
||||
displayName: Bash Script
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: unzip $(Build.SourcesDirectory)/$(Build.SourceVersion).zip -d $(Build.SourcesDirectory)/$(Build.SourceVersion)
|
||||
- task: AzureStaticWebApp@0
|
||||
displayName: 'Static Web App: '
|
||||
inputs:
|
||||
workingDirectory: '$(Build.SourcesDirectory)'
|
||||
app_location: '/$(Build.SourceVersion)'
|
||||
config_file_location: /dictation_client
|
||||
skip_app_build: true
|
||||
skip_api_build: true
|
||||
is_static_export: false
|
||||
verbose: false
|
||||
azure_static_web_apps_api_token: $(STATIC_DICTATION_DEPLOYMENT_TOKEN)
|
||||
- job: smoke_test
|
||||
dependsOn: frontend_deploy
|
||||
condition: succeeded('frontend_deploy')
|
||||
displayName: 'smoke test'
|
||||
pool:
|
||||
name: odms-deploy-pipeline
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
# TODO: Productionと同様にデプロイを行う
|
||||
# スモークテスト用にjobを確保
|
||||
- job: swap_slot
|
||||
dependsOn: smoke_test
|
||||
condition: succeeded('smoke_test')
|
||||
displayName: 'Swap Staging and Production'
|
||||
pool:
|
||||
name: odms-deploy-pipeline
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: AzureAppServiceManage@0
|
||||
displayName: 'Azure App Service Manage: app-odms-dictation-stg'
|
||||
inputs:
|
||||
azureSubscription: 'omds-service-connection-stg'
|
||||
action: 'Swap Slots'
|
||||
WebAppName: 'app-odms-dictation-stg'
|
||||
ResourceGroupName: 'stg-application-rg'
|
||||
SourceSlot: 'staging'
|
||||
SwapWithProduction: true
|
||||
- job: migration
|
||||
dependsOn: frontend_deploy
|
||||
condition: succeeded('frontend_deploy')
|
||||
dependsOn: swap_slot
|
||||
condition: succeeded('swap_slot')
|
||||
displayName: DB migration
|
||||
pool:
|
||||
name: odms-deploy-pipeline
|
||||
@ -228,4 +292,22 @@ jobs:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
# TODO: Productionと同様にマイグレーションを行う
|
||||
- task: AzureKeyVault@2
|
||||
displayName: 'Azure Key Vault: kv-odms-secret-stg'
|
||||
inputs:
|
||||
ConnectedServiceName: 'omds-service-connection-stg'
|
||||
KeyVaultName: kv-odms-secret-stg
|
||||
- task: CmdLine@2
|
||||
displayName: migration
|
||||
inputs:
|
||||
script: >2
|
||||
# DB接続情報書き換え
|
||||
sed -i -e "s/DB_NAME/$(db-name)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_PASS/$(admin-db-pass)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_USERNAME/$(admin-db-user)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_PORT/$(db-port)/g" ./dictation_server/db/dbconfig.yml
|
||||
sed -i -e "s/DB_HOST/$(db-host)/g" ./dictation_server/db/dbconfig.yml
|
||||
sql-migrate --version
|
||||
cat ./dictation_server/db/dbconfig.yml
|
||||
# migration実行
|
||||
sql-migrate up -config=./dictation_server/db/dbconfig.yml -env=ci
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,17 +8,14 @@
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"location": "Japan East",
|
||||
"name": "[parameters('namespaces_ntfns_odms_dev_name')]",
|
||||
"properties": {
|
||||
"createdAt": "2023-07-24T01:26:14.6870000Z",
|
||||
"critical": false,
|
||||
"enabled": true,
|
||||
"namespaceType": "NotificationHub",
|
||||
"provisioningState": "Succeeded",
|
||||
"serviceBusEndpoint": "[concat('https://', parameters('namespaces_ntfns_odms_dev_name'), '.servicebus.windows.net:443/')]",
|
||||
"status": "Active",
|
||||
"updatedAt": "2023-07-24T01:26:14.7370000Z"
|
||||
"publicNetworkAccess": "Enabled",
|
||||
"status": "Created"
|
||||
},
|
||||
"sku": {
|
||||
"name": "Free"
|
||||
@ -26,11 +23,10 @@
|
||||
"type": "Microsoft.NotificationHubs/namespaces"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_dev_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_dev_name'), '/RootManageSharedAccessKey')]",
|
||||
"properties": {
|
||||
"rights": [
|
||||
@ -39,32 +35,31 @@
|
||||
"Send"
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/AuthorizationRules"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/authorizationRules"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_dev_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_dev_name'), '/ntf-odms-dev')]",
|
||||
"properties": {
|
||||
"authorizationRules": [],
|
||||
"name": "ntf-odms-dev",
|
||||
"registrationTtl": "10675199.02:48:05.4775807"
|
||||
},
|
||||
"tags": {
|
||||
"Project": "OMDS",
|
||||
"environment": "develop"
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/NotificationHubs"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/NotificationHubs', parameters('namespaces_ntfns_odms_dev_name'), 'ntf-odms-dev')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs', parameters('namespaces_ntfns_odms_dev_name'), 'ntf-odms-dev')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_dev_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_dev_name'), '/ntf-odms-dev/DefaultFullSharedAccessSignature')]",
|
||||
"properties": {
|
||||
"rights": [
|
||||
@ -73,22 +68,21 @@
|
||||
"Send"
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/NotificationHubs/AuthorizationRules"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs/authorizationRules"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/NotificationHubs', parameters('namespaces_ntfns_odms_dev_name'), 'ntf-odms-dev')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs', parameters('namespaces_ntfns_odms_dev_name'), 'ntf-odms-dev')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_dev_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_dev_name'), '/ntf-odms-dev/DefaultListenSharedAccessSignature')]",
|
||||
"properties": {
|
||||
"rights": [
|
||||
"Listen"
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/NotificationHubs/AuthorizationRules"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs/authorizationRules"
|
||||
}
|
||||
],
|
||||
"variables": {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,17 +8,14 @@
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"location": "Japan East",
|
||||
"name": "[parameters('namespaces_ntfns_odms_stg_name')]",
|
||||
"properties": {
|
||||
"createdAt": "2023-07-25T01:57:35.5400000Z",
|
||||
"critical": false,
|
||||
"enabled": true,
|
||||
"namespaceType": "NotificationHub",
|
||||
"provisioningState": "Succeeded",
|
||||
"serviceBusEndpoint": "[concat('https://', parameters('namespaces_ntfns_odms_stg_name'), '.servicebus.windows.net:443/')]",
|
||||
"status": "Active",
|
||||
"updatedAt": "2023-07-25T01:57:35.5970000Z"
|
||||
"publicNetworkAccess": "Enabled",
|
||||
"status": "Created"
|
||||
},
|
||||
"sku": {
|
||||
"name": "Free"
|
||||
@ -26,11 +23,10 @@
|
||||
"type": "Microsoft.NotificationHubs/namespaces"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_stg_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_stg_name'), '/RootManageSharedAccessKey')]",
|
||||
"properties": {
|
||||
"rights": [
|
||||
@ -39,32 +35,31 @@
|
||||
"Send"
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/AuthorizationRules"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/authorizationRules"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_stg_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_stg_name'), '/ntf-odms-stg')]",
|
||||
"properties": {
|
||||
"authorizationRules": [],
|
||||
"name": "ntf-odms-stg",
|
||||
"registrationTtl": "10675199.02:48:05.4775807"
|
||||
},
|
||||
"tags": {
|
||||
"Project": "OMDS",
|
||||
"environment": "staging"
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/NotificationHubs"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/NotificationHubs', parameters('namespaces_ntfns_odms_stg_name'), 'ntf-odms-stg')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs', parameters('namespaces_ntfns_odms_stg_name'), 'ntf-odms-stg')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_stg_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_stg_name'), '/ntf-odms-stg/DefaultFullSharedAccessSignature')]",
|
||||
"properties": {
|
||||
"rights": [
|
||||
@ -73,22 +68,21 @@
|
||||
"Send"
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/NotificationHubs/AuthorizationRules"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs/authorizationRules"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-04-01",
|
||||
"apiVersion": "2023-09-01",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/NotificationHubs', parameters('namespaces_ntfns_odms_stg_name'), 'ntf-odms-stg')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs', parameters('namespaces_ntfns_odms_stg_name'), 'ntf-odms-stg')]",
|
||||
"[resourceId('Microsoft.NotificationHubs/namespaces', parameters('namespaces_ntfns_odms_stg_name'))]"
|
||||
],
|
||||
"location": "Japan East",
|
||||
"name": "[concat(parameters('namespaces_ntfns_odms_stg_name'), '/ntf-odms-stg/DefaultListenSharedAccessSignature')]",
|
||||
"properties": {
|
||||
"rights": [
|
||||
"Listen"
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.NotificationHubs/namespaces/NotificationHubs/AuthorizationRules"
|
||||
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs/authorizationRules"
|
||||
}
|
||||
],
|
||||
"variables": {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@ export const errorCodes = [
|
||||
"E010401", // PONumber重複エラー
|
||||
"E010501", // アカウント不在エラー
|
||||
"E010502", // アカウント情報変更不可エラー
|
||||
"E010503", // 代行操作不許可エラー
|
||||
"E010601", // タスク変更不可エラー(タスクが変更できる状態でない、またはタスクが存在しない)
|
||||
"E010602", // タスク変更権限不足エラー
|
||||
"E010603", // タスク不在エラー
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
isAuthenticatedSelector,
|
||||
isTokenExpired,
|
||||
} from "features/auth/selectors";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppDispatch } from "app/store";
|
||||
import { clearToken } from "features/auth";
|
||||
import {
|
||||
clearToken,
|
||||
isAuthenticatedSelector,
|
||||
isTokenExpired,
|
||||
} from "features/auth";
|
||||
import { useMsal } from "@azure/msal-react";
|
||||
import { clearUserInfo } from "features/login";
|
||||
|
||||
|
||||
@ -2,8 +2,7 @@ import React, { useCallback } from "react";
|
||||
import { AppDispatch } from "app/store";
|
||||
import { decodeToken } from "common/decodeToken";
|
||||
import { useInterval } from "common/useInterval";
|
||||
import { updateTokenAsync } from "features/auth/operations";
|
||||
import { loadAccessToken } from "features/auth/utils";
|
||||
import { updateTokenAsync, loadAccessToken } from "features/auth";
|
||||
import { DateTime } from "luxon";
|
||||
import { useDispatch } from "react-redux";
|
||||
// アクセストークンを更新する基準の秒数
|
||||
|
||||
@ -1,22 +1,30 @@
|
||||
// 代行操作中に表示するコンポーネント
|
||||
// ------------------------------------------------------
|
||||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import React, { useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getTranslationID } from "translation";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {
|
||||
cleanupDelegateAccount,
|
||||
selectDelegatedCompanyName,
|
||||
} from "features/partner";
|
||||
import { clearDelegationToken } from "features/auth";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import styles from "../../styles/app.module.scss";
|
||||
import exit from "../../assets/images/exit.svg";
|
||||
import reportWhite from "../../assets/images/report_white.svg";
|
||||
import { getTranslationID } from "translation";
|
||||
|
||||
interface DelegationBarProps {
|
||||
delegatedCompanyName: string;
|
||||
}
|
||||
|
||||
export const DelegationBar: React.FC<DelegationBarProps> = (
|
||||
porps
|
||||
): JSX.Element => {
|
||||
const { delegatedCompanyName } = porps;
|
||||
export const DelegationBar: React.FC = (): JSX.Element => {
|
||||
const delegatedCompanyName = useSelector(selectDelegatedCompanyName);
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onClickExit = useCallback(() => {
|
||||
dispatch(clearDelegationToken());
|
||||
dispatch(cleanupDelegateAccount());
|
||||
navigate("/partners");
|
||||
}, [dispatch, navigate]);
|
||||
|
||||
return (
|
||||
<div className={styles.manageInfo}>
|
||||
@ -25,11 +33,13 @@ export const DelegationBar: React.FC<DelegationBarProps> = (
|
||||
{t(getTranslationID("common.label.operationInsteadOf"))}
|
||||
<span>{delegatedCompanyName}</span>
|
||||
</p>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions */}
|
||||
<img
|
||||
src={exit}
|
||||
className={styles.manageIconClose}
|
||||
alt="Exit"
|
||||
title="Exit"
|
||||
onClick={onClickExit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { getTranslationID } from "translation";
|
||||
import { HeaderMenus, LoginedPaths } from "./types";
|
||||
|
||||
export const HEADER_MENUS_ACCOUNT = "Account";
|
||||
@ -8,17 +9,45 @@ export const HEADER_MENUS_WORKFLOW = "Workflow";
|
||||
export const HEADER_MENUS_PARTNER = "Partners";
|
||||
export const HEADER_MENUS_XXX = "XXX"; // XXX 仮のタブ
|
||||
|
||||
export const HEADER_MENUS: { label: HeaderMenus; path: LoginedPaths }[] = [
|
||||
{ label: HEADER_MENUS_ACCOUNT, path: "/account" },
|
||||
{ label: HEADER_MENUS_DICTATIONS, path: "/dictations" },
|
||||
{ label: HEADER_MENUS_LICENSE, path: "/license" },
|
||||
{ label: HEADER_MENUS_USER, path: "/user" },
|
||||
{ label: HEADER_MENUS_WORKFLOW, path: "/workflow" },
|
||||
{ label: HEADER_MENUS_PARTNER, path: "/partners" },
|
||||
{ label: HEADER_MENUS_XXX, path: "/xxx" }, // XXX 仮のタブ
|
||||
export const HEADER_MENUS: {
|
||||
key: HeaderMenus;
|
||||
label: string;
|
||||
path: LoginedPaths;
|
||||
}[] = [
|
||||
{
|
||||
key: HEADER_MENUS_ACCOUNT,
|
||||
label: getTranslationID("common.label.headerAccount"),
|
||||
path: "/account",
|
||||
},
|
||||
{
|
||||
key: HEADER_MENUS_DICTATIONS,
|
||||
label: getTranslationID("common.label.headerDictations"),
|
||||
path: "/dictations",
|
||||
},
|
||||
{
|
||||
key: HEADER_MENUS_LICENSE,
|
||||
label: getTranslationID("common.label.headerLicense"),
|
||||
path: "/license",
|
||||
},
|
||||
{
|
||||
key: HEADER_MENUS_USER,
|
||||
label: getTranslationID("common.label.headerUser"),
|
||||
path: "/user",
|
||||
},
|
||||
{
|
||||
key: HEADER_MENUS_WORKFLOW,
|
||||
label: getTranslationID("common.label.headerWorkflow"),
|
||||
path: "/workflow",
|
||||
},
|
||||
{
|
||||
key: HEADER_MENUS_PARTNER,
|
||||
label: getTranslationID("common.label.headerPartners"),
|
||||
path: "/partners",
|
||||
},
|
||||
{ key: HEADER_MENUS_XXX, label: "xxx", path: "/xxx" }, // XXX 仮のタブ
|
||||
];
|
||||
|
||||
export const HEADER_NAME = "ODMS Cloud";
|
||||
export const HEADER_NAME = getTranslationID("common.label.headerName");
|
||||
|
||||
/**
|
||||
* adminのみに表示するヘッダータブ
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
selectIsUserNameEmpty,
|
||||
clearUserInfo,
|
||||
} from "features/login";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getFilteredMenus } from "./utils";
|
||||
import logo from "../../assets/images/OMS_logo_black.svg";
|
||||
import ac from "../../assets/images/account_circle.svg";
|
||||
@ -30,6 +31,7 @@ const LoginedHeader: React.FC<HeaderProps> = (props: HeaderProps) => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const { instance } = useMsal();
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Headerのユーザー情報を取得する
|
||||
const isUserNameEmpty = useSelector(selectIsUserNameEmpty);
|
||||
@ -61,20 +63,21 @@ const LoginedHeader: React.FC<HeaderProps> = (props: HeaderProps) => {
|
||||
<div className={styles.headerLogo}>
|
||||
<img src={logo} alt="OM System" />
|
||||
</div>
|
||||
<div className={styles.headerSub}>{HEADER_NAME}</div>
|
||||
<div className={styles.headerSub}>{t(HEADER_NAME)}</div>
|
||||
<div className={styles.headerMenu}>
|
||||
<ul>
|
||||
{filterMenus.map((x) => (
|
||||
<li key={x.label}>
|
||||
<li key={x.key}>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href={x.path}
|
||||
onClick={() => navigate(x.path)}
|
||||
className={
|
||||
activePath.toUpperCase() === x.path.toUpperCase()
|
||||
? styles.isActive
|
||||
: ""
|
||||
}
|
||||
>
|
||||
{x.label}
|
||||
{t(x.label)}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
import {
|
||||
isAdminUser,
|
||||
isApproveTier,
|
||||
isStandardUser,
|
||||
} from "features/auth/utils";
|
||||
import { isAdminUser, isApproveTier, isStandardUser } from "features/auth";
|
||||
import { LoginedPaths } from "./types";
|
||||
import {
|
||||
ADMIN_ONLY_TABS,
|
||||
@ -49,21 +45,17 @@ export const getFilteredMenus = () => {
|
||||
return HEADER_MENUS;
|
||||
}
|
||||
if (isStandard) {
|
||||
return HEADER_MENUS.filter(
|
||||
(item) => !ADMIN_ONLY_TABS.includes(item.label)
|
||||
);
|
||||
return HEADER_MENUS.filter((item) => !ADMIN_ONLY_TABS.includes(item.key));
|
||||
}
|
||||
}
|
||||
if (isTier5) {
|
||||
if (isAdmin) {
|
||||
return HEADER_MENUS.filter(
|
||||
(item) => !TIER1_TO_TIER4_ONLY_TABS.includes(item.label)
|
||||
(item) => !TIER1_TO_TIER4_ONLY_TABS.includes(item.key)
|
||||
);
|
||||
}
|
||||
if (isStandard) {
|
||||
return HEADER_MENUS.filter(
|
||||
(item) => !ADMIN_ONLY_TABS.includes(item.label)
|
||||
);
|
||||
return HEADER_MENUS.filter((item) => !ADMIN_ONLY_TABS.includes(item.key));
|
||||
}
|
||||
}
|
||||
// admin,standardでなく、第1~5階層でもないアカウントに表示する空のヘッダータブ
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import styles from "styles/app.module.scss";
|
||||
import { SnackbarLevel } from "features/ui/types";
|
||||
import reportWhite from "../../assets/images/report_white.svg";
|
||||
import closeWhite from "../../assets/images/close_white.svg";
|
||||
import checkCircleWhite from "../../assets/images/check_circle_white.svg";
|
||||
|
||||
export type SnackbarLevel = "info" | "error";
|
||||
|
||||
interface SnackbarProps {
|
||||
isOpen: boolean;
|
||||
level: SnackbarLevel;
|
||||
|
||||
@ -3,6 +3,7 @@ import type { RootState } from "app/store";
|
||||
import { ErrorObject, createErrorObject } from "common/errors";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
AccountsApi,
|
||||
UpdateAccountInfoRequest,
|
||||
@ -26,7 +27,8 @@ export const getAccountRelationsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
const usersApi = new UsersApi(config);
|
||||
@ -72,7 +74,8 @@ export const updateAccountInfoAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountApi = new AccountsApi(config);
|
||||
|
||||
@ -125,7 +128,8 @@ export const deleteAccountAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountApi = new AccountsApi(config);
|
||||
|
||||
|
||||
@ -8,14 +8,15 @@ import {
|
||||
saveRefreshToken,
|
||||
removeRefreshToken,
|
||||
} from "./utils";
|
||||
import { AuthState } from "./state";
|
||||
import type { AuthState } from "./state";
|
||||
import { getDelegationTokenAsync, updateTokenAsync } from "./operations";
|
||||
|
||||
const initialState: AuthState = {
|
||||
configuration: initialConfig(),
|
||||
accessToken: loadAccessToken(),
|
||||
refreshToken: loadRefreshToken(),
|
||||
delegatedAccessToken: null,
|
||||
delegatedRefreshToken: null,
|
||||
delegationAccessToken: null,
|
||||
delegationRefreshToken: null,
|
||||
};
|
||||
|
||||
export const authSlice = createSlice({
|
||||
@ -24,12 +25,10 @@ export const authSlice = createSlice({
|
||||
reducers: {
|
||||
setToken: (
|
||||
state,
|
||||
action: PayloadAction<
|
||||
Omit<
|
||||
AuthState,
|
||||
"configuration" | "delegatedAccessToken" | "delegatedRefreshToken"
|
||||
>
|
||||
>
|
||||
action: PayloadAction<{
|
||||
accessToken: string | null;
|
||||
refreshToken: string | null;
|
||||
}>
|
||||
) => {
|
||||
const { accessToken, refreshToken } = action.payload;
|
||||
if (accessToken && refreshToken) {
|
||||
@ -46,9 +45,25 @@ export const authSlice = createSlice({
|
||||
removeAccessToken();
|
||||
removeRefreshToken();
|
||||
},
|
||||
clearDelegationToken: (state) => {
|
||||
state.delegationAccessToken = null;
|
||||
state.delegationRefreshToken = null;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(updateTokenAsync.fulfilled, (state, action) => {
|
||||
const { accessToken } = action.payload;
|
||||
state.accessToken = accessToken;
|
||||
saveAccessToken(accessToken);
|
||||
});
|
||||
builder.addCase(getDelegationTokenAsync.fulfilled, (state, action) => {
|
||||
const { accessToken, refreshToken } = action.payload;
|
||||
state.delegationAccessToken = accessToken;
|
||||
state.delegationRefreshToken = refreshToken;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const { setToken, clearToken } = authSlice.actions;
|
||||
export const { setToken, clearToken, clearDelegationToken } = authSlice.actions;
|
||||
|
||||
export default authSlice.reducer;
|
||||
|
||||
@ -1 +1,5 @@
|
||||
export { authSlice, clearToken, setToken } from "./authSlice";
|
||||
export * from "./authSlice";
|
||||
export * from "./state";
|
||||
export * from "./operations";
|
||||
export * from "./selectors";
|
||||
export * from "./utils";
|
||||
|
||||
@ -1,13 +1,18 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { RootState } from "app/store";
|
||||
import { AuthApi } from "../../api/api";
|
||||
import type { RootState } from "app/store";
|
||||
import { openSnackbar } from "features/ui";
|
||||
import { getTranslationID } from "translation";
|
||||
import { ErrorObject, createErrorObject } from "common/errors";
|
||||
import {
|
||||
AccessTokenResponse,
|
||||
AuthApi,
|
||||
DelegationTokenResponse,
|
||||
} from "../../api/api";
|
||||
import { Configuration } from "../../api/configuration";
|
||||
import { setToken } from "./authSlice";
|
||||
import { getAccessToken, loadRefreshToken } from "./utils";
|
||||
|
||||
export const updateTokenAsync = createAsyncThunk<
|
||||
{
|
||||
/* Empty Object */
|
||||
},
|
||||
AccessTokenResponse,
|
||||
void,
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
@ -19,7 +24,8 @@ export const updateTokenAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, refreshToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const refreshToken = loadRefreshToken();
|
||||
const config = new Configuration(configuration);
|
||||
const authApi = new AuthApi(config);
|
||||
|
||||
@ -27,16 +33,70 @@ export const updateTokenAsync = createAsyncThunk<
|
||||
const { data } = await authApi.accessToken({
|
||||
headers: { authorization: `Bearer ${refreshToken}` },
|
||||
});
|
||||
// アクセストークン・リフレッシュトークンをlocalStorageに保存
|
||||
thunkApi.dispatch(
|
||||
setToken({
|
||||
accessToken: data.accessToken,
|
||||
refreshToken: state.auth.refreshToken,
|
||||
})
|
||||
);
|
||||
|
||||
return {};
|
||||
return data;
|
||||
} catch (e) {
|
||||
return thunkApi.rejectWithValue({});
|
||||
}
|
||||
});
|
||||
|
||||
// パートナーのアカウントを代理操作するトークンを取得する
|
||||
export const getDelegationTokenAsync = createAsyncThunk<
|
||||
// 正常時の戻り値の型
|
||||
DelegationTokenResponse,
|
||||
void,
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
rejectValue: {
|
||||
error: ErrorObject;
|
||||
};
|
||||
}
|
||||
>("auth/getDelegationTokenAsync", async (args, thunkApi) => {
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const { delegatedAccountId } = state.partner.apps;
|
||||
const config = new Configuration(configuration);
|
||||
const authApi = new AuthApi(config);
|
||||
|
||||
try {
|
||||
if (!delegatedAccountId) {
|
||||
throw new Error("delegatedAccountId is not set");
|
||||
}
|
||||
|
||||
const { data } = await authApi.delegationToken(
|
||||
{ delegatedAccountId },
|
||||
{ headers: { authorization: `Bearer ${accessToken}` } }
|
||||
);
|
||||
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "info",
|
||||
message: getTranslationID("common.message.success"),
|
||||
})
|
||||
);
|
||||
return data;
|
||||
} catch (e) {
|
||||
const error = createErrorObject(e);
|
||||
let errorMessage = getTranslationID("common.message.internalServerError");
|
||||
|
||||
if (error.code === "E010503") {
|
||||
errorMessage = getTranslationID(
|
||||
"partnerPage.message.delegateNotAllowedError"
|
||||
);
|
||||
}
|
||||
if (error.code === "E010501") {
|
||||
errorMessage = getTranslationID("partnerPage.message.deleteFailedError");
|
||||
}
|
||||
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: errorMessage,
|
||||
})
|
||||
);
|
||||
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { RootState } from "app/store";
|
||||
import type { RootState } from "app/store";
|
||||
import { decodeToken } from "common/decodeToken";
|
||||
import { DateTime } from "luxon";
|
||||
import { loadAccessToken } from "./utils";
|
||||
/**
|
||||
* ログイン済みかどうかを判定する
|
||||
* @param state RootState
|
||||
@ -24,5 +25,9 @@ export const isTokenExpired = (state: RootState): boolean => {
|
||||
};
|
||||
|
||||
// 代行操作用のトークンを取得する
|
||||
export const selectDelegatedAccessToken = (state: RootState): string | null =>
|
||||
state.auth.delegatedAccessToken;
|
||||
export const selectDelegationAccessToken = (state: RootState): string | null =>
|
||||
state.auth.delegationAccessToken;
|
||||
|
||||
// 代行操作用がなければ通常トークンを取得する
|
||||
export const selectAccessToken = (state: RootState): string | null =>
|
||||
state.auth.delegationAccessToken ?? loadAccessToken();
|
||||
|
||||
@ -4,6 +4,6 @@ export interface AuthState {
|
||||
configuration: ConfigurationParameters;
|
||||
accessToken: string | null;
|
||||
refreshToken: string | null;
|
||||
delegatedAccessToken: string | null;
|
||||
delegatedRefreshToken: string | null;
|
||||
delegationAccessToken: string | null;
|
||||
delegationRefreshToken: string | null;
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ConfigurationParameters } from "api";
|
||||
import { decodeToken } from "../../common/decodeToken";
|
||||
import { ADMIN_ROLES, USER_ROLES } from "../../components/auth/constants";
|
||||
import type { AuthState } from "./state";
|
||||
|
||||
/**
|
||||
* Get access token
|
||||
@ -42,6 +43,22 @@ export const removeRefreshToken = (): void => {
|
||||
localStorage.removeItem("refreshToken");
|
||||
};
|
||||
|
||||
/**
|
||||
* 代行操作用のアクセストークンを持っている場合はそれを返す
|
||||
* なければ通常のアクセストークンを返す
|
||||
* @returns access token
|
||||
*/
|
||||
export const getAccessToken = (state: AuthState): string | null =>
|
||||
state.delegationAccessToken ?? state.accessToken;
|
||||
|
||||
/**
|
||||
* 代行操作用のリフレッシュトークンを持っている場合はそれを返す
|
||||
* なければ通常のリフレッシュトークンを返す
|
||||
* @returns refresh token
|
||||
*/
|
||||
export const getRefreshToken = (state: AuthState): string | null =>
|
||||
state.delegationRefreshToken ?? state.refreshToken;
|
||||
|
||||
// 初期状態のAPI Config
|
||||
export const initialConfig = (): ConfigurationParameters => {
|
||||
const config: ConfigurationParameters = {};
|
||||
|
||||
@ -2,6 +2,7 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
TasksResponse,
|
||||
TasksApi,
|
||||
@ -42,7 +43,8 @@ export const listTasksAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const tasksApi = new TasksApi(config);
|
||||
|
||||
@ -89,7 +91,8 @@ export const getSortColumnAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
|
||||
@ -138,7 +141,8 @@ export const listTypistsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -174,7 +178,8 @@ export const listTypistGroupsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -217,7 +222,8 @@ export const updateAssigneeAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const tasksApi = new TasksApi(config);
|
||||
|
||||
@ -283,7 +289,8 @@ export const playbackAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const tasksApi = new TasksApi(config);
|
||||
const usersApi = new UsersApi(config);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import { openSnackbar } from "../../ui/uiSlice";
|
||||
import type { RootState } from "../../../app/store";
|
||||
import { getTranslationID } from "../../../translation";
|
||||
@ -26,7 +27,8 @@ export const activateCardLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const licensesApi = new LicensesApi(config);
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import { openSnackbar } from "../../ui/uiSlice";
|
||||
import type { RootState } from "../../../app/store";
|
||||
import { getTranslationID } from "../../../translation";
|
||||
@ -24,7 +25,8 @@ export const createCardLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const licensesApi = new LicensesApi(config);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import { LicensesApi } from "../../../api/api";
|
||||
import { Configuration } from "../../../api/configuration";
|
||||
import { ErrorObject, createErrorObject } from "../../../common/errors";
|
||||
@ -27,7 +28,8 @@ export const orderLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const licensesApi = new LicensesApi(config);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import { AccountsApi, LicensesApi } from "../../../api/api";
|
||||
import { Configuration } from "../../../api/configuration";
|
||||
import { ErrorObject, createErrorObject } from "../../../common/errors";
|
||||
@ -26,7 +27,8 @@ export const getLicenseOrderHistoriesAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -95,7 +97,8 @@ export const issueLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -161,7 +164,8 @@ export const cancelOrderAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const licensesApi = new LicensesApi(config);
|
||||
|
||||
@ -223,7 +227,8 @@ export const cancelIssueAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
AccountsApi,
|
||||
GetLicenseSummaryResponse,
|
||||
@ -25,7 +26,8 @@ export const getLicenseSummaryAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import type { RootState } from "../../../app/store";
|
||||
import { getTranslationID } from "../../../translation";
|
||||
import { openSnackbar } from "../../ui/uiSlice";
|
||||
@ -25,7 +26,8 @@ export const getMyAccountAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
try {
|
||||
@ -67,7 +69,8 @@ export const getPartnerLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
import { getUserInfoAsync } from "./operations";
|
||||
import { HeaderState } from "./state";
|
||||
import type { HeaderState } from "./state";
|
||||
|
||||
const initialState: HeaderState = {
|
||||
domain: {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||
import { LoginState } from "./state";
|
||||
import type { LoginState } from "./state";
|
||||
import { loginAsync } from "./operations";
|
||||
|
||||
const initialState: LoginState = {
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { setToken } from "features/auth/authSlice";
|
||||
import { AuthApi, UsersApi, GetMyUserResponse } from "../../api/api";
|
||||
import { setToken, getAccessToken } from "features/auth";
|
||||
import {
|
||||
AuthApi,
|
||||
UsersApi,
|
||||
GetMyUserResponse,
|
||||
TokenResponse,
|
||||
} from "../../api/api";
|
||||
import { Configuration } from "../../api/configuration";
|
||||
import { ErrorObject, createErrorObject } from "../../common/errors";
|
||||
|
||||
export const loginAsync = createAsyncThunk<
|
||||
{
|
||||
//
|
||||
},
|
||||
TokenResponse,
|
||||
{
|
||||
idToken: string;
|
||||
},
|
||||
@ -40,7 +43,7 @@ export const loginAsync = createAsyncThunk<
|
||||
})
|
||||
);
|
||||
|
||||
return {};
|
||||
return data;
|
||||
} catch (e) {
|
||||
// e ⇒ errorObjectに変換"
|
||||
const error = createErrorObject(e);
|
||||
@ -63,7 +66,8 @@ export const getUserInfoAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { RootState } from "app/store";
|
||||
import type { RootState } from "app/store";
|
||||
|
||||
export const selectLoginApiCallStatus = (
|
||||
state: RootState
|
||||
|
||||
@ -3,6 +3,7 @@ import type { RootState } from "app/store";
|
||||
import { ErrorObject, createErrorObject } from "common/errors";
|
||||
import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
AccountsApi,
|
||||
CreatePartnerAccountRequest,
|
||||
@ -26,7 +27,8 @@ export const createPartnerAccountAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountApi = new AccountsApi(config);
|
||||
|
||||
@ -86,7 +88,8 @@ export const getPartnerInfoAsync = createAsyncThunk<
|
||||
const { limit, offset } = args;
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
|
||||
@ -60,6 +60,21 @@ export const partnerSlice = createSlice({
|
||||
state.apps.limit = limit;
|
||||
state.apps.offset = offset;
|
||||
},
|
||||
changeDelegateAccount: (
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
delegatedAccountId?: number;
|
||||
delegatedCompanyName?: string;
|
||||
}>
|
||||
) => {
|
||||
const { delegatedAccountId, delegatedCompanyName } = action.payload;
|
||||
state.apps.delegatedAccountId = delegatedAccountId;
|
||||
state.apps.delegatedCompanyName = delegatedCompanyName;
|
||||
},
|
||||
cleanupDelegateAccount: (state) => {
|
||||
state.apps.delegatedAccountId = undefined;
|
||||
state.apps.delegatedCompanyName = undefined;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(createPartnerAccountAsync.pending, (state) => {
|
||||
@ -91,5 +106,7 @@ export const {
|
||||
changeCountry,
|
||||
cleanupAddPartner,
|
||||
savePageInfo,
|
||||
changeDelegateAccount,
|
||||
cleanupDelegateAccount,
|
||||
} = partnerSlice.actions;
|
||||
export default partnerSlice.reducer;
|
||||
|
||||
@ -53,3 +53,9 @@ export const selectCurrentPage = (state: RootState) => {
|
||||
const page = floor(offset / limit) + 1;
|
||||
return page;
|
||||
};
|
||||
|
||||
// delegation
|
||||
export const selectDelegatedAccountId = (state: RootState) =>
|
||||
state.partner.apps.delegatedAccountId;
|
||||
export const selectDelegatedCompanyName = (state: RootState) =>
|
||||
state.partner.apps.delegatedCompanyName;
|
||||
|
||||
@ -17,4 +17,6 @@ export interface Apps {
|
||||
offset: number;
|
||||
addPartner: CreatePartnerAccountRequest;
|
||||
isLoading: boolean;
|
||||
delegatedAccountId?: number;
|
||||
delegatedCompanyName?: string;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import { getTranslationID } from "translation";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getIdTokenFromLocalStorage } from "common/token";
|
||||
import { TIERS } from "components/auth/constants";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
UsersApi,
|
||||
GetAccountInfoMinimalAccessResponse,
|
||||
@ -30,7 +31,8 @@ export const getAccountInfoMinimalAccessAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountApi = new AccountsApi(config);
|
||||
|
||||
@ -74,7 +76,8 @@ export const getTermsInfoAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const termsApi = new TermsApi(config);
|
||||
|
||||
@ -120,7 +123,8 @@ export const updateAcceptedVersionAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const userApi = new UsersApi(config);
|
||||
|
||||
|
||||
@ -2,3 +2,4 @@ export * from "./constants";
|
||||
export * from "./selectors";
|
||||
export * from "./state";
|
||||
export * from "./uiSlice";
|
||||
export * from "./types";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { RootState } from "app/store";
|
||||
import { SnackbarLevel } from "components/snackbar";
|
||||
import type { RootState } from "app/store";
|
||||
import { SnackbarLevel } from "./types";
|
||||
|
||||
export const selectSnackber = (
|
||||
state: RootState
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SnackbarLevel } from "components/snackbar";
|
||||
import { SnackbarLevel } from "./types";
|
||||
|
||||
export interface UIState {
|
||||
isOpen: boolean;
|
||||
|
||||
1
dictation_client/src/features/ui/types.ts
Normal file
1
dictation_client/src/features/ui/types.ts
Normal file
@ -0,0 +1 @@
|
||||
export type SnackbarLevel = "info" | "error";
|
||||
@ -1,5 +1,5 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { SnackbarLevel } from "components/snackbar";
|
||||
import { SnackbarLevel } from "./types";
|
||||
import { UIState } from "./state";
|
||||
import { DEFAULT_SNACKBAR_DURATION } from "./constants";
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ import type { RootState } from "app/store";
|
||||
import { USER_ROLES } from "components/auth/constants";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getTranslationID } from "translation";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
GetUsersResponse,
|
||||
UsersApi,
|
||||
@ -27,7 +28,8 @@ export const listUsersAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
|
||||
@ -67,7 +69,8 @@ export const addUserAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
const { addUser } = state.user.apps;
|
||||
@ -134,7 +137,8 @@ export const updateUserAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
const { updateUser } = state.user.apps;
|
||||
@ -217,7 +221,8 @@ export const getAllocatableLicensesAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const licensesApi = new LicensesApi(config);
|
||||
|
||||
@ -266,7 +271,8 @@ export const allocateLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
|
||||
@ -335,7 +341,8 @@ export const deallocateLicenseAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const usersApi = new UsersApi(config);
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
} from "api";
|
||||
import type { RootState } from "app/store";
|
||||
import { ErrorObject, createErrorObject } from "common/errors";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getTranslationID } from "translation";
|
||||
|
||||
@ -30,7 +31,8 @@ export const listWorkflowAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const workflowsApi = new WorkflowsApi(config);
|
||||
|
||||
@ -68,7 +70,8 @@ export const createWorkflowAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const workflowsApi = new WorkflowsApi(config);
|
||||
const { selectedAssignees, authorId, templateId, worktypeId } =
|
||||
@ -155,7 +158,8 @@ export const updateWorkflowAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const workflowsApi = new WorkflowsApi(config);
|
||||
const {
|
||||
@ -258,7 +262,8 @@ export const getworkflowRelationsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
const templatesApi = new TemplatesApi(config);
|
||||
@ -326,7 +331,8 @@ export const deleteWorkflowAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const workflowsApi = new WorkflowsApi(config);
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import { ErrorObject, createErrorObject } from "common/errors";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getTranslationID } from "translation";
|
||||
import { BlockBlobClient, ContainerClient } from "@azure/storage-blob";
|
||||
import { getAccessToken } from "features/auth";
|
||||
|
||||
export const listTemplateAsync = createAsyncThunk<
|
||||
GetTemplatesResponse,
|
||||
@ -24,7 +25,8 @@ export const listTemplateAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const templateApi = new TemplatesApi(config);
|
||||
|
||||
@ -62,7 +64,8 @@ export const uploadTemplateAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const { uploadFile } = state.template.apps;
|
||||
const config = new Configuration(configuration);
|
||||
const filesApi = new FilesApi(config);
|
||||
|
||||
@ -2,6 +2,7 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getTranslationID } from "translation";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
AccountsApi,
|
||||
GetTypistGroupsResponse,
|
||||
@ -26,7 +27,8 @@ export const listTypistGroupsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -62,7 +64,8 @@ export const listTypistsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -100,7 +103,8 @@ export const createTypistGroupAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -152,7 +156,8 @@ export const getTypistGroupAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -204,7 +209,8 @@ export const updateTypistGroupAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const { updateTypistGroupId, selectedTypists, groupName } =
|
||||
state.typistGroup.apps;
|
||||
const config = new Configuration(configuration);
|
||||
|
||||
@ -2,6 +2,7 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import type { RootState } from "app/store";
|
||||
import { openSnackbar } from "features/ui/uiSlice";
|
||||
import { getTranslationID } from "translation";
|
||||
import { getAccessToken } from "features/auth";
|
||||
import {
|
||||
AccountsApi,
|
||||
GetOptionItemsResponse,
|
||||
@ -23,7 +24,8 @@ export const listWorktypesAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
@ -63,7 +65,8 @@ export const addWorktypeAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
// stateからworktypeIdとdescriptionを取得する
|
||||
@ -130,7 +133,8 @@ export const editWorktypeAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
// stateからselectedId,worktypeId,descriptionを取得する
|
||||
@ -197,7 +201,8 @@ export const getOptionItemsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
// stateからselectedIdを取得する
|
||||
@ -249,7 +254,8 @@ export const editOptionItemsAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
// stateからselectedId,optionItemsを取得する
|
||||
@ -315,7 +321,8 @@ export const updateActiveWorktypeAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
const { id } = args;
|
||||
@ -374,7 +381,8 @@ export const deleteWorktypeAsync = createAsyncThunk<
|
||||
// apiのConfigurationを取得する
|
||||
const { getState } = thunkApi;
|
||||
const state = getState() as RootState;
|
||||
const { configuration, accessToken } = state.auth;
|
||||
const { configuration } = state.auth;
|
||||
const accessToken = getAccessToken(state.auth);
|
||||
const config = new Configuration(configuration);
|
||||
const accountsApi = new AccountsApi(config);
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ import {
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getTranslationID } from "translation";
|
||||
import { TIERS } from "components/auth/constants";
|
||||
import { isApproveTier } from "features/auth/utils";
|
||||
import { isApproveTier } from "features/auth";
|
||||
import { DeleteAccountPopup } from "./deleteAccountPopup";
|
||||
import progress_activit from "../../assets/images/progress_activit.svg";
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ import {
|
||||
} from "features/dictation";
|
||||
import { getTranslationID } from "translation";
|
||||
import { Task } from "api/api";
|
||||
import { isAdminUser, isAuthorUser, isTypistUser } from "features/auth/utils";
|
||||
import { isAdminUser, isAuthorUser, isTypistUser } from "features/auth";
|
||||
import { STATUS, LIMIT_TASK_NUM } from "../../features/dictation";
|
||||
import uploaded from "../../assets/images/uploaded.svg";
|
||||
import pending from "../../assets/images/pending.svg";
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import React, { useCallback } from "react";
|
||||
import { loadAccessToken } from "features/auth/utils";
|
||||
import { decodeToken } from "common/decodeToken";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppDispatch } from "app/store";
|
||||
import { clearToken } from "features/auth";
|
||||
import { useMsal } from "@azure/msal-react";
|
||||
import { Token } from "common/token";
|
||||
import { clearUserInfo } from "features/login";
|
||||
import { selectAccessToken } from "features/auth/selectors";
|
||||
import { LicenseSummary } from "./licenseSummary";
|
||||
import PartnerLicense from "./partnerLicense";
|
||||
|
||||
const LicensePage: React.FC = (): JSX.Element => {
|
||||
const jwt = loadAccessToken();
|
||||
const jwt = useSelector(selectAccessToken);
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const { instance } = useMsal();
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
|
||||
import { isApproveTier } from "features/auth/utils";
|
||||
import { isApproveTier } from "features/auth";
|
||||
import { TIERS } from "components/auth/constants";
|
||||
import Footer from "components/footer";
|
||||
import Header from "components/header";
|
||||
@ -27,7 +27,7 @@ import {
|
||||
cancelIssueAsync,
|
||||
} from "features/license/licenseOrderHistory";
|
||||
import { selectSelectedRow } from "features/license/partnerLicense";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import undo from "../../assets/images/undo.svg";
|
||||
import history from "../../assets/images/history.svg";
|
||||
@ -49,7 +49,7 @@ export const LicenseOrderHistory: React.FC<LicenseOrderHistoryProps> = (
|
||||
const isLoading = useSelector(selectIsLoading);
|
||||
const selectedRow = useSelector(selectSelectedRow);
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
|
||||
// Return押下時の処理
|
||||
const returnGui = useCallback(() => {
|
||||
@ -159,12 +159,11 @@ export const LicenseOrderHistory: React.FC<LicenseOrderHistoryProps> = (
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.wrap} ${delegatedAccessToken ? styles.manage : ""}`}
|
||||
className={`${styles.wrap} ${delegationAccessToken ? styles.manage : ""}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && <DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
delegationAccessToken && <DelegationBar />
|
||||
}
|
||||
<Header />
|
||||
<UpdateTokenTimer />
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
selecLicenseSummaryInfo,
|
||||
} from "features/license/licenseSummary";
|
||||
import { selectSelectedRow } from "features/license/partnerLicense";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import postAdd from "../../assets/images/post_add.svg";
|
||||
import history from "../../assets/images/history.svg";
|
||||
@ -36,7 +36,7 @@ export const LicenseSummary: React.FC<LicenseSummaryProps> = (
|
||||
const [t] = useTranslation();
|
||||
const selectedRow = useSelector(selectSelectedRow);
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
|
||||
// popup制御関係
|
||||
const [islicenseOrderPopupOpen, setIslicenseOrderPopupOpen] = useState(false);
|
||||
@ -102,16 +102,10 @@ export const LicenseSummary: React.FC<LicenseSummaryProps> = (
|
||||
{!islicenseOrderHistoryOpen && (
|
||||
<div
|
||||
className={`${styles.wrap} ${
|
||||
delegatedAccessToken ? styles.manage : ""
|
||||
delegationAccessToken ? styles.manage : ""
|
||||
}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && (
|
||||
<DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
)
|
||||
}
|
||||
{delegationAccessToken && <DelegationBar />}
|
||||
<Header />
|
||||
|
||||
<UpdateTokenTimer />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useMsal } from "@azure/msal-react";
|
||||
import { AppDispatch } from "app/store";
|
||||
import { isIdToken } from "common/token";
|
||||
import { loadAccessToken, loadRefreshToken } from "features/auth/utils";
|
||||
import { loadAccessToken, loadRefreshToken } from "features/auth";
|
||||
import { loginAsync, selectLocalStorageKeyforIdToken } from "features/login";
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import Footer from "components/footer";
|
||||
|
||||
@ -6,7 +6,7 @@ import Header from "components/header";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import styles from "styles/app.module.scss";
|
||||
import { isApproveTier } from "features/auth/utils";
|
||||
import { isApproveTier } from "features/auth";
|
||||
import {
|
||||
LIMIT_PARTNER_VIEW_NUM,
|
||||
selectCurrentPage,
|
||||
@ -17,9 +17,14 @@ import {
|
||||
getPartnerInfoAsync,
|
||||
selectPartnersInfo,
|
||||
} from "features/partner/index";
|
||||
import { savePageInfo } from "features/partner/partnerSlice";
|
||||
import {
|
||||
changeDelegateAccount,
|
||||
savePageInfo,
|
||||
} from "features/partner/partnerSlice";
|
||||
import { getTranslationID } from "translation";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getDelegationTokenAsync } from "features/auth/operations";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import personAdd from "../../assets/images/person_add.svg";
|
||||
import { TIERS } from "../../components/auth/constants";
|
||||
import { AddPartnerAccountPopup } from "./addPartnerAccountPopup";
|
||||
@ -29,6 +34,7 @@ const PartnerPage: React.FC = (): JSX.Element => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
||||
const [t] = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const total = useSelector(selectTotal);
|
||||
const totalPage = useSelector(selectTotalPage);
|
||||
const offset = useSelector(selectOffset);
|
||||
@ -83,6 +89,19 @@ const PartnerPage: React.FC = (): JSX.Element => {
|
||||
savePageInfo({ limit: LIMIT_PARTNER_VIEW_NUM, offset: targetOffset })
|
||||
);
|
||||
};
|
||||
// 代理操作開始処理
|
||||
const startDealerManagement = useCallback(
|
||||
async (delegatedAccountId: number, delegatedCompanyName: string) => {
|
||||
dispatch(
|
||||
changeDelegateAccount({ delegatedAccountId, delegatedCompanyName })
|
||||
);
|
||||
const { meta } = await dispatch(getDelegationTokenAsync());
|
||||
if (meta.requestStatus === "fulfilled") {
|
||||
navigate("/user");
|
||||
}
|
||||
},
|
||||
[dispatch, navigate]
|
||||
);
|
||||
|
||||
// HTML
|
||||
return (
|
||||
@ -160,8 +179,8 @@ const PartnerPage: React.FC = (): JSX.Element => {
|
||||
<tr>
|
||||
<td className={styles.clm0}>
|
||||
<ul className={styles.menuInTable}>
|
||||
<li>
|
||||
{isVisibleButton && (
|
||||
{isVisibleButton && (
|
||||
<li>
|
||||
<a>
|
||||
{t(
|
||||
getTranslationID(
|
||||
@ -169,8 +188,27 @@ const PartnerPage: React.FC = (): JSX.Element => {
|
||||
)
|
||||
)}
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
</li>
|
||||
)}
|
||||
{isVisibleDealerManagement && (
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
onClick={() => {
|
||||
startDealerManagement(x.accountId, x.name);
|
||||
}}
|
||||
className={
|
||||
x.dealerManagement ? "" : styles.isDisable
|
||||
}
|
||||
>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"partnerPage.label.dealerManagement"
|
||||
)
|
||||
)}
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</td>
|
||||
<td>{x.name}</td>
|
||||
|
||||
@ -14,15 +14,17 @@ import {
|
||||
listTemplateAsync,
|
||||
selectIsLoading,
|
||||
} from "features/workflow/template";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AddTemplateFilePopup } from "./addTemplateFilePopup";
|
||||
|
||||
export const TemplateFilePage: React.FC = () => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [t] = useTranslation();
|
||||
// authStateに配置予定の代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const navigate = useNavigate();
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
const templates = useSelector(selectTemplates);
|
||||
const isLoading = useSelector(selectIsLoading);
|
||||
|
||||
@ -44,16 +46,10 @@ export const TemplateFilePage: React.FC = () => {
|
||||
)}
|
||||
<div
|
||||
className={`${styles.wrap} ${
|
||||
delegatedAccessToken ? styles.manage : ""
|
||||
delegationAccessToken ? styles.manage : ""
|
||||
}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && (
|
||||
<DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
)
|
||||
}
|
||||
{delegationAccessToken && <DelegationBar />}
|
||||
<Header />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
@ -71,8 +67,9 @@ export const TemplateFilePage: React.FC = () => {
|
||||
<div>
|
||||
<ul className={`${styles.menuAction} ${styles.worktype}`}>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href="/workflow"
|
||||
onClick={() => navigate("/workflow")}
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
>
|
||||
<img src={undo} alt="" className={styles.menuIcon} />
|
||||
|
||||
@ -15,16 +15,18 @@ import {
|
||||
import { AppDispatch } from "app/store";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getTranslationID } from "translation";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import { EditTypistGroupPopup } from "./editTypistGroupPopup";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AddTypistGroupPopup } from "./addTypistGroupPopup";
|
||||
import { EditTypistGroupPopup } from "./editTypistGroupPopup";
|
||||
|
||||
const TypistGroupSettingPage: React.FC = (): JSX.Element => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [t] = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
const isLoading = useSelector(selectIsLoading);
|
||||
const typistGroup = useSelector(selectTypistGroups);
|
||||
|
||||
@ -66,16 +68,10 @@ const TypistGroupSettingPage: React.FC = (): JSX.Element => {
|
||||
/>
|
||||
<div
|
||||
className={`${styles.wrap} ${
|
||||
delegatedAccessToken ? styles.manage : ""
|
||||
delegationAccessToken ? styles.manage : ""
|
||||
}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && (
|
||||
<DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
)
|
||||
}
|
||||
{delegationAccessToken && <DelegationBar />}
|
||||
<Header />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
@ -93,8 +89,9 @@ const TypistGroupSettingPage: React.FC = (): JSX.Element => {
|
||||
<div>
|
||||
<ul className={styles.menuAction}>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href="/workflow"
|
||||
onClick={() => navigate("/workflow")}
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
>
|
||||
<img src={undo} alt="" className={styles.menuIcon} />
|
||||
|
||||
@ -15,14 +15,14 @@ import { useTranslation } from "react-i18next";
|
||||
import { getTranslationID } from "translation";
|
||||
import { isLicenseStatusType, UserView } from "features/user/types";
|
||||
import { LICENSE_STATUS } from "features/user/constants";
|
||||
import { isApproveTier } from "features/auth/utils";
|
||||
import { isApproveTier } from "features/auth";
|
||||
import { TIERS } from "components/auth/constants";
|
||||
import {
|
||||
changeUpdateUser,
|
||||
changeLicenseAllocateUser,
|
||||
} from "features/user/userSlice";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import personAdd from "../../assets/images/person_add.svg";
|
||||
import checkFill from "../../assets/images/check_fill.svg";
|
||||
import checkOutline from "../../assets/images/check_outline.svg";
|
||||
@ -35,7 +35,7 @@ const UserListPage: React.FC = (): JSX.Element => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [t] = useTranslation();
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
|
||||
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
||||
const [isUpdatePopupOpen, setIsUpdatePopupOpen] = useState(false);
|
||||
@ -112,16 +112,10 @@ const UserListPage: React.FC = (): JSX.Element => {
|
||||
/>
|
||||
<div
|
||||
className={`${styles.wrap} ${
|
||||
delegatedAccessToken ? styles.manage : ""
|
||||
delegationAccessToken ? styles.manage : ""
|
||||
}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && (
|
||||
<DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
)
|
||||
}
|
||||
{delegationAccessToken && <DelegationBar />}
|
||||
<Header />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
|
||||
@ -21,8 +21,9 @@ import {
|
||||
deleteWorktypeAsync,
|
||||
} from "features/workflow/worktype";
|
||||
import { AppDispatch } from "app/store";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AddWorktypeIdPopup } from "./addWorktypeIdPopup";
|
||||
import { EditWorktypeIdPopup } from "./editWorktypeIdPopup";
|
||||
import { EditOptionItemsPopup } from "./editOptionItemsPopup";
|
||||
@ -30,8 +31,9 @@ import { EditOptionItemsPopup } from "./editOptionItemsPopup";
|
||||
const WorktypeIdSettingPage: React.FC = (): JSX.Element => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [t] = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
const isLoading = useSelector(selectIsLoading);
|
||||
const worktypes = useSelector(selectWorktypes);
|
||||
const activeWorktypeId = useSelector(selectActiveWorktypeId);
|
||||
@ -131,16 +133,10 @@ const WorktypeIdSettingPage: React.FC = (): JSX.Element => {
|
||||
/>
|
||||
<div
|
||||
className={`${styles.wrap} ${
|
||||
delegatedAccessToken ? styles.manage : ""
|
||||
delegationAccessToken ? styles.manage : ""
|
||||
}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && (
|
||||
<DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
)
|
||||
}
|
||||
{delegationAccessToken && <DelegationBar />}
|
||||
<Header />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
@ -157,8 +153,9 @@ const WorktypeIdSettingPage: React.FC = (): JSX.Element => {
|
||||
<div>
|
||||
<ul className={`${styles.menuAction} ${styles.worktype}`}>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href="/workflow"
|
||||
onClick={() => navigate("/workflow")}
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
>
|
||||
<img src={undo} alt="" className={styles.menuIcon} />
|
||||
|
||||
@ -17,23 +17,25 @@ import {
|
||||
selectIsLoading,
|
||||
selectWorkflows,
|
||||
} from "features/workflow";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import { selectDelegationAccessToken } from "features/auth/selectors";
|
||||
import progress_activit from "assets/images/progress_activit.svg";
|
||||
import { getTranslationID } from "translation";
|
||||
import { DelegationBar } from "components/delegate";
|
||||
import { selectDelegatedAccessToken } from "features/auth/selectors";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { EditWorkflowPopup } from "./editworkflowPopup";
|
||||
import { AddWorkflowPopup } from "./addworkflowPopup";
|
||||
|
||||
const WorkflowPage: React.FC = (): JSX.Element => {
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [t] = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// 追加Popupの表示制御
|
||||
const [isShowAddPopup, setIsShowAddPopup] = useState<boolean>(false);
|
||||
// 編集Popupの表示制御
|
||||
const [isShowEditPopup, setIsShowEditPopup] = useState<boolean>(false);
|
||||
// 代行操作用のトークンを取得する
|
||||
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
|
||||
const delegationAccessToken = useSelector(selectDelegationAccessToken);
|
||||
const workflows = useSelector(selectWorkflows);
|
||||
const isLoading = useSelector(selectIsLoading);
|
||||
|
||||
@ -76,16 +78,10 @@ const WorkflowPage: React.FC = (): JSX.Element => {
|
||||
)}
|
||||
<div
|
||||
className={`${styles.wrap} ${
|
||||
delegatedAccessToken ? styles.manage : ""
|
||||
delegationAccessToken ? styles.manage : ""
|
||||
}`}
|
||||
>
|
||||
{
|
||||
// 代行操作中の場合は、代行操作バーを表示する
|
||||
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする(別タスクで)
|
||||
delegatedAccessToken && (
|
||||
<DelegationBar delegatedCompanyName="XXXXXX" />
|
||||
)
|
||||
}
|
||||
{delegationAccessToken && <DelegationBar />}
|
||||
<Header />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
@ -115,8 +111,9 @@ const WorkflowPage: React.FC = (): JSX.Element => {
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href="/workflow/template"
|
||||
onClick={() => navigate("/workflow/template")}
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
>
|
||||
<img
|
||||
@ -130,8 +127,9 @@ const WorkflowPage: React.FC = (): JSX.Element => {
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href="/workflow/worktype-id"
|
||||
onClick={() => navigate("/workflow/worktype-id")}
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
>
|
||||
<img
|
||||
@ -145,8 +143,9 @@ const WorkflowPage: React.FC = (): JSX.Element => {
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<a
|
||||
href="/workflow/typist-group"
|
||||
onClick={() => navigate("/workflow/typist-group")}
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
>
|
||||
<img
|
||||
|
||||
@ -18,6 +18,13 @@
|
||||
"delete": "Löschen",
|
||||
"return": "zurückkehren",
|
||||
"operationInsteadOf": "(de)Operation instead of:",
|
||||
"headerName": "(de)ODMS Cloud",
|
||||
"headerAccount": "(de)Account",
|
||||
"headerUser": "(de)User",
|
||||
"headerLicense": "(de)License",
|
||||
"headerDictations": "(de)Dictations",
|
||||
"headerWorkflow": "(de)Workflow",
|
||||
"headerPartners": "(de)Partners",
|
||||
"tier1": "(de)Admin",
|
||||
"tier2": "(de)BC",
|
||||
"tier3": "(de)Distributor",
|
||||
@ -463,6 +470,11 @@
|
||||
"dealerManagement": "Erlauben Sie dem Händler, Änderungen vorzunehmen",
|
||||
"partners": "Partner",
|
||||
"deleteAccount": "Konto löschen"
|
||||
},
|
||||
"message": {
|
||||
"delegateNotAllowedError": "(de)パートナーの代行操作が許可されていません。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "(de)代行操作に失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"delegateCancelError": "(de)代行操作の許可が取り消されたため、代行操作を終了しました。"
|
||||
}
|
||||
},
|
||||
"accountPage": {
|
||||
|
||||
@ -18,6 +18,13 @@
|
||||
"delete": "Delete",
|
||||
"return": "Return",
|
||||
"operationInsteadOf": "Operation instead of:",
|
||||
"headerName": "ODMS Cloud",
|
||||
"headerAccount": "Account",
|
||||
"headerUser": "User",
|
||||
"headerLicense": "License",
|
||||
"headerDictations": "Dictations",
|
||||
"headerWorkflow": "Workflow",
|
||||
"headerPartners": "Partners",
|
||||
"tier1": "Admin",
|
||||
"tier2": "BC",
|
||||
"tier3": "Distributor",
|
||||
@ -463,6 +470,11 @@
|
||||
"dealerManagement": "Dealer Management",
|
||||
"partners": "Partners",
|
||||
"deleteAccount": "Delete Account"
|
||||
},
|
||||
"message": {
|
||||
"delegateNotAllowedError": "パートナーの代行操作が許可されていません。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "代行操作に失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"delegateCancelError": "代行操作の許可が取り消されたため、代行操作を終了しました。"
|
||||
}
|
||||
},
|
||||
"accountPage": {
|
||||
|
||||
@ -18,6 +18,13 @@
|
||||
"delete": "Delete",
|
||||
"return": "Devolver",
|
||||
"operationInsteadOf": "(es)Operation instead of:",
|
||||
"headerName": "(es)ODMS Cloud",
|
||||
"headerAccount": "(es)Account",
|
||||
"headerUser": "(es)User",
|
||||
"headerLicense": "(es)License",
|
||||
"headerDictations": "(es)Dictations",
|
||||
"headerWorkflow": "(es)Workflow",
|
||||
"headerPartners": "(es)Partners",
|
||||
"tier1": "(es)Admin",
|
||||
"tier2": "(es)BC",
|
||||
"tier3": "(es)Distributor",
|
||||
@ -463,6 +470,11 @@
|
||||
"dealerManagement": "Permitir que el distribuidor realice los cambios",
|
||||
"partners": "Socios",
|
||||
"deleteAccount": "Borrar cuenta"
|
||||
},
|
||||
"message": {
|
||||
"delegateNotAllowedError": "(es)パートナーの代行操作が許可されていません。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "(es)代行操作に失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"delegateCancelError": "(es)代行操作の許可が取り消されたため、代行操作を終了しました。"
|
||||
}
|
||||
},
|
||||
"accountPage": {
|
||||
|
||||
@ -18,6 +18,13 @@
|
||||
"delete": "Delete",
|
||||
"return": "Retour",
|
||||
"operationInsteadOf": "(fr)Operation instead of:",
|
||||
"headerName": "(fr)ODMS Cloud",
|
||||
"headerAccount": "(fr)Account",
|
||||
"headerUser": "(fr)User",
|
||||
"headerLicense": "(fr)License",
|
||||
"headerDictations": "(fr)Dictations",
|
||||
"headerWorkflow": "(fr)Workflow",
|
||||
"headerPartners": "(fr)Partners",
|
||||
"tier1": "(fr)Admin",
|
||||
"tier2": "(fr)BC",
|
||||
"tier3": "(fr)Distributor",
|
||||
@ -463,6 +470,11 @@
|
||||
"dealerManagement": "Autoriser le revendeur à modifier les paramètres",
|
||||
"partners": "Partenaires",
|
||||
"deleteAccount": "Supprimer le compte"
|
||||
},
|
||||
"message": {
|
||||
"delegateNotAllowedError": "(fr)パートナーの代行操作が許可されていません。画面を更新し、再度ご確認ください。",
|
||||
"deleteFailedError": "(fr)代行操作に失敗しました。画面を更新し、再度ご確認ください。",
|
||||
"delegateCancelError": "(fr)代行操作の許可が取り消されたため、代行操作を終了しました。"
|
||||
}
|
||||
},
|
||||
"accountPage": {
|
||||
|
||||
1
dictation_function/.devcontainer/.dockerignore
Normal file
1
dictation_function/.devcontainer/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
local.settings.json
|
||||
38
dictation_function/.devcontainer/Dockerfile
Normal file
38
dictation_function/.devcontainer/Dockerfile
Normal file
@ -0,0 +1,38 @@
|
||||
# To enable ssh & remote debugging on app service change the base image to the one below
|
||||
# FROM mcr.microsoft.com/azure-functions/node:4-node18-appservice
|
||||
# FROM mcr.microsoft.com/azure-functions/node:4-node18
|
||||
FROM node:18.17.1-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
|
||||
|
||||
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
|
||||
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
|
||||
|
||||
# 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
|
||||
|
||||
# Update NPM
|
||||
RUN npm install -g npm
|
||||
|
||||
# 以下 ユーザー権限で実施
|
||||
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
|
||||
57
dictation_function/.devcontainer/devcontainer.json
Normal file
57
dictation_function/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,57 @@
|
||||
// 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": "Dev Dictation Function",
|
||||
"dockerComposeFile": [
|
||||
"docker-compose.yml"
|
||||
],
|
||||
"service": "dictation_function",
|
||||
// コンテナを自動停止させない
|
||||
"shutdownAction": "none",
|
||||
"workspaceFolder": "/app/dictation_function",
|
||||
"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",
|
||||
"Azurite.azurite"
|
||||
],
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "yarn install",
|
||||
"postCreateCommand": "sudo chown -R vscode:vscode /app/dictation_function",
|
||||
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode"
|
||||
}
|
||||
@ -5,8 +5,8 @@ services:
|
||||
build: .
|
||||
working_dir: /app/dictation_function
|
||||
ports:
|
||||
- "3001:3001"
|
||||
- "6007:6007"
|
||||
- "80:80"
|
||||
- "8082:8082"
|
||||
volumes:
|
||||
- ../../:/app
|
||||
- node_modules:/app/dictation_function/node_modules
|
||||
20
dictation_function/.devcontainer/init.sh
Normal file
20
dictation_function/.devcontainer/init.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Init Script for function Container
|
||||
#
|
||||
|
||||
echo [init.sh] dictation_function 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/dictation_function
|
||||
|
||||
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!"
|
||||
133
dictation_function/.devcontainer/library-scripts/go-debian.sh
Normal file
133
dictation_function/.devcontainer/library-scripts/go-debian.sh
Normal file
@ -0,0 +1,133 @@
|
||||
#!/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.
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docs/go.md
|
||||
#
|
||||
# Syntax: ./go-debian.sh [Go version] [GOROOT] [GOPATH] [non-root user] [Add GOPATH, GOROOT to rc files flag] [Install tools flag]
|
||||
|
||||
TARGET_GO_VERSION=${1:-"latest"}
|
||||
TARGET_GOROOT=${2:-"/usr/local/go"}
|
||||
TARGET_GOPATH=${3:-"/go"}
|
||||
USERNAME=${4:-"automatic"}
|
||||
UPDATE_RC=${5:-"true"}
|
||||
INSTALL_GO_TOOLS=${6:-"true"}
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
|
||||
rm -f /etc/profile.d/00-restore-env.sh
|
||||
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
|
||||
chmod +x /etc/profile.d/00-restore-env.sh
|
||||
|
||||
# Determine the appropriate non-root user
|
||||
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
||||
USERNAME=""
|
||||
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
|
||||
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
|
||||
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
|
||||
USERNAME=${CURRENT_USER}
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "${USERNAME}" = "" ]; then
|
||||
USERNAME=root
|
||||
fi
|
||||
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
|
||||
USERNAME=root
|
||||
fi
|
||||
|
||||
function updaterc() {
|
||||
if [ "${UPDATE_RC}" = "true" ]; then
|
||||
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
|
||||
echo -e "$1" >> /etc/bash.bashrc
|
||||
if [ -f "/etc/zsh/zshrc" ]; then
|
||||
echo -e "$1" >> /etc/zsh/zshrc
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install curl, tar, git, other dependencies if missing
|
||||
if ! dpkg -s curl ca-certificates tar git g++ gcc libc6-dev make pkg-config > /dev/null 2>&1; then
|
||||
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
|
||||
apt-get update
|
||||
fi
|
||||
apt-get -y install --no-install-recommends curl ca-certificates tar git g++ gcc libc6-dev make pkg-config
|
||||
fi
|
||||
|
||||
# Get latest version number if latest is specified
|
||||
if [ "${TARGET_GO_VERSION}" = "latest" ] || [ "${TARGET_GO_VERSION}" = "current" ] || [ "${TARGET_GO_VERSION}" = "lts" ]; then
|
||||
TARGET_GO_VERSION=$(curl -sSL "https://golang.org/VERSION?m=text" | sed -n '/^go/s///p' )
|
||||
fi
|
||||
|
||||
# Install Go
|
||||
GO_INSTALL_SCRIPT="$(cat <<EOF
|
||||
set -e
|
||||
echo "Downloading Go ${TARGET_GO_VERSION}..."
|
||||
curl -sSL -o /tmp/go.tar.gz "https://golang.org/dl/go${TARGET_GO_VERSION}.linux-amd64.tar.gz"
|
||||
echo "Extracting Go ${TARGET_GO_VERSION}..."
|
||||
tar -xzf /tmp/go.tar.gz -C "${TARGET_GOROOT}" --strip-components=1
|
||||
rm -f /tmp/go.tar.gz
|
||||
EOF
|
||||
)"
|
||||
if [ "${TARGET_GO_VERSION}" != "none" ] && ! type go > /dev/null 2>&1; then
|
||||
mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}"
|
||||
chown -R ${USERNAME} "${TARGET_GOROOT}" "${TARGET_GOPATH}"
|
||||
su ${USERNAME} -c "${GO_INSTALL_SCRIPT}"
|
||||
else
|
||||
echo "Go already installed. Skipping."
|
||||
fi
|
||||
|
||||
# Install Go tools that are isImportant && !replacedByGopls based on
|
||||
# https://github.com/golang/vscode-go/blob/0c6dce4a96978f61b022892c1376fe3a00c27677/src/goTools.ts#L188
|
||||
# exception: golangci-lint is installed using their install script below.
|
||||
# バージョン指定だとインストールがこけるため、latestを指定。
|
||||
GO_TOOLS="\
|
||||
golang.org/x/tools/gopls@latest \
|
||||
honnef.co/go/tools/...@latest \
|
||||
golang.org/x/lint/golint@latest \
|
||||
github.com/mgechev/revive@latest \
|
||||
github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest \
|
||||
github.com/ramya-rao-a/go-outline@latest \
|
||||
github.com/go-delve/delve/cmd/dlv@latest \
|
||||
github.com/golangci/golangci-lint/cmd/golangci-lint@latest \
|
||||
github.com/cweill/gotests/...@latest \
|
||||
github.com/davidrjenni/reftools/cmd/fillstruct@latest "
|
||||
if [ "${INSTALL_GO_TOOLS}" = "true" ]; then
|
||||
echo "Installing common Go tools..."
|
||||
export PATH=${TARGET_GOROOT}/bin:${PATH}
|
||||
echo `PATH=${TARGET_GOROOT}/bin:${PATH}`
|
||||
mkdir -p /tmp/gotools /usr/local/etc/vscode-dev-containers ${TARGET_GOPATH}/bin
|
||||
cd /tmp/gotools
|
||||
export GOPATH=/tmp/gotools
|
||||
export GOCACHE=/tmp/gotools/cache
|
||||
|
||||
# Go tools w/module support
|
||||
export GO111MODULE=on
|
||||
(echo "${GO_TOOLS}" | xargs -n 1 go install -v )2>&1 | tee -a /usr/local/etc/vscode-dev-containers/go.log
|
||||
|
||||
# Move Go tools into path and clean up
|
||||
mv /tmp/gotools/bin/* ${TARGET_GOPATH}/bin/
|
||||
rm -rf /tmp/gotools
|
||||
chown -R ${USERNAME} "${TARGET_GOPATH}"
|
||||
fi
|
||||
|
||||
# Add GOPATH variable and bin directory into PATH in bashrc/zshrc files (unless disabled)
|
||||
updaterc "$(cat << EOF
|
||||
export GOPATH="${TARGET_GOPATH}"
|
||||
if [[ "\${PATH}" != *"\${GOPATH}/bin"* ]]; then export PATH="\${PATH}:\${GOPATH}/bin"; fi
|
||||
export GOROOT="${TARGET_GOROOT}"
|
||||
if [[ "\${PATH}" != *"\${GOROOT}/bin"* ]]; then export PATH="\${PATH}:\${GOROOT}/bin"; fi
|
||||
EOF
|
||||
)"
|
||||
|
||||
echo "Done!"
|
||||
2
dictation_function/package-lock.json
generated
2
dictation_function/package-lock.json
generated
@ -7,7 +7,7 @@
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@azure/functions": "^4.0.0-alpha.9"
|
||||
"@azure/functions": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.x",
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
"test": "echo \"No tests yet...\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/functions": "^4.0.0-alpha.9"
|
||||
"@azure/functions": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"azure-functions-core-tools": "^4.x",
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
|
||||
|
||||
export async function HttpExample(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
|
||||
context.log(`Http function processed request for url "${request.url}"`);
|
||||
|
||||
const name = request.query.get('name') || await request.text() || 'world';
|
||||
|
||||
return { body: `Hello, ${name}!` };
|
||||
};
|
||||
|
||||
app.http('HttpExample', {
|
||||
methods: ['GET', 'POST'],
|
||||
authLevel: 'anonymous',
|
||||
handler: HttpExample
|
||||
});
|
||||
15
dictation_function/src/functions/timerTriggerExample.ts
Normal file
15
dictation_function/src/functions/timerTriggerExample.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { app, InvocationContext, Timer } from "@azure/functions";
|
||||
|
||||
// タイマートリガー処理のサンプルです
|
||||
// TODO:開発が進んだら削除すること
|
||||
export async function timerTriggerExample(
|
||||
myTimer: Timer,
|
||||
context: InvocationContext
|
||||
): Promise<void> {
|
||||
context.log("Timer function processed request.");
|
||||
}
|
||||
|
||||
app.timer("timerTriggerExample", {
|
||||
schedule: "0 */1 * * * *",
|
||||
handler: timerTriggerExample,
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user