Skip to content

Commit

Permalink
feat: add enterprise related definitions (#1167)
Browse files Browse the repository at this point in the history
* feat: add enterprise related definitions

* fix: imported multiple times

* fix: delete base collaborators
  • Loading branch information
boris-w authored Dec 16, 2024
1 parent 8c88dfe commit b2020fe
Show file tree
Hide file tree
Showing 27 changed files with 202 additions and 21 deletions.
2 changes: 2 additions & 0 deletions apps/nestjs-backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { InvitationModule } from './features/invitation/invitation.module';
import { NextModule } from './features/next/next.module';
import { NotificationModule } from './features/notification/notification.module';
import { OAuthModule } from './features/oauth/oauth.module';
import { OrganizationModule } from './features/organization/organization.module';
import { PinModule } from './features/pin/pin.module';
import { PluginModule } from './features/plugin/plugin.module';
import { SelectionModule } from './features/selection/selection.module';
Expand Down Expand Up @@ -66,6 +67,7 @@ export const appModules = {
PluginModule,
DashboardModule,
CommentOpenApiModule,
OrganizationModule,
],
providers: [InitBootstrapProvider],
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,17 @@ export class CollaboratorService {
},
},
});
if (resourceType === CollaboratorType.Space) {
this.eventEmitterService.emitAsync(
Events.COLLABORATOR_DELETE,
new CollaboratorDeleteEvent(resourceId)
);
let spaceId: string = resourceId;
if (resourceType === CollaboratorType.Base) {
const space = await this.prismaService
.txClient()
.base.findUniqueOrThrow({ where: { id: resourceId }, select: { spaceId: true } });
spaceId = space.spaceId;
}
this.eventEmitterService.emitAsync(
Events.COLLABORATOR_DELETE,
new CollaboratorDeleteEvent(spaceId)
);
return result;
}

Expand Down Expand Up @@ -389,7 +394,7 @@ export class CollaboratorService {
throw new BadRequestException('has already existed in base');
}

return this.prismaService.txClient().collaborator.create({
const res = await this.prismaService.txClient().collaborator.create({
data: {
resourceId: baseId,
resourceType: CollaboratorType.Base,
Expand All @@ -398,6 +403,11 @@ export class CollaboratorService {
createdBy: currentUserId!,
},
});
this.eventEmitterService.emitAsync(
Events.COLLABORATOR_CREATE,
new CollaboratorCreateEvent(base.spaceId)
);
return res;
}

async getSharedBase() {
Expand Down
1 change: 1 addition & 0 deletions apps/nestjs-backend/src/features/next/next.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class NextController {
'oauth/?*',
'developer/?*',
'public/?*',
'enterprise/?*',
])
public async home(@Req() req: express.Request, @Res() res: express.Response) {
await this.nextService.server.getRequestHandler()(req, res);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Controller, Get } from '@nestjs/common';
import type { IOrganizationMeVo } from '@teable/openapi';

@Controller('api/organization')
export class OrganizationController {
@Get('me')
async getOrganizationMe(): Promise<IOrganizationMeVo> {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Module } from '@nestjs/common';
import { OrganizationController } from './organization.controller';

@Module({
controllers: [OrganizationController],
})
export class OrganizationModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,9 @@ export class RecordOpenApiService {
}

private async getValidateAttachmentRecord(tableId: string, recordId: string, fieldId: string) {
const field = await this.prismaService.field
.findFirstOrThrow({
const field = await this.prismaService
.txClient()
.field.findFirstOrThrow({
where: {
id: fieldId,
deletedTime: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Spin } from '@teable/ui-lib/base';
import { Button, Input, Label, Separator } from '@teable/ui-lib/shadcn';
import { useTranslation } from 'next-i18next';
import { useMemo, useState } from 'react';
import { useOrganization } from '@/features/app/hooks/useOrganization';
import { personalAccessTokenConfig } from '@/features/i18n/personal-access-token.config';
import { RequireCom } from '../../components/RequireCom';
import { ScopesSelect } from '../../components/ScopesSelect';
Expand Down Expand Up @@ -46,6 +47,7 @@ export const AccessTokenForm = <T extends IFormType>(props: IAccessTokenForm<T>)
const { t } = useTranslation(personalAccessTokenConfig.i18nNamespaces);

const { user } = useSession();
const { organization } = useOrganization();

const [spaceIds, setSpaceIds] = useState<string[] | undefined | null>(defaultData?.spaceIds);
const [baseIds, setBaseIds] = useState<string[] | undefined | null>(defaultData?.baseIds);
Expand All @@ -70,8 +72,11 @@ export const AccessTokenForm = <T extends IFormType>(props: IAccessTokenForm<T>)
if (user.isAdmin) {
prefixes.push(ActionPrefix.Instance);
}
if (organization?.isAdmin) {
prefixes.push(ActionPrefix.Enterprise);
}
return prefixes;
}, [user.isAdmin]);
}, [user.isAdmin, organization?.isAdmin]);

const disableSubmit = useMemo(() => {
if (type === 'new') {
Expand Down
4 changes: 4 additions & 0 deletions apps/nextjs-app/src/features/app/blocks/space/SpaceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ export const SpaceCard: FC<ISpaceCard> = (props) => {
status={subscription?.status}
spaceId={space.id}
withUpgrade={space.role === Role.Owner}
organization={space?.organization}
/>
)}
{!isCloud && space?.organization && (
<div className="text-sm text-gray-500">{space.organization.name}</div>
)}
</div>
<SpaceActionBar
className="flex shrink-0 items-center gap-3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,12 @@ export const SpaceInnerPage: React.FC = () => {
status={subscriptionSummary?.status}
spaceId={space.id}
withUpgrade={space.role === Role.Owner}
organization={space.organization}
/>
)}
{!isCloud && space.organization && (
<div className="text-sm text-gray-500">{space.organization.name}</div>
)}
</div>

{basesInSpace?.length ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Button } from '@teable/ui-lib/shadcn/ui/button';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { useOrganization } from '@/features/app/hooks/useOrganization';
import { spaceConfig } from '@/features/i18n/space.config';
import { PinList } from './PinList';
import { SpaceList } from './SpaceList';
Expand All @@ -12,6 +13,7 @@ export const SpaceSideBar = (props: { isAdmin?: boolean | null }) => {
const { isAdmin } = props;
const router = useRouter();
const { t } = useTranslation(spaceConfig.i18nNamespaces);
const { organization } = useOrganization();

const pageRoutes: {
href: string;
Expand All @@ -35,6 +37,12 @@ export const SpaceSideBar = (props: { isAdmin?: boolean | null }) => {
Icon: Admin,
hidden: !isAdmin,
},
{
href: `/enterprise/${organization?.id}`,
text: t('noun.organizationPanel'),
Icon: Admin,
hidden: !organization?.isAdmin,
},
{
href: '/space/trash',
text: t('noun.trash'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { SubscriptionStatus } from '@teable/openapi';
import { BillingProductLevel } from '@teable/openapi';
import { SubscriptionStatus, BillingProductLevel } from '@teable/openapi';
import {
Button,
Tooltip,
Expand All @@ -18,10 +17,14 @@ interface ILevelWithUpgradeProps {
level?: BillingProductLevel;
status?: SubscriptionStatus;
withUpgrade?: boolean;
organization?: {
id: string;
name: string;
};
}

export const LevelWithUpgrade = (props: ILevelWithUpgradeProps) => {
const { level, spaceId, withUpgrade, status } = props;
const { level, spaceId, withUpgrade, status, organization } = props;
const isEnterprise = level === BillingProductLevel.Enterprise;
const { t } = useTranslation('common');
const { description } = useBillingLevelConfig(level);
Expand All @@ -48,6 +51,9 @@ export const LevelWithUpgrade = (props: ILevelWithUpgradeProps) => {
</TooltipContent>
</Tooltip>
</TooltipProvider>
{status === SubscriptionStatus.Active && organization?.name && (
<span className="text-xs text-muted-foreground">{organization.name}</span>
)}
<Status status={status} />
{withUpgrade && !isEnterprise && (
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ export interface ISidebarContentRoute {
}

interface ISidebarContentProps {
className?: string;
title?: string;
routes: ISidebarContentRoute[];
}

export const SidebarContent = (props: ISidebarContentProps) => {
const { title, routes } = props;
const { title, routes, className } = props;
const router = useRouter();

return (
<div className="flex flex-col gap-2 border-t px-4 py-2">
<div className={cn('flex flex-col gap-2 border-t px-4 py-2', className)}>
{title && <span className="text-sm text-slate-500">{title}</span>}
<ul>
{routes.map(({ Icon, label, route, pathTo, disabledTip }) => {
Expand Down
19 changes: 19 additions & 0 deletions apps/nextjs-app/src/features/app/hooks/useOrganization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { getOrganizationMe } from '@teable/openapi';

const OrganizationQueryKey = 'organization-me';

export const useOrganization = () => {
const queryClient = useQueryClient();
const { data: organization } = useQuery({
queryKey: [OrganizationQueryKey],
queryFn: () => getOrganizationMe().then((res) => res.data),
});

return {
organization,
refetch: () => {
queryClient.invalidateQueries({ queryKey: [OrganizationQueryKey] });
},
};
};
4 changes: 3 additions & 1 deletion packages/common-i18n/src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"brand": "Teable",
"actions": {
"title": "Actions",
"add": "Add",
"save": "Save",
"doNotSave": "Don't Save",
"submit": "Submit",
Expand Down Expand Up @@ -134,7 +135,8 @@
"instanceId": "Instance ID",
"beta": "Beta",
"trash": "Trash",
"global": "Global"
"global": "Global",
"organizationPanel": "Organization Panel"
},
"level": {
"free": "Free",
Expand Down
7 changes: 5 additions & 2 deletions packages/common-i18n/src/locales/en/sdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@
"recordHistoryRead": "Read record history",
"baseQuery": "Query base",
"instanceRead": "Read instance",
"instanceUpdate": "Update instance"
"instanceUpdate": "Update instance",
"enterpriseRead": "Read enterprise configuration",
"enterpriseUpdate": "Update enterprise configuration"
}
},
"noun": {
Expand All @@ -308,7 +310,8 @@
"user": "User",
"recordHistory": "Record History",
"you": "You",
"instance": "Instance"
"instance": "Instance",
"enterprise": "Enterprise"
},
"formula": {
"SUM": {
Expand Down
4 changes: 3 additions & 1 deletion packages/common-i18n/src/locales/zh/common.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"brand": "Teable",
"actions": {
"add": "添加",
"title": "操作",
"save": "保存",
"doNotSave": "不保存",
Expand Down Expand Up @@ -134,7 +135,8 @@
"instanceId": "实例 ID",
"beta": "测试版",
"trash": "回收站",
"global": "全局"
"global": "全局",
"organizationPanel": "组织管理面板"
},
"level": {
"free": "免费版",
Expand Down
7 changes: 5 additions & 2 deletions packages/common-i18n/src/locales/zh/sdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"user": "用户",
"recordHistory": "记录历史",
"you": "",
"instance": "实例"
"instance": "实例",
"enterprise": "企业"
},
"preview": {
"previewFileLimit": "预览暂不支持{{size}}MB以上的附件, 请下载后预览",
Expand Down Expand Up @@ -307,7 +308,9 @@
"recordHistoryRead": "查看记录历史",
"baseQuery": "查询数据库",
"instanceRead": "查看实例",
"instanceUpdate": "更新实例"
"instanceUpdate": "更新实例",
"enterpriseRead": "查看企业配置",
"enterpriseUpdate": "更新企业配置"
}
},
"formula": {
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/auth/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export enum ActionPrefix {
User = 'user',
TableRecordHistory = 'table_record_history',
Instance = 'instance',
Enterprise = 'enterprise',
}

export const spaceActions = [
Expand Down Expand Up @@ -101,6 +102,10 @@ export const instanceActions = ['instance|read', 'instance|update'] as const;
export const instanceActionSchema = z.enum(instanceActions);
export type InstanceAction = z.infer<typeof instanceActionSchema>;

export const enterpriseActions = ['enterprise|read', 'enterprise|update'] as const;
export const enterpriseActionSchema = z.enum(enterpriseActions);
export type EnterpriseAction = z.infer<typeof enterpriseActionSchema>;

export type Action =
| SpaceAction
| BaseAction
Expand All @@ -111,7 +116,8 @@ export type Action =
| AutomationAction
| UserAction
| TableRecordHistoryAction
| InstanceAction;
| InstanceAction
| EnterpriseAction;

export type ActionPrefixMap = {
[ActionPrefix.Space]: SpaceAction[];
Expand All @@ -124,6 +130,7 @@ export type ActionPrefixMap = {
[ActionPrefix.User]: UserAction[];
[ActionPrefix.TableRecordHistory]: TableRecordHistoryAction[];
[ActionPrefix.Instance]: InstanceAction[];
[ActionPrefix.Enterprise]: EnterpriseAction[];
};
export const actionPrefixMap: ActionPrefixMap = {
[ActionPrefix.Space]: [...spaceActions],
Expand All @@ -136,4 +143,5 @@ export const actionPrefixMap: ActionPrefixMap = {
[ActionPrefix.TableRecordHistory]: [...tableRecordHistoryActions],
[ActionPrefix.User]: [...userActions],
[ActionPrefix.Instance]: [...instanceActions],
[ActionPrefix.Enterprise]: [...enterpriseActions],
};
Loading

0 comments on commit b2020fe

Please sign in to comment.