Files
jkunz 833cf3b4b8 feat: Update organization member management and bulk invite functionality
- Marked the status of "Invite and Manage Team Members" story as Complete in README.
- Updated the status of ORG-002 to Complete in the corresponding markdown file.
- Modified OrganizationManager to assign roles as 'owner' during organization creation.
- Implemented bulk invitation feature in UserInvitationManager, allowing multiple users to be invited via CSV upload.
- Added IReq_BulkCreateInvitations interface for bulk invitation requests.
- Enhanced CreateOrgForm to update state with new roles upon organization creation.
- Introduced BulkInviteModal for bulk inviting users, including email validation and role assignment.
- Updated UsersView to support ownership transfer and bulk invitation functionality.
- Improved account state management to handle new roles and organizations.
2025-12-05 09:34:19 +00:00

110 lines
3.8 KiB
TypeScript

import * as plugins from '../plugins.js';
import { IdpState } from './idp.state.js';
export type TStateTypes = 'IAccountState';
export interface IAccountState {
user: plugins.idpInterfaces.data.IUser;
/**
* the available orgs
*/
organizations: Array<plugins.idpInterfaces.data.IOrganization>;
roles: Array<plugins.idpInterfaces.data.IRole>
selectedOrg: plugins.idpInterfaces.data.IOrganization;
selectedOrgBillingPlan: plugins.tsclass.typeFest.PartialDeep<plugins.idpInterfaces.data.IBillingPlan>;
/**
* used for keeping the state when creating a new org
*/
newOrg: {
chosenName: string;
chosenSlug: string;
validated: boolean;
validationOk: boolean;
};
}
const smartStateInstance = new plugins.deesDomtools.plugins.smartstate.Smartstate<TStateTypes>();
export const accountState = await smartStateInstance.getStatePart<IAccountState>('IAccountState', {
user: null,
organizations: [],
roles: [],
selectedOrg: null,
selectedOrgBillingPlan: null,
newOrg: {
chosenName: null,
chosenSlug: null,
validated: null,
validationOk: null,
},
});
export const getOrganizationsAction = accountState.createAction<void>(
async (statePartArg, payloadArg) => {
const idpState = await IdpState.getSingletonInstance();
const currentState = statePartArg.getState();
const response = await idpState.idpClient.getRolesAndOrganizations();
currentState.organizations = response.organizations;
currentState.roles = response.roles;
// Also fetch user data for admin checks
const whoIsResponse = await idpState.idpClient.whoIs().catch(() => null);
if (whoIsResponse?.user) {
currentState.user = whoIsResponse.user;
}
return currentState;
}
);
export const setNewOrgName = accountState.createAction<string>(async (statePartArg, payloadArg) => {
const idpState = await IdpState.getSingletonInstance();
const currentState = statePartArg.getState();
currentState.newOrg.chosenName = payloadArg;
currentState.newOrg.chosenSlug = payloadArg
.replace(/[^a-zA-Z0-9]/g, '-')
.replace(/\s/g, '-')
.toLowerCase();
const result = await idpState.idpClient.createOrganization(
currentState.newOrg.chosenName,
currentState.newOrg.chosenSlug,
'checkAvailability'
);
console.log(result);
currentState.newOrg.validated = true;
currentState.newOrg.validationOk = result.nameAvailable;
if (payloadArg === '') {
currentState.newOrg.validated = false;
currentState.newOrg.validationOk = false;
}
return currentState;
});
export const manifestNewOrgName = accountState.createAction(async (statePartArg, payloadArg) => {
const idpState = await IdpState.getSingletonInstance();
const currentState: IAccountState = statePartArg.getState();
const result = await idpState.idpClient.createOrganization(
currentState.newOrg.chosenName,
currentState.newOrg.chosenSlug,
'manifest'
);
currentState.organizations.push(result.resultingOrganization);
if (result.role) {
currentState.roles.push(result.role);
}
currentState.selectedOrg = result.resultingOrganization;
return currentState;
});
export const setSelectedOrg = accountState.createAction<plugins.idpInterfaces.data.IOrganization>(async (statePartArg, payloadArg) => {
const currentState = statePartArg.getState();
currentState.selectedOrg = payloadArg;
return currentState;
})
export const updatePaddleCheckoutId = accountState.createAction<string>(async (statePartArg, checkoutIdArg) => {
const idpState = await IdpState.getSingletonInstance();
const currentState: IAccountState = statePartArg.getState();
const response = await idpState.idpClient.updatePaddleCheckoutId(currentState.selectedOrg.id, checkoutIdArg);
currentState.selectedOrgBillingPlan = response.billingPlan;
return currentState;
});