makabe.t ef83477533 Merged PR 305: ユーザー編集ポップアップ実装
## 概要
[Task2315: ユーザー編集ポップアップ実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2315)

- ユーザー編集ポップアップを実装しました。

## レビューポイント
- デザイン判定は適切か
  - 表示文言は適切か
- エラーチェックは適切か

## UIの変更
- [Task2315](https://ndstokyo.sharepoint.com/:f:/r/sites/Piranha/Shared%20Documents/General/OMDS/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88/Task2315?csf=1&web=1&e=AP7b9M)

## 動作確認状況
- ローカルで確認
2023-08-08 02:48:40 +00:00

230 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { RootState } from "app/store";
import { USER_ROLES } from "components/auth/constants";
import {
AddUser,
RoleType,
UserView,
isLicenseStatusType,
isRoleType,
} from "./types";
import { LICENSE_STATUS } from "./constants";
export const selectInputValidationErrors = (state: RootState) => {
const { name, email, role, authorId, encryption, encryptionPassword } =
state.user.apps.addUser;
// 必須項目のチェック
const hasErrorEmptyName = name === "";
const hasErrorEmptyEmail = email === "";
// Authorの場合、AuthorIDが必須(空文字,undefinedは不可)
const hasErrorEmptyAuthorId =
role === USER_ROLES.AUTHOR && (authorId === "" || !authorId);
const hasErrorIncorrectAuthorId = checkErrorIncorrectAuthorId(
authorId ?? undefined,
role
);
const hasErrorIncorrectEmail = email.match(/^[^@]+@[^@]+$/)?.length !== 1;
const hasErrorIncorrectEncryptionPassword =
checkErrorIncorrectEncryptionPassword(encryptionPassword, role, encryption);
return {
hasErrorEmptyName,
hasErrorEmptyEmail,
hasErrorEmptyAuthorId,
hasErrorIncorrectEmail,
hasErrorIncorrectAuthorId,
hasErrorIncorrectEncryptionPassword,
};
};
export const selectUpdateValidationErrors = (state: RootState) => {
const { role, authorId, encryption, encryptionPassword } =
state.user.apps.updateUser;
const { encryption: initEncryption } = state.user.apps.selectedUser;
// Authorの場合、AuthorIDが必須(空文字,undefinedは不可)
const hasErrorEmptyAuthorId =
role === USER_ROLES.AUTHOR && (authorId === "" || !authorId);
const hasErrorIncorrectAuthorId = checkErrorIncorrectAuthorId(
authorId ?? undefined,
role
);
let hasErrorIncorrectEncryptionPassword = false;
const passwordError = checkErrorIncorrectEncryptionPassword(
encryptionPassword,
role,
encryption
);
if (passwordError) {
// 最初にEncryptionがfasleで、Encryptionがtrueに変更された場合、EncryptionPasswordが必須
if (!initEncryption) {
hasErrorIncorrectEncryptionPassword = true;
// Encryptionがある状態で変更がある場合、EncryptionPasswordが空でもエラーにしない
} else if (!encryptionPassword || encryptionPassword === "") {
hasErrorIncorrectEncryptionPassword = false;
} else {
hasErrorIncorrectEncryptionPassword = true;
}
}
return {
hasErrorEmptyAuthorId,
hasErrorIncorrectAuthorId,
hasErrorIncorrectEncryptionPassword,
};
};
// encreyptionPasswordのチェック
const checkErrorIncorrectEncryptionPassword = (
encryptionPassword: string | undefined,
role: RoleType,
encryption: boolean | undefined
): boolean => {
// roleがAuthor以外の場合、チェックしない
if (role !== USER_ROLES.AUTHOR) {
return false;
}
// roleがAuthorかつencryptionがfalseの場合、チェックしない
if (!encryption) {
return false;
}
// encryptionPasswordがundefined,空文字の場合、エラー
if (!encryptionPassword || encryptionPassword === "") {
return true;
}
// encryptionPasswordがルールに則していない場合、エラー
const regex = /^[!-~]{4,16}$/;
if (!regex.test(encryptionPassword)) {
return true;
}
// チェックを通ったらエラーではない
return false;
};
export const checkErrorIncorrectAuthorId = (
authorId: string | undefined,
role: string
): boolean => {
if (!authorId || role !== USER_ROLES.AUTHOR) {
return false;
}
// 半角英数字と_の組み合わせで文字まで
const charaTypePattern = /^[A-Z0-9_]{1,16}$/;
const charaType = new RegExp(charaTypePattern).test(authorId);
return !charaType;
};
export const selectName = (state: RootState) => state.user.apps.addUser.name;
export const selectEmail = (state: RootState) => state.user.apps.addUser.email;
export const selectRole = (state: RootState) => state.user.apps.addUser.role;
export const selectAuthorId = (state: RootState) =>
state.user.apps.addUser.authorId;
export const selectAutoRenew = (state: RootState) =>
state.user.apps.addUser.autoRenew;
export const selectLicenseAlert = (state: RootState) =>
state.user.apps.addUser.licenseAlert;
export const selectNotification = (state: RootState) =>
state.user.apps.addUser.notification;
// AddUserを返却する
export const selectAddUser = (state: RootState): AddUser =>
state.user.apps.addUser;
// usersからUserViewに変換して返却する
export const selectUserViews = (state: RootState): UserView[] => {
const { users } = state.user.domain;
const userViews = users.map((user): UserView => {
const {
role,
authorId,
encryption,
prompt,
typistGroupName,
licenseStatus,
expiration,
remaining,
...rest
} = user;
// roleの型がstringなので、isRoleTypeで型ガードを行う
// roleの型がRoleTypeでなければ、何も返さない
if (!isRoleType(role) || !isLicenseStatusType(licenseStatus)) {
return {} as UserView;
}
const convertedValues = convertValueBasedOnRole(
role,
authorId,
encryption,
prompt,
typistGroupName
);
// restのid以外をUserViewに追加する
return {
typistGroupName: convertedValues.typistGroupName,
prompt: convertedValues.prompt,
encryption: convertedValues.encryption,
authorId: convertedValues.authorId,
// roleの一文字目を大文字に変換する
role: role.charAt(0).toUpperCase() + role.slice(1),
licenseStatus:
licenseStatus === LICENSE_STATUS.NORMAL ? "-" : licenseStatus,
expiration: expiration ?? "-",
remaining: remaining ?? "-",
...rest,
};
});
// 空のオブジェクトを除外する
return userViews.filter((userView) => Object.keys(userView).length !== 0);
};
export const selectIsLoading = (state: RootState) => state.user.apps.isLoading;
// roleに応じて値を変換する
const convertValueBasedOnRole = (
role: RoleType,
authorId: string | undefined,
encryption: boolean,
prompt: boolean,
typistGroupName: string[]
): {
authorId: string;
encryption: boolean | string;
prompt: boolean | string;
typistGroupName: string[] | string;
} => {
if (role === USER_ROLES.AUTHOR && authorId) {
return {
authorId,
encryption,
prompt,
typistGroupName: "-",
};
}
if (role === USER_ROLES.TYPIST) {
return {
authorId: "-",
encryption: "-",
prompt: "-",
typistGroupName,
};
}
return {
authorId: "-",
encryption: "-",
prompt: "-",
typistGroupName: "-",
};
};
export const selectUpdateUser = (state: RootState) =>
state.user.apps.updateUser;
export const selectHasPasswordMask = (state: RootState) =>
state.user.apps.hasPasswordMask;