Merged PR 344: 画面実装(ユーザー一覧画面修正)
## 概要 [Task2449: 画面実装(ユーザー一覧画面修正)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2449) - 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず) - 何をどう変更したか、追加したライブラリなど - ユーザー一覧画面を修正し、License Deallocation押下時にライセンス割り当て解除APIを呼び出す処理を追加しました - このPull Requestでの対象/対象外 - すべて対象になります - 影響範囲(他の機能にも影響があるか) - 無し ## レビューポイント - 特にレビューしてほしい箇所 - 軽微なものや自明なものは記載不要 - 修正範囲が大きい場合などに記載 - 全体的にや仕様を満たしているか等は本当に必要な時のみ記載 - 特筆すべきところはありません。 ## UIの変更 - 変更なし ## 動作確認状況 - ローカルで確認 ## 補足 - 特になし
This commit is contained in:
parent
c42ba4d3db
commit
177c8beb41
@ -446,6 +446,19 @@ export interface Dealer {
|
|||||||
*/
|
*/
|
||||||
country: string;
|
country: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface DeallocateLicenseRequest
|
||||||
|
*/
|
||||||
|
export interface DeallocateLicenseRequest {
|
||||||
|
/**
|
||||||
|
* ユーザーID
|
||||||
|
* @type {number}
|
||||||
|
* @memberof DeallocateLicenseRequest
|
||||||
|
*/
|
||||||
|
userId: number;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
@ -3601,8 +3614,6 @@ export const LicensesApiAxiosParamCreator = function (
|
|||||||
// http bearer authentication required
|
// http bearer authentication required
|
||||||
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
||||||
|
|
||||||
localVarHeaderParameter["Content-Type"] = "application/json";
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
let headersFromBaseOptions =
|
let headersFromBaseOptions =
|
||||||
baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
@ -3611,10 +3622,6 @@ export const LicensesApiAxiosParamCreator = function (
|
|||||||
...headersFromBaseOptions,
|
...headersFromBaseOptions,
|
||||||
...options.headers,
|
...options.headers,
|
||||||
};
|
};
|
||||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
|
||||||
localVarRequestOptions,
|
|
||||||
configuration
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: toPathString(localVarUrlObj),
|
url: toPathString(localVarUrlObj),
|
||||||
@ -5302,6 +5309,64 @@ export const UsersApiAxiosParamCreator = function (
|
|||||||
options: localVarRequestOptions,
|
options: localVarRequestOptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* ライセンス割り当てを解除します
|
||||||
|
* @summary
|
||||||
|
* @param {DeallocateLicenseRequest} deallocateLicenseRequest
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
deallocateLicense: async (
|
||||||
|
deallocateLicenseRequest: DeallocateLicenseRequest,
|
||||||
|
options: AxiosRequestConfig = {}
|
||||||
|
): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'deallocateLicenseRequest' is not null or undefined
|
||||||
|
assertParamExists(
|
||||||
|
"deallocateLicense",
|
||||||
|
"deallocateLicenseRequest",
|
||||||
|
deallocateLicenseRequest
|
||||||
|
);
|
||||||
|
const localVarPath = `/users/license/deallocate`;
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = {
|
||||||
|
method: "POST",
|
||||||
|
...baseOptions,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
||||||
|
|
||||||
|
localVarHeaderParameter["Content-Type"] = "application/json";
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions =
|
||||||
|
baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {
|
||||||
|
...localVarHeaderParameter,
|
||||||
|
...headersFromBaseOptions,
|
||||||
|
...options.headers,
|
||||||
|
};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||||
|
deallocateLicenseRequest,
|
||||||
|
localVarRequestOptions,
|
||||||
|
configuration
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* ログインしているユーザーに関連する各種情報を取得します
|
* ログインしているユーザーに関連する各種情報を取得します
|
||||||
* @summary
|
* @summary
|
||||||
@ -5684,6 +5749,31 @@ export const UsersApiFp = function (configuration?: Configuration) {
|
|||||||
configuration
|
configuration
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* ライセンス割り当てを解除します
|
||||||
|
* @summary
|
||||||
|
* @param {DeallocateLicenseRequest} deallocateLicenseRequest
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async deallocateLicense(
|
||||||
|
deallocateLicenseRequest: DeallocateLicenseRequest,
|
||||||
|
options?: AxiosRequestConfig
|
||||||
|
): Promise<
|
||||||
|
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>
|
||||||
|
> {
|
||||||
|
const localVarAxiosArgs =
|
||||||
|
await localVarAxiosParamCreator.deallocateLicense(
|
||||||
|
deallocateLicenseRequest,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
return createRequestFunction(
|
||||||
|
localVarAxiosArgs,
|
||||||
|
globalAxios,
|
||||||
|
BASE_PATH,
|
||||||
|
configuration
|
||||||
|
);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* ログインしているユーザーに関連する各種情報を取得します
|
* ログインしているユーザーに関連する各種情報を取得します
|
||||||
* @summary
|
* @summary
|
||||||
@ -5888,6 +5978,21 @@ export const UsersApiFactory = function (
|
|||||||
.confirmUserAndInitPassword(confirmRequest, options)
|
.confirmUserAndInitPassword(confirmRequest, options)
|
||||||
.then((request) => request(axios, basePath));
|
.then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* ライセンス割り当てを解除します
|
||||||
|
* @summary
|
||||||
|
* @param {DeallocateLicenseRequest} deallocateLicenseRequest
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
deallocateLicense(
|
||||||
|
deallocateLicenseRequest: DeallocateLicenseRequest,
|
||||||
|
options?: any
|
||||||
|
): AxiosPromise<object> {
|
||||||
|
return localVarFp
|
||||||
|
.deallocateLicense(deallocateLicenseRequest, options)
|
||||||
|
.then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* ログインしているユーザーに関連する各種情報を取得します
|
* ログインしているユーザーに関連する各種情報を取得します
|
||||||
* @summary
|
* @summary
|
||||||
@ -6024,6 +6129,23 @@ export class UsersApi extends BaseAPI {
|
|||||||
.then((request) => request(this.axios, this.basePath));
|
.then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ライセンス割り当てを解除します
|
||||||
|
* @summary
|
||||||
|
* @param {DeallocateLicenseRequest} deallocateLicenseRequest
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof UsersApi
|
||||||
|
*/
|
||||||
|
public deallocateLicense(
|
||||||
|
deallocateLicenseRequest: DeallocateLicenseRequest,
|
||||||
|
options?: AxiosRequestConfig
|
||||||
|
) {
|
||||||
|
return UsersApiFp(this.configuration)
|
||||||
|
.deallocateLicense(deallocateLicenseRequest, options)
|
||||||
|
.then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ログインしているユーザーに関連する各種情報を取得します
|
* ログインしているユーザーに関連する各種情報を取得します
|
||||||
* @summary
|
* @summary
|
||||||
|
|||||||
@ -46,4 +46,5 @@ export const errorCodes = [
|
|||||||
"E010804", // ライセンス数不足エラー
|
"E010804", // ライセンス数不足エラー
|
||||||
"E010805", // ライセンス有効期限切れエラー
|
"E010805", // ライセンス有効期限切れエラー
|
||||||
"E010806", // ライセンス割り当て不可エラー
|
"E010806", // ライセンス割り当て不可エラー
|
||||||
|
"E010807", // ライセンス割り当て解除不可エラー
|
||||||
] as const;
|
] as const;
|
||||||
|
|||||||
@ -306,3 +306,67 @@ export const allocateLicenseAsync = createAsyncThunk<
|
|||||||
return thunkApi.rejectWithValue({ error });
|
return thunkApi.rejectWithValue({ error });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const deallocateLicenseAsync = createAsyncThunk<
|
||||||
|
// 正常時の戻り値の型
|
||||||
|
{
|
||||||
|
/* Empty Object */
|
||||||
|
},
|
||||||
|
// 引数
|
||||||
|
{
|
||||||
|
userId: number;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("users/deallocateLicenseAsync", async (args, thunkApi) => {
|
||||||
|
const { userId } = args;
|
||||||
|
|
||||||
|
// apiのConfigurationを取得する
|
||||||
|
const { getState } = thunkApi;
|
||||||
|
const state = getState() as RootState;
|
||||||
|
const { configuration, accessToken } = state.auth;
|
||||||
|
const config = new Configuration(configuration);
|
||||||
|
const usersApi = new UsersApi(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await usersApi.deallocateLicense(
|
||||||
|
{
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "info",
|
||||||
|
message: getTranslationID("common.message.success"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return {};
|
||||||
|
} catch (e) {
|
||||||
|
// e ⇒ errorObjectに変換
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
|
||||||
|
let errorMessage = getTranslationID("common.message.internalServerError");
|
||||||
|
|
||||||
|
if (error.code === "E010807") {
|
||||||
|
errorMessage = getTranslationID(
|
||||||
|
"userListPage.message.alreadyLicenseDeallocatedError"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: errorMessage,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {
|
|||||||
listUsersAsync,
|
listUsersAsync,
|
||||||
updateUserAsync,
|
updateUserAsync,
|
||||||
getAllocatableLicensesAsync,
|
getAllocatableLicensesAsync,
|
||||||
|
deallocateLicenseAsync,
|
||||||
} from "./operations";
|
} from "./operations";
|
||||||
import { RoleType, UserView } from "./types";
|
import { RoleType, UserView } from "./types";
|
||||||
|
|
||||||
@ -298,6 +299,15 @@ export const userSlice = createSlice({
|
|||||||
builder.addCase(getAllocatableLicensesAsync.rejected, (state) => {
|
builder.addCase(getAllocatableLicensesAsync.rejected, (state) => {
|
||||||
state.apps.isLoading = false;
|
state.apps.isLoading = false;
|
||||||
});
|
});
|
||||||
|
builder.addCase(deallocateLicenseAsync.pending, (state) => {
|
||||||
|
state.apps.isLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(deallocateLicenseAsync.fulfilled, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(deallocateLicenseAsync.rejected, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import {
|
|||||||
listUsersAsync,
|
listUsersAsync,
|
||||||
selectUserViews,
|
selectUserViews,
|
||||||
selectIsLoading,
|
selectIsLoading,
|
||||||
|
deallocateLicenseAsync,
|
||||||
} from "features/user";
|
} from "features/user";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { getTranslationID } from "translation";
|
import { getTranslationID } from "translation";
|
||||||
@ -57,6 +58,24 @@ const UserListPage: React.FC = (): JSX.Element => {
|
|||||||
[setIsAllocateLicensePopupOpen, dispatch]
|
[setIsAllocateLicensePopupOpen, dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onLicenseDeallocation = useCallback(
|
||||||
|
async (userId: number) => {
|
||||||
|
// ダイアログ確認
|
||||||
|
if (
|
||||||
|
/* eslint-disable-next-line no-alert */
|
||||||
|
!window.confirm(t(getTranslationID("common.message.dialogConfirm")))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { meta } = await dispatch(deallocateLicenseAsync({ userId }));
|
||||||
|
if (meta.requestStatus === "fulfilled") {
|
||||||
|
dispatch(listUsersAsync());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch, t]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// ユーザ一覧取得処理を呼び出す
|
// ユーザ一覧取得処理を呼び出す
|
||||||
dispatch(listUsersAsync());
|
dispatch(listUsersAsync());
|
||||||
@ -196,7 +215,18 @@ const UserListPage: React.FC = (): JSX.Element => {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="">
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
|
||||||
|
<a
|
||||||
|
className={
|
||||||
|
user.licenseStatus !==
|
||||||
|
LICENSE_STATUS.NOLICENSE
|
||||||
|
? styles.isDisable
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
onLicenseDeallocation(user.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
{t(
|
{t(
|
||||||
getTranslationID(
|
getTranslationID(
|
||||||
"userListPage.label.licenseDeallocation"
|
"userListPage.label.licenseDeallocation"
|
||||||
|
|||||||
@ -113,7 +113,8 @@
|
|||||||
"authorIdConflictError": "(de)このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
"authorIdConflictError": "(de)このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
||||||
"authorIdIncorrectError": "(de)Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
"authorIdIncorrectError": "(de)Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
||||||
"roleChangeError": "(de)Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
"roleChangeError": "(de)Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
||||||
"encryptionPasswordCorrectError": "(de)EncryptionPasswordがルールを満たしていません。"
|
"encryptionPasswordCorrectError": "(de)EncryptionPasswordがルールを満たしていません。",
|
||||||
|
"alreadyLicenseDeallocatedError": "(de)すでにライセンス割り当てが解除されています。画面を更新して再度ご確認下さい。"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"title": "(de)User",
|
"title": "(de)User",
|
||||||
|
|||||||
@ -113,7 +113,8 @@
|
|||||||
"authorIdConflictError": "このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
"authorIdConflictError": "このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
||||||
"authorIdIncorrectError": "Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
"authorIdIncorrectError": "Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
||||||
"roleChangeError": "Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
"roleChangeError": "Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
||||||
"encryptionPasswordCorrectError": "EncryptionPasswordがルールを満たしていません。"
|
"encryptionPasswordCorrectError": "EncryptionPasswordがルールを満たしていません。",
|
||||||
|
"alreadyLicenseDeallocatedError": "すでにライセンス割り当てが解除されています。画面を更新して再度ご確認下さい。"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"title": "User",
|
"title": "User",
|
||||||
|
|||||||
@ -113,7 +113,8 @@
|
|||||||
"authorIdConflictError": "(es)このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
"authorIdConflictError": "(es)このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
||||||
"authorIdIncorrectError": "(es)Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
"authorIdIncorrectError": "(es)Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
||||||
"roleChangeError": "(es)Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
"roleChangeError": "(es)Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
||||||
"encryptionPasswordCorrectError": "(es)EncryptionPasswordがルールを満たしていません。"
|
"encryptionPasswordCorrectError": "(es)EncryptionPasswordがルールを満たしていません。",
|
||||||
|
"alreadyLicenseDeallocatedError": "(es)すでにライセンス割り当てが解除されています。画面を更新して再度ご確認下さい。"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"title": "(es)User",
|
"title": "(es)User",
|
||||||
|
|||||||
@ -113,7 +113,8 @@
|
|||||||
"authorIdConflictError": "(fr)このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
"authorIdConflictError": "(fr)このAuthor IDは既に登録されています。他のAuthor IDで登録してください。",
|
||||||
"authorIdIncorrectError": "(fr)Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
"authorIdIncorrectError": "(fr)Author IDの形式が不正です。Author IDは半角英数字(大文字)と\"_\"のみ入力可能です。",
|
||||||
"roleChangeError": "(fr)Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
"roleChangeError": "(fr)Roleの変更に失敗しました。画面を更新して再度ユーザー情報を取得してください。",
|
||||||
"encryptionPasswordCorrectError": "(fr)EncryptionPasswordがルールを満たしていません。"
|
"encryptionPasswordCorrectError": "(fr)EncryptionPasswordがルールを満たしていません。",
|
||||||
|
"alreadyLicenseDeallocatedError": "(fr)すでにライセンス割り当てが解除されています。画面を更新して再度ご確認下さい。"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"title": "(fr)User",
|
"title": "(fr)User",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user