-
@@ -1231,7 +1225,12 @@ const DictationPage: React.FC = (): JSX.Element => {
|
)}
{displayColumn.Priority && (
-
+ |
{x.priority === "01"
? PRIORITY.HIGH
: PRIORITY.NORMAL}
diff --git a/dictation_client/src/pages/ErrorPage/index.tsx b/dictation_client/src/pages/ErrorPage/index.tsx
index 4592ea0..6d82f50 100644
--- a/dictation_client/src/pages/ErrorPage/index.tsx
+++ b/dictation_client/src/pages/ErrorPage/index.tsx
@@ -1,8 +1,10 @@
import React from "react";
+import { Link } from "react-router-dom";
export const AuthErrorPage = (): JSX.Element => (
- ログインに失敗しました
+ login failed
+ return to TopPage
);
diff --git a/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx b/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx
index 9cbafd0..1a3a4cb 100644
--- a/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx
+++ b/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx
@@ -171,8 +171,11 @@ export const LicenseOrderHistory: React.FC = (
- {t(getTranslationID("orderHistoriesPage.label.title"))}
+ {t(getTranslationID("LicenseSummaryPage.label.title"))}
+
+ {t(getTranslationID("orderHistoriesPage.label.orderHistory"))}
+
diff --git a/dictation_client/src/pages/LoginPage/index.tsx b/dictation_client/src/pages/LoginPage/index.tsx
index c335bd3..8727452 100644
--- a/dictation_client/src/pages/LoginPage/index.tsx
+++ b/dictation_client/src/pages/LoginPage/index.tsx
@@ -1,6 +1,6 @@
import { useMsal } from "@azure/msal-react";
import { AppDispatch } from "app/store";
-import { isIdToken } from "common/token";
+import { isIdToken, isTokenExpired } from "common/token";
import {
clearToken,
isAdminUser,
@@ -52,10 +52,10 @@ const LoginPage: React.FC = (): JSX.Element => {
instance.logoutRedirect({
postLogoutRedirectUri: "/AuthError",
});
- clearToken();
- }, [instance, navigate]);
+ dispatch(clearToken());
+ }, [instance, navigate, dispatch]);
- const tokenSet = useCallback(
+ const tokenSetAndNavigate = useCallback(
async (idToken: string) => {
// ログイン処理呼び出し
const { meta, payload } = await dispatch(loginAsync({ idToken }));
@@ -96,31 +96,32 @@ const LoginPage: React.FC = (): JSX.Element => {
useEffect(() => {
// idTokenStringがあるか⇒認証中
- // accessTokenがある場合⇒ログイン済み
- // どちらもなければ直打ち
+ // accessTokenがある場合⇒ログイン済みなのにブラウザバックでログイン画面に戻ってきた場合
+ // どちらもなければURL直打ち
(async () => {
- if (loadAccessToken()) {
- navigateToLoginedPage();
- return;
+ // ローカルストレージにidTokenがある場合は取得する
+ let idTokenString: string | null = null;
+ if (localStorageKeyforIdToken !== null) {
+ idTokenString = localStorage.getItem(localStorageKeyforIdToken);
}
- // AADB2Cのログイン画面とLoginPageを経由していない場合はトップページに遷移する
- if (!localStorageKeyforIdToken) {
- navigate("/");
- return;
- }
- const idTokenString = localStorage.getItem(localStorageKeyforIdToken);
-
+ // idTokenがない(=正常なログインプロセス中でない)場合は有効なアクセストークンを所持しているか確認し、
+ // 有効であればログイン画面に遷移 or 無効であればトップページに遷移
if (idTokenString === null) {
- navigate("/");
+ const token = loadAccessToken();
+ // アクセストークンがない or 有効期限切れ場合はトップページに遷移
+ if (isTokenExpired(token)) {
+ navigate("/");
+ } else {
+ // 有効なアクセストークンがある場合はログイン画面に遷移
+ navigateToLoginedPage();
+ }
return;
}
- if (idTokenString) {
- const idTokenObject = JSON.parse(idTokenString);
- if (isIdToken(idTokenObject)) {
- await tokenSet(idTokenObject.secret);
- }
+ const idTokenObject = JSON.parse(idTokenString);
+ if (isIdToken(idTokenObject)) {
+ await tokenSetAndNavigate(idTokenObject.secret);
}
})();
// 画面描画後のみ実行するため引数を設定しない
diff --git a/dictation_client/src/pages/UserListPage/index.tsx b/dictation_client/src/pages/UserListPage/index.tsx
index b6b0072..76b3a8b 100644
--- a/dictation_client/src/pages/UserListPage/index.tsx
+++ b/dictation_client/src/pages/UserListPage/index.tsx
@@ -147,104 +147,115 @@ const UserListPage: React.FC = (): JSX.Element => {
-
-
-
- | {/** th is empty */} |
- {t(getTranslationID("userListPage.label.name"))} |
- {t(getTranslationID("userListPage.label.role"))} |
-
- {t(getTranslationID("userListPage.label.authorID"))}
- |
-
- {t(getTranslationID("userListPage.label.encryption"))}
- |
-
- {t(getTranslationID("userListPage.label.prompt"))}
- |
-
- {t(getTranslationID("userListPage.label.typistGroup"))}
- |
- {t(getTranslationID("userListPage.label.email"))} |
-
- {t(getTranslationID("userListPage.label.status"))}
- |
-
- {t(getTranslationID("userListPage.label.expiration"))}
- |
-
- {t(getTranslationID("userListPage.label.remaining"))}
- |
-
- {t(getTranslationID("userListPage.label.autoRenew"))}
- |
-
- {t(getTranslationID("userListPage.label.notification"))}
- |
-
- {t(
- getTranslationID("userListPage.label.emailVerified")
- )}
- |
-
- {!isLoading &&
- users.map((user) => (
-
-
-
- -
- {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
- {
- onUpdateOpen(user.id);
- }}
- >
- {t(
- getTranslationID(
- "userListPage.label.editUser"
- )
- )}
-
-
- {isTier5 && (
- <>
- -
- {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
- {
- onAllocateLicensePopupOpen(user);
- }}
- >
- {t(
- getTranslationID(
- "userListPage.label.licenseAllocation"
- )
- )}
-
-
- -
- {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
- {
- onLicenseDeallocation(user.id);
- }}
- >
- {t(
- getTranslationID(
- "userListPage.label.licenseDeallocation"
- )
- )}
-
-
- >
- )}
- {/* ユーザー削除 CCB後回し分なので今は非表示
+
+
+
+
+ | {/** th is empty */} |
+
+ {t(getTranslationID("userListPage.label.name"))}
+ |
+
+ {t(getTranslationID("userListPage.label.role"))}
+ |
+
+ {t(getTranslationID("userListPage.label.authorID"))}
+ |
+
+ {t(getTranslationID("userListPage.label.encryption"))}
+ |
+
+ {t(getTranslationID("userListPage.label.prompt"))}
+ |
+
+ {t(
+ getTranslationID("userListPage.label.typistGroup")
+ )}
+ |
+
+ {t(getTranslationID("userListPage.label.email"))}
+ |
+
+ {t(getTranslationID("userListPage.label.status"))}
+ |
+
+ {t(getTranslationID("userListPage.label.expiration"))}
+ |
+
+ {t(getTranslationID("userListPage.label.remaining"))}
+ |
+
+ {t(getTranslationID("userListPage.label.autoRenew"))}
+ |
+
+ {t(
+ getTranslationID("userListPage.label.notification")
+ )}
+ |
+
+ {t(
+ getTranslationID("userListPage.label.emailVerified")
+ )}
+ |
+
+ {!isLoading &&
+ users.map((user) => (
+
+ |
+
- |
- {user.name} |
- {user.role} |
- {user.authorId} |
- {boolToElement(user.encryption)} |
- {boolToElement(user.prompt)} |
- {arrayToElement(user.typistGroupName)} |
- {user.email} |
-
-
- {getLicenseStatus(user.licenseStatus)}
-
- |
-
-
- {user.expiration ?? "-"}
-
- |
-
-
- {user.remaining ?? "-"}
-
- |
- {boolToElement(user.autoRenew)} |
- {boolToElement(user.notification)} |
- {boolToElement(user.emailVerified)} |
-
- ))}
-
-
+
+ |
+ {user.name} |
+ {user.role} |
+ {user.authorId} |
+ {boolToElement(user.encryption)} |
+ {boolToElement(user.prompt)} |
+ {arrayToElement(user.typistGroupName)} |
+ {user.email} |
+
+
+ {getLicenseStatus(user.licenseStatus)}
+
+ |
+
+
+ {user.expiration ?? "-"}
+
+ |
+
+
+ {user.remaining ?? "-"}
+
+ |
+ {boolToElement(user.autoRenew)} |
+ {boolToElement(user.notification)} |
+ {boolToElement(user.emailVerified)} |
+
+ ))}
+
+
+
{!isLoading && users.length === 0 && (
= (
-
-
-
- |
- {t(getTranslationID("worktypeIdSetting.label.itemLabel"))}
- |
-
- {t(
- getTranslationID("worktypeIdSetting.label.defaultValue")
- )}
- |
-
- {t(
- getTranslationID("worktypeIdSetting.label.initialValue")
- )}
- |
-
- {optionItems?.map((item) => (
-
- |
- {
- const { value } = e.target;
- // optionItemsの更新
- const newOptionItem = {
- ...item,
- itemLabel: value,
- };
- onChangeOptionItem(newOptionItem);
- }}
- />
- |
-
-
- |
-
- {item.defaultValueType ===
- OPTION_ITEMS_DEFAULT_VALUE_TYPE.DEFAULT ? (
+
{isPushSaveButton && hasInvalidOptionItems && (
@@ -248,14 +273,6 @@ export const EditOptionItemsPopup: React.FC = (
)}
)}
-
- {t(
- getTranslationID("worktypeIdSetting.label.optionItemTerms")
- )}
-
-
diff --git a/dictation_client/src/styles/app.module.scss b/dictation_client/src/styles/app.module.scss
index c075fdc..0753e75 100644
--- a/dictation_client/src/styles/app.module.scss
+++ b/dictation_client/src/styles/app.module.scss
@@ -1130,6 +1130,9 @@ h3 + .brCrumb .tlIcon {
.modal .form .table.backup td:first-child {
padding: 0.6rem 0.2rem;
}
+.modal .form .table.optionItem select {
+ width: 123px;
+}
.modal .form .pagenation {
margin-bottom: 1.5rem;
padding-right: 2.5%;
@@ -1597,15 +1600,6 @@ _:-ms-lang(x)::-ms-backdrop,
left: 0;
z-index: 2;
}
-.account .table.user,
-.user .table.user,
-.license .table.user,
-.dictation .table.user,
-.partners .table.user,
-.workflow .table.user,
-.support .table.user {
- margin-bottom: 5rem;
-}
.account .table.user th::after,
.user .table.user th::after,
.license .table.user th::after,
@@ -1626,6 +1620,16 @@ _:-ms-lang(x)::-ms-backdrop,
vertical-align: top;
}
+.user .table {
+ margin-bottom: 0;
+}
+.user .tableWrap {
+ max-width: calc(100vw - 5.1rem);
+ max-height: 90vh;
+ overflow-x: scroll;
+ margin-bottom: 5rem;
+}
+
.account .listVertical {
margin-bottom: 3rem;
}
@@ -2488,10 +2492,13 @@ tr.isSelected .menuInTable li a.isDisable {
.formChange ul.chooseMember li input + label,
.formChange ul.holdMember li input + label {
display: block;
- padding: 0.2rem 0 0.2rem 1.5rem;
+ padding: 0.4rem 0 0.4rem 1.5rem;
margin-right: 0;
background: url(../assets/images/circle.svg) no-repeat left center;
background-size: 1.3rem;
+ white-space: pre-line;
+ word-break: break-all;
+ line-height: 1.3;
}
.formChange ul.chooseMember li input + label:hover,
.formChange ul.holdMember li input + label:hover {
@@ -2501,7 +2508,7 @@ tr.isSelected .menuInTable li a.isDisable {
}
.formChange ul.chooseMember li input:checked + label,
.formChange ul.holdMember li input:checked + label {
- padding: 0.2rem 1rem 0.2rem 0;
+ padding: 0.4rem 1.5rem 0.4rem 0;
background: url(../assets/images/check_circle_fill.svg) no-repeat right center;
background-size: 1.3rem;
}
diff --git a/dictation_client/src/styles/app.module.scss.d.ts b/dictation_client/src/styles/app.module.scss.d.ts
index 68fcbca..d6ebd8f 100644
--- a/dictation_client/src/styles/app.module.scss.d.ts
+++ b/dictation_client/src/styles/app.module.scss.d.ts
@@ -74,6 +74,7 @@ declare const classNames: {
readonly table: "table";
readonly tableHeader: "tableHeader";
readonly backup: "backup";
+ readonly optionItem: "optionItem";
readonly pagenation: "pagenation";
readonly encryptionPass: "encryptionPass";
readonly pageHeader: "pageHeader";
diff --git a/dictation_function/src/entity/user.entity.ts b/dictation_function/src/entity/user.entity.ts
index 78d2c7d..10032d4 100644
--- a/dictation_function/src/entity/user.entity.ts
+++ b/dictation_function/src/entity/user.entity.ts
@@ -40,9 +40,6 @@ export class User {
@Column({ default: true })
auto_renew: boolean;
- @Column({ default: true })
- license_alert: boolean;
-
@Column({ default: true })
notification: boolean;
diff --git a/dictation_function/src/test/common/utility.ts b/dictation_function/src/test/common/utility.ts
index 512d975..f675ed7 100644
--- a/dictation_function/src/test/common/utility.ts
+++ b/dictation_function/src/test/common/utility.ts
@@ -48,7 +48,6 @@ export const makeTestUser = async (
accepted_dpa_version: d?.accepted_dpa_version ?? "1.0",
email_verified: d?.email_verified ?? true,
auto_renew: d?.auto_renew ?? true,
- license_alert: d?.license_alert ?? true,
notification: d?.notification ?? true,
encryption: d?.encryption ?? true,
encryption_password: d?.encryption_password,
@@ -117,7 +116,6 @@ export const makeTestAccount = async (
accepted_dpa_version: d?.accepted_dpa_version ?? "1.0",
email_verified: d?.email_verified ?? true,
auto_renew: d?.auto_renew ?? true,
- license_alert: d?.license_alert ?? true,
notification: d?.notification ?? true,
encryption: d?.encryption ?? true,
encryption_password: d?.encryption_password ?? "password",
diff --git a/dictation_server/src/features/tasks/tasks.service.spec.ts b/dictation_server/src/features/tasks/tasks.service.spec.ts
index d50233a..0b77c95 100644
--- a/dictation_server/src/features/tasks/tasks.service.spec.ts
+++ b/dictation_server/src/features/tasks/tasks.service.spec.ts
@@ -11,6 +11,7 @@ import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { TasksService } from './tasks.service';
import { DataSource } from 'typeorm';
import {
+ createAudioFile,
createCheckoutPermissions,
createTask,
createUserGroup,
@@ -703,6 +704,19 @@ describe('TasksService', () => {
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
+
+ //「バグ 3661: [FB対応]Option Itemにチェックを付けると真っ白な画面になる」の確認のため
+ // audio_file_idをTaskIdと異なる値にするために、AudioFileを作成
+ await createAudioFile(
+ source,
+ accountId,
+ userId,
+ 'MY_AUTHOR_ID',
+ '',
+ '00',
+ );
+
+ // Taskを作成
await createTask(
source,
accountId,
@@ -746,10 +760,26 @@ describe('TasksService', () => {
{
const task = tasks[0];
expect(task.jobNumber).toEqual('00000001');
+ // AudioOptionItem
+ const audioOptionItems = Array.from({ length: 10 }).map((_, i) => {
+ return {
+ optionItemLabel: `label${i}:audio_file_id${task.audioFileId}`,
+ optionItemValue: `value${i}:audio_file_id${task.audioFileId}`,
+ };
+ });
+ expect(task.optionItemList).toEqual(audioOptionItems);
}
{
const task = tasks[1];
expect(task.jobNumber).toEqual('00000002');
+ // AudioOptionItem
+ const audioOptionItems = Array.from({ length: 10 }).map((_, i) => {
+ return {
+ optionItemLabel: `label${i}:audio_file_id${task.audioFileId}`,
+ optionItemValue: `value${i}:audio_file_id${task.audioFileId}`,
+ };
+ });
+ expect(task.optionItemList).toEqual(audioOptionItems);
}
});
it('[Author] Authorは同一アカウントであっても自分以外のAuhtorのTaskは取得できない', async () => {
diff --git a/dictation_server/src/features/tasks/test/utility.ts b/dictation_server/src/features/tasks/test/utility.ts
index 171f061..9931b6b 100644
--- a/dictation_server/src/features/tasks/test/utility.ts
+++ b/dictation_server/src/features/tasks/test/utility.ts
@@ -38,6 +38,7 @@ import {
NotificationhubServiceMockValue,
makeNotificationhubServiceMock,
} from './tasks.service.mock';
+import { AudioOptionItem } from '../../../repositories/audio_option_items/entity/audio_option_item.entity';
export const makeTaskTestingModuleWithNotificaiton = async (
datasource: DataSource,
@@ -130,6 +131,18 @@ export const createTask = async (
audio_format: 'audio_format',
is_encrypted: true,
});
+ // AudioOptionItemを10個作成
+ const audioOptionItems = Array.from({ length: 10 }).map((_, i) => {
+ return {
+ audio_file_id: audioFileIdentifiers[0].id,
+ label: `label${i}:audio_file_id${audioFileIdentifiers[0].id}`,
+ value: `value${i}:audio_file_id${audioFileIdentifiers[0].id}`,
+ };
+ }
+ );
+
+ await datasource.getRepository(AudioOptionItem).insert(audioOptionItems);
+
const audioFile = audioFileIdentifiers.pop() as AudioFile;
const { identifiers: taskIdentifiers } = await datasource
.getRepository(Task)
@@ -147,6 +160,37 @@ export const createTask = async (
const task = taskIdentifiers.pop() as Task;
return { taskId: task.id, audioFileId: audioFile.id };
};
+
+export const createAudioFile = async(
+ datasource: DataSource,
+ account_id: number,
+ owner_user_id: number,
+ author_id: string,
+ work_type_id: string,
+ priority: string,
+): Promise<{ audioFileId: number }> => {
+ const { identifiers: audioFileIdentifiers } = await datasource
+ .getRepository(AudioFile)
+ .insert({
+ account_id: account_id,
+ owner_user_id: owner_user_id,
+ url: '',
+ file_name: 'x.zip',
+ author_id: author_id,
+ work_type_id: work_type_id,
+ started_at: new Date(),
+ duration: '100000',
+ finished_at: new Date(),
+ uploaded_at: new Date(),
+ file_size: 10000,
+ priority: priority,
+ audio_format: 'audio_format',
+ is_encrypted: true,
+ });
+ const audioFile = audioFileIdentifiers.pop() as AudioFile;
+ return { audioFileId: audioFile.id };
+}
+
/**
*
* @param datasource
diff --git a/dictation_server/src/features/users/users.service.ts b/dictation_server/src/features/users/users.service.ts
index 359f163..6b58912 100644
--- a/dictation_server/src/features/users/users.service.ts
+++ b/dictation_server/src/features/users/users.service.ts
@@ -1073,13 +1073,13 @@ export class UsersService {
const { parent_account_id: dealerId } =
await this.accountsRepository.findAccountById(context, accountId);
- if (dealerId == null) {
- throw new Error(`dealer is null. account_id=${accountId}`);
+ let dealerName: string | null = null;
+ if (dealerId !== null) {
+ const { company_name } =
+ await this.accountsRepository.findAccountById(context, dealerId);
+ dealerName = company_name;
}
- const { company_name: dealerName } =
- await this.accountsRepository.findAccountById(context, dealerId);
-
const { companyName, adminEmails } = await this.getAccountInformation(
context,
accountId,
diff --git a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts
index 985c7b1..17fa39b 100644
--- a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts
+++ b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts
@@ -41,6 +41,9 @@ export class SendGridService {
private readonly templateU107Text: string;
private readonly templateU108Html: string;
private readonly templateU108Text: string;
+ // U-108のテンプレート差分(親アカウントがない場合)
+ private readonly templateU108NoParentHtml: string;
+ private readonly templateU108NoParentText: string;
private readonly templateU109Html: string;
private readonly templateU109Text: string;
private readonly templateU111Html: string;
@@ -118,6 +121,17 @@ export class SendGridService {
path.resolve(__dirname, `../../templates/template_U_108.txt`),
'utf-8',
);
+ this.templateU108NoParentHtml = readFileSync(
+ path.resolve(
+ __dirname,
+ `../../templates/template_U_108_no_parent.html`,
+ ),
+ 'utf-8',
+ );
+ this.templateU108NoParentText = readFileSync(
+ path.resolve(__dirname, `../../templates/template_U_108_no_parent.txt`),
+ 'utf-8',
+ );
this.templateU109Html = readFileSync(
path.resolve(__dirname, `../../templates/template_U_109.html`),
'utf-8',
@@ -462,7 +476,7 @@ export class SendGridService {
userMail: string,
customerAdminMails: string[],
customerAccountName: string,
- dealerAccountName: string,
+ dealerAccountName: string | null,
): Promise {
this.logger.log(
`[IN] [${context.getTrackingId()}] ${this.sendMailWithU108.name}`,
@@ -471,19 +485,34 @@ export class SendGridService {
const subject = 'License Assigned Notification [U-108]';
const url = new URL(this.appDomain).href;
- // メールの本文を作成する
- const html = this.templateU108Html
- .replaceAll(CUSTOMER_NAME, customerAccountName)
- .replaceAll(DEALER_NAME, dealerAccountName)
- .replaceAll(USER_NAME, userName)
- .replaceAll(USER_EMAIL, userMail)
- .replaceAll(TOP_URL, url);
- const text = this.templateU108Text
- .replaceAll(CUSTOMER_NAME, customerAccountName)
- .replaceAll(DEALER_NAME, dealerAccountName)
- .replaceAll(USER_NAME, userName)
- .replaceAll(USER_EMAIL, userMail)
- .replaceAll(TOP_URL, url);
+ let html: string;
+ let text: string;
+
+ if (dealerAccountName === null) {
+ html = this.templateU108NoParentHtml
+ .replaceAll(CUSTOMER_NAME, customerAccountName)
+ .replaceAll(USER_NAME, userName)
+ .replaceAll(USER_EMAIL, userMail)
+ .replaceAll(TOP_URL, url);
+ text = this.templateU108NoParentText
+ .replaceAll(CUSTOMER_NAME, customerAccountName)
+ .replaceAll(USER_NAME, userName)
+ .replaceAll(USER_EMAIL, userMail)
+ .replaceAll(TOP_URL, url);
+ } else {
+ html = this.templateU108Html
+ .replaceAll(CUSTOMER_NAME, customerAccountName)
+ .replaceAll(DEALER_NAME, dealerAccountName)
+ .replaceAll(USER_NAME, userName)
+ .replaceAll(USER_EMAIL, userMail)
+ .replaceAll(TOP_URL, url);
+ text = this.templateU108Text
+ .replaceAll(CUSTOMER_NAME, customerAccountName)
+ .replaceAll(DEALER_NAME, dealerAccountName)
+ .replaceAll(USER_NAME, userName)
+ .replaceAll(USER_EMAIL, userMail)
+ .replaceAll(TOP_URL, url);
+ }
const ccAddress = customerAdminMails.includes(userMail) ? [] : [userMail];
diff --git a/dictation_server/src/repositories/audio_option_items/entity/audio_option_item.entity.ts b/dictation_server/src/repositories/audio_option_items/entity/audio_option_item.entity.ts
index 665ac69..5d586c5 100644
--- a/dictation_server/src/repositories/audio_option_items/entity/audio_option_item.entity.ts
+++ b/dictation_server/src/repositories/audio_option_items/entity/audio_option_item.entity.ts
@@ -18,6 +18,6 @@ export class AudioOptionItem {
@Column()
value: string;
@ManyToOne(() => Task, (task) => task.audio_file_id)
- @JoinColumn({ name: 'audio_file_id' })
+ @JoinColumn({ name: 'audio_file_id', referencedColumnName: 'audio_file_id' })
task: Task | null;
}
diff --git a/dictation_server/src/templates/template_U_108_no_parent.html b/dictation_server/src/templates/template_U_108_no_parent.html
new file mode 100644
index 0000000..b8b6b8b
--- /dev/null
+++ b/dictation_server/src/templates/template_U_108_no_parent.html
@@ -0,0 +1,69 @@
+
+
+ License Assigned Notification [U-108]
+
+
+
+ <English>
+ Dear $CUSTOMER_NAME$,
+
+ Please be informed that a license has been assigned to the following
+ user.
+ - User Name: $USER_NAME$
+ - Email: $USER_EMAIL$
+
+
+ Please log in to ODMS Cloud to verify the license expiration date.
+ URL: $TOP_URL$
+
+
+ If you have received this e-mail in error, please delete this e-mail
+ from your system.
+ This is an automatically generated e-mail and this mailbox is not
+ monitored. Please do not reply.
+
+
+
+ <Deutsch>
+ Sehr geehrte(r) $CUSTOMER_NAME$,
+
+ Bitte beachten Sie, dass dem folgenden Benutzer eine Lizenz zugewiesen
+ wurde.
+ - Nutzername: $USER_NAME$
+ - Email: $USER_EMAIL$
+
+
+ Bitte melden Sie sich bei ODMS Cloud an, um das Ablaufdatum der Lizenz
+ zu überprüfen.
+ URL: $TOP_URL$
+
+
+ Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie
+ diese E-Mail bitte aus Ihrem System.
+ Dies ist eine automatisch generierte E-Mail und dieses Postfach wird
+ nicht überwacht. Bitte nicht antworten.
+
+
+
+ <Français>
+ Chère/Cher $CUSTOMER_NAME$,
+
+ Veuillez être informé qu'une licence a été attribuée à l'utilisateur
+ suivant.
+ - Nom d'utilisateur: $USER_NAME$
+ - Email: $USER_EMAIL$
+
+
+ Veuillez vous connecter à ODMS Cloud pour vérifier la date d'expiration
+ de la licence.
+ URL: $TOP_URL$
+
+
+ Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail
+ de votre système.
+ Il s'agit d'un e-mail généré automatiquement et cette boîte aux lettres
+ n'est pas surveillée. Merci de ne pas répondre.
+
+
+
+
diff --git a/dictation_server/src/templates/template_U_108_no_parent.txt b/dictation_server/src/templates/template_U_108_no_parent.txt
new file mode 100644
index 0000000..b0ce4a2
--- /dev/null
+++ b/dictation_server/src/templates/template_U_108_no_parent.txt
@@ -0,0 +1,41 @@
+
+
+Dear $CUSTOMER_NAME$,
+
+Please be informed that a license has been assigned to the following user.
+ - User Name: $USER_NAME$
+ - Email: $USER_EMAIL$
+
+Please log in to ODMS Cloud to verify the license expiration date.
+URL: $TOP_URL$
+
+If you have received this e-mail in error, please delete this e-mail from your system.
+This is an automatically generated e-mail and this mailbox is not monitored. Please do not reply.
+
+
+
+Sehr geehrte(r) $CUSTOMER_NAME$,
+
+Bitte beachten Sie, dass dem folgenden Benutzer eine Lizenz zugewiesen wurde.
+ - Nutzername: $USER_NAME$
+ - Email: $USER_EMAIL$
+
+Bitte melden Sie sich bei ODMS Cloud an, um das Ablaufdatum der Lizenz zu überprüfen.
+URL: $TOP_URL$
+
+Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie diese E-Mail bitte aus Ihrem System.
+Dies ist eine automatisch generierte E-Mail und dieses Postfach wird nicht überwacht. Bitte nicht antworten.
+
+
+
+Chère/Cher $CUSTOMER_NAME$,
+
+Veuillez être informé qu'une licence a été attribuée à l'utilisateur suivant.
+ - Nom d'utilisateur: $USER_NAME$
+ - Email: $USER_EMAIL$
+
+Veuillez vous connecter à ODMS Cloud pour vérifier la date d'expiration de la licence.
+URL: $TOP_URL$
+
+Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail de votre système.
+Il s'agit d'un e-mail généré automatiquement et cette boîte aux lettres n'est pas surveillée. Merci de ne pas répondre.
\ No newline at end of file
| |