// Copyright (C) 2021-2022 Intel Corporation // // SPDX-License-Identifier: MIT import { Store } from 'antd/lib/form/interface'; import { User } from 'components/task-page/user-selector'; import { getCore } from 'cvat-core-wrapper'; import { ActionUnion, createAction, ThunkAction } from 'utils/redux'; const core = getCore(); export enum OrganizationActionsTypes { GET_ORGANIZATIONS = 'GET_ORGANIZATIONS', GET_ORGANIZATIONS_SUCCESS = 'GET_ORGANIZATIONS_SUCCESS', GET_ORGANIZATIONS_FAILED = 'GET_ORGANIZATIONS_FAILED', ACTIVATE_ORGANIZATION_SUCCESS = 'ACTIVATE_ORGANIZATION_SUCCESS', ACTIVATE_ORGANIZATION_FAILED = 'ACTIVATE_ORGANIZATION_FAILED', CREATE_ORGANIZATION = 'CREATE_ORGANIZATION', CREATE_ORGANIZATION_SUCCESS = 'CREATE_ORGANIZATION_SUCCESS', CREATE_ORGANIZATION_FAILED = 'CREATE_ORGANIZATION_FAILED', UPDATE_ORGANIZATION = 'UPDATE_ORGANIZATION', UPDATE_ORGANIZATION_SUCCESS = 'UPDATE_ORGANIZATION_SUCCESS', UPDATE_ORGANIZATION_FAILED = 'UPDATE_ORGANIZATION_FAILED', REMOVE_ORGANIZATION = 'REMOVE_ORGANIZATION', REMOVE_ORGANIZATION_SUCCESS = 'REMOVE_ORGANIZATION_SUCCESS', REMOVE_ORGANIZATION_FAILED = 'REMOVE_ORGANIZATION_FAILED', INVITE_ORGANIZATION_MEMBERS = 'INVITE_ORGANIZATION_MEMBERS', INVITE_ORGANIZATION_MEMBERS_FAILED = 'INVITE_ORGANIZATION_MEMBERS_FAILED', INVITE_ORGANIZATION_MEMBERS_DONE = 'INVITE_ORGANIZATION_MEMBERS_DONE', INVITE_ORGANIZATION_MEMBER_SUCCESS = 'INVITE_ORGANIZATION_MEMBER_SUCCESS', INVITE_ORGANIZATION_MEMBER_FAILED = 'INVITE_ORGANIZATION_MEMBER_FAILED', LEAVE_ORGANIZATION = 'LEAVE_ORGANIZATION', LEAVE_ORGANIZATION_SUCCESS = 'LEAVE_ORGANIZATION_SUCCESS', LEAVE_ORGANIZATION_FAILED = 'LEAVE_ORGANIZATION_FAILED', REMOVE_ORGANIZATION_MEMBER = 'REMOVE_ORGANIZATION_MEMBERS', REMOVE_ORGANIZATION_MEMBER_SUCCESS = 'REMOVE_ORGANIZATION_MEMBER_SUCCESS', REMOVE_ORGANIZATION_MEMBER_FAILED = 'REMOVE_ORGANIZATION_MEMBER_FAILED', UPDATE_ORGANIZATION_MEMBER = 'UPDATE_ORGANIZATION_MEMBER', UPDATE_ORGANIZATION_MEMBER_SUCCESS = 'UPDATE_ORGANIZATION_MEMBER_SUCCESS', UPDATE_ORGANIZATION_MEMBER_FAILED = 'UPDATE_ORGANIZATION_MEMBER_FAILED', } const organizationActions = { getOrganizations: () => createAction(OrganizationActionsTypes.GET_ORGANIZATIONS), getOrganizationsSuccess: (list: any[]) => createAction( OrganizationActionsTypes.GET_ORGANIZATIONS_SUCCESS, { list }, ), getOrganizationsFailed: (error: any) => createAction(OrganizationActionsTypes.GET_ORGANIZATIONS_FAILED, { error }), createOrganization: () => createAction(OrganizationActionsTypes.CREATE_ORGANIZATION), createOrganizationSuccess: (organization: any) => createAction( OrganizationActionsTypes.CREATE_ORGANIZATION_SUCCESS, { organization }, ), createOrganizationFailed: (slug: string, error: any) => createAction( OrganizationActionsTypes.CREATE_ORGANIZATION_FAILED, { slug, error }, ), updateOrganization: () => createAction(OrganizationActionsTypes.UPDATE_ORGANIZATION), updateOrganizationSuccess: (organization: any) => createAction( OrganizationActionsTypes.UPDATE_ORGANIZATION_SUCCESS, { organization }, ), updateOrganizationFailed: (slug: string, error: any) => createAction( OrganizationActionsTypes.UPDATE_ORGANIZATION_FAILED, { slug, error }, ), activateOrganizationSuccess: (organization: any | null) => createAction( OrganizationActionsTypes.ACTIVATE_ORGANIZATION_SUCCESS, { organization }, ), activateOrganizationFailed: (error: any, slug: string | null) => createAction( OrganizationActionsTypes.ACTIVATE_ORGANIZATION_FAILED, { slug, error }, ), removeOrganization: () => createAction(OrganizationActionsTypes.REMOVE_ORGANIZATION), removeOrganizationSuccess: (slug: string) => createAction( OrganizationActionsTypes.REMOVE_ORGANIZATION_SUCCESS, { slug }, ), removeOrganizationFailed: (error: any, slug: string) => createAction( OrganizationActionsTypes.REMOVE_ORGANIZATION_FAILED, { error, slug }, ), inviteOrganizationMembers: () => createAction(OrganizationActionsTypes.INVITE_ORGANIZATION_MEMBERS), inviteOrganizationMembersFailed: (error: any) => createAction( OrganizationActionsTypes.INVITE_ORGANIZATION_MEMBERS_FAILED, { error }, ), inviteOrganizationMembersDone: () => createAction(OrganizationActionsTypes.INVITE_ORGANIZATION_MEMBERS_DONE), inviteOrganizationMemberSuccess: (email: string) => createAction( OrganizationActionsTypes.INVITE_ORGANIZATION_MEMBER_SUCCESS, { email }, ), inviteOrganizationMemberFailed: (email: string, error: any) => createAction( OrganizationActionsTypes.INVITE_ORGANIZATION_MEMBER_FAILED, { email, error }, ), leaveOrganization: () => createAction(OrganizationActionsTypes.LEAVE_ORGANIZATION), leaveOrganizationSuccess: () => createAction(OrganizationActionsTypes.LEAVE_ORGANIZATION_SUCCESS), leaveOrganizationFailed: (error: any) => createAction( OrganizationActionsTypes.LEAVE_ORGANIZATION_FAILED, { error }, ), removeOrganizationMember: () => createAction(OrganizationActionsTypes.REMOVE_ORGANIZATION_MEMBER), removeOrganizationMemberSuccess: () => createAction(OrganizationActionsTypes.REMOVE_ORGANIZATION_MEMBER_SUCCESS), removeOrganizationMemberFailed: (username: string, error: any) => createAction( OrganizationActionsTypes.REMOVE_ORGANIZATION_MEMBER_FAILED, { username, error }, ), updateOrganizationMember: () => createAction(OrganizationActionsTypes.UPDATE_ORGANIZATION_MEMBER), updateOrganizationMemberSuccess: () => createAction(OrganizationActionsTypes.UPDATE_ORGANIZATION_MEMBER_SUCCESS), updateOrganizationMemberFailed: (username: string, role: string, error: any) => createAction( OrganizationActionsTypes.UPDATE_ORGANIZATION_MEMBER_FAILED, { username, role, error }, ), }; export function getOrganizationsAsync(): ThunkAction { return async function (dispatch) { dispatch(organizationActions.getOrganizations()); try { const organizations = await core.organizations.get(); let currentOrganization = null; try { // this action is dispatched after user is authentificated // need to configure organization at cvat-core immediately to get relevant data const curSlug = localStorage.getItem('currentOrganization'); if (curSlug) { currentOrganization = organizations.find((organization: any) => organization.slug === curSlug) || null; if (currentOrganization) { await core.organizations.activate(currentOrganization); } else { // not valid anymore (for example when organization // does not exist anymore, or the user has been kicked from it) localStorage.removeItem('currentOrganization'); } } dispatch(organizationActions.activateOrganizationSuccess(currentOrganization)); } catch (error) { dispatch( organizationActions.activateOrganizationFailed(error, localStorage.getItem('currentOrganization')), ); } finally { dispatch(organizationActions.getOrganizationsSuccess(organizations)); } } catch (error) { dispatch(organizationActions.getOrganizationsFailed(error)); } }; } export function createOrganizationAsync( organizationData: Store, onCreateSuccess?: (createdSlug: string) => void, ): ThunkAction { return async function (dispatch) { const { slug } = organizationData; const organization = new core.classes.Organization(organizationData); dispatch(organizationActions.createOrganization()); try { const createdOrganization = await organization.save(); dispatch(organizationActions.createOrganizationSuccess(createdOrganization)); if (onCreateSuccess) onCreateSuccess(createdOrganization.slug); } catch (error) { dispatch(organizationActions.createOrganizationFailed(slug, error)); } }; } export function updateOrganizationAsync(organization: any): ThunkAction { return async function (dispatch) { dispatch(organizationActions.updateOrganization()); try { const updatedOrganization = await organization.save(); dispatch(organizationActions.updateOrganizationSuccess(updatedOrganization)); } catch (error) { dispatch(organizationActions.updateOrganizationFailed(organization.slug, error)); } }; } export function removeOrganizationAsync(organization: any): ThunkAction { return async function (dispatch) { try { await organization.remove(); localStorage.removeItem('currentOrganization'); dispatch(organizationActions.removeOrganizationSuccess(organization.slug)); } catch (error) { dispatch(organizationActions.removeOrganizationFailed(error, organization.slug)); } }; } export function inviteOrganizationMembersAsync( organization: any, members: { email: string; role: string }[], onFinish: () => void, ): ThunkAction { return async function (dispatch) { dispatch(organizationActions.inviteOrganizationMembers()); try { for (let i = 0; i < members.length; i++) { const { email, role } = members[i]; organization .invite(email, role) .then(() => { dispatch(organizationActions.inviteOrganizationMemberSuccess(email)); }) .catch((error: any) => { dispatch(organizationActions.inviteOrganizationMemberFailed(email, error)); }) .finally(() => { if (i === members.length - 1) { dispatch(organizationActions.inviteOrganizationMembersDone()); onFinish(); } }); } } catch (error) { dispatch(organizationActions.inviteOrganizationMembersFailed(error)); } }; } export function leaveOrganizationAsync(organization: any): ThunkAction { return async function (dispatch, getState) { const { user } = getState().auth; dispatch(organizationActions.leaveOrganization()); try { await organization.leave(user); dispatch(organizationActions.leaveOrganizationSuccess()); localStorage.removeItem('currentOrganization'); } catch (error) { dispatch(organizationActions.leaveOrganizationFailed(error)); } }; } export function removeOrganizationMemberAsync( organization: any, { user, id }: { user: User; id: number }, onFinish: () => void, ): ThunkAction { return async function (dispatch) { dispatch(organizationActions.removeOrganizationMember()); try { await organization.deleteMembership(id); dispatch(organizationActions.removeOrganizationMemberSuccess()); onFinish(); } catch (error) { dispatch(organizationActions.removeOrganizationMemberFailed(user.username, error)); } }; } export function updateOrganizationMemberAsync( organization: any, { user, id }: { user: User; id: number }, role: string, onFinish: () => void, ): ThunkAction { return async function (dispatch) { dispatch(organizationActions.updateOrganizationMember()); try { await organization.updateMembership(id, role); dispatch(organizationActions.updateOrganizationMemberSuccess()); onFinish(); } catch (error) { dispatch(organizationActions.updateOrganizationMemberFailed(user.username, role, error)); } }; } export type OrganizationActions = ActionUnion;