mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-15 17:16:16 +08:00
feat(core): add an entry for admin panel (#10813)

This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
} from '@affine/core/modules/dialogs';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { AccountIcon, SignOutIcon } from '@blocksuite/icons/rc';
|
||||
import { AccountIcon, AdminIcon, SignOutIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
ServerService,
|
||||
SubscriptionService,
|
||||
UserCopilotQuotaService,
|
||||
UserFeatureService,
|
||||
UserQuotaService,
|
||||
} from '../../modules/cloud';
|
||||
import { UserPlanButton } from '../affine/auth/user-plan-button';
|
||||
@@ -80,6 +81,9 @@ const UnauthorizedUserInfo = () => {
|
||||
const AccountMenu = () => {
|
||||
const workspaceDialogService = useService(WorkspaceDialogService);
|
||||
const openSignOutModal = useSignOut();
|
||||
const serverService = useService(ServerService);
|
||||
const userFeatureService = useService(UserFeatureService);
|
||||
const isAdmin = useLiveData(userFeatureService.userFeature.isAdmin$);
|
||||
|
||||
const onOpenAccountSetting = useCallback(() => {
|
||||
track.$.navigationPanel.profileAndBadge.openSettings({ to: 'account' });
|
||||
@@ -88,8 +92,16 @@ const AccountMenu = () => {
|
||||
});
|
||||
}, [workspaceDialogService]);
|
||||
|
||||
const onOpenAdminPanel = useCallback(() => {
|
||||
window.open(`${serverService.server.baseUrl}/admin`, '_blank');
|
||||
}, [serverService.server.baseUrl]);
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
useEffect(() => {
|
||||
userFeatureService.userFeature.revalidate();
|
||||
}, [userFeatureService]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MenuItem
|
||||
@@ -99,6 +111,15 @@ const AccountMenu = () => {
|
||||
>
|
||||
{t['com.affine.workspace.cloud.account.settings']()}
|
||||
</MenuItem>
|
||||
{isAdmin ? (
|
||||
<MenuItem
|
||||
prefixIcon={<AdminIcon />}
|
||||
data-testid="workspace-modal-account-admin-option"
|
||||
onClick={onOpenAdminPanel}
|
||||
>
|
||||
{t['com.affine.workspace.cloud.account.admin']()}
|
||||
</MenuItem>
|
||||
) : null}
|
||||
<MenuItem
|
||||
prefixIcon={<SignOutIcon />}
|
||||
data-testid="workspace-modal-sign-out-option"
|
||||
|
||||
@@ -18,6 +18,11 @@ import type { UserFeatureStore } from '../stores/user-feature';
|
||||
export class UserFeature extends Entity {
|
||||
// undefined means no user, null means loading
|
||||
features$ = new LiveData<FeatureType[] | null | undefined>(null);
|
||||
|
||||
isAdmin$ = this.features$.map(features =>
|
||||
features === null ? null : features?.some(f => f === FeatureType.Admin)
|
||||
);
|
||||
|
||||
isEarlyAccess$ = this.features$.map(features =>
|
||||
features === null
|
||||
? null
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"it-IT": 99,
|
||||
"it": 1,
|
||||
"ja": 99,
|
||||
"ko": 63,
|
||||
"ko": 62,
|
||||
"pl": 99,
|
||||
"pt-BR": 99,
|
||||
"ru": 99,
|
||||
|
||||
@@ -5404,8 +5404,8 @@ export function useAFFiNEI18N(): {
|
||||
*/
|
||||
["com.affine.settings.workspace.experimental-features.enable-callout.description"](): string;
|
||||
/**
|
||||
* Embed Iframe Block
|
||||
*/
|
||||
* `Embed Iframe Block`
|
||||
*/
|
||||
["com.affine.settings.workspace.experimental-features.enable-embed-iframe-block.name"](): string;
|
||||
/**
|
||||
* `Enables Embed Iframe Block.`
|
||||
@@ -6465,6 +6465,10 @@ export function useAFFiNEI18N(): {
|
||||
* `Account settings`
|
||||
*/
|
||||
["com.affine.workspace.cloud.account.settings"](): string;
|
||||
/**
|
||||
* `Admin panel`
|
||||
*/
|
||||
["com.affine.workspace.cloud.account.admin"](): string;
|
||||
/**
|
||||
* `Sign up/ Sign in`
|
||||
*/
|
||||
@@ -6549,6 +6553,18 @@ export function useAFFiNEI18N(): {
|
||||
* `Yesterday`
|
||||
*/
|
||||
["com.affine.yesterday"](): string;
|
||||
/**
|
||||
* `Inactive`
|
||||
*/
|
||||
["com.affine.inactive"](): string;
|
||||
/**
|
||||
* `Inactive member`
|
||||
*/
|
||||
["com.affine.inactive-member"](): string;
|
||||
/**
|
||||
* `Inactive workspace`
|
||||
*/
|
||||
["com.affine.inactive-workspace"](): string;
|
||||
/**
|
||||
* `core`
|
||||
*/
|
||||
@@ -6992,12 +7008,9 @@ export function useAFFiNEI18N(): {
|
||||
*/
|
||||
["com.affine.notification.unsupported"](): string;
|
||||
/**
|
||||
* `{{username}} mentioned you in {{docTitle}}`
|
||||
* `No new notifications`
|
||||
*/
|
||||
["com.affine.notification.mention"](options: Readonly<{
|
||||
username: string;
|
||||
docTitle: string;
|
||||
}>): string;
|
||||
["com.affine.notification.empty"](): string;
|
||||
/**
|
||||
* `Tips`
|
||||
*/
|
||||
@@ -7006,6 +7019,10 @@ export function useAFFiNEI18N(): {
|
||||
* `Template`
|
||||
*/
|
||||
Template(): string;
|
||||
/**
|
||||
* `Delete Template`
|
||||
*/
|
||||
["com.affine.template-list.delete"](): string;
|
||||
/**
|
||||
* `No template`
|
||||
*/
|
||||
@@ -7119,6 +7136,12 @@ export function useAFFiNEI18N(): {
|
||||
["error.QUERY_TOO_LONG"](options: {
|
||||
readonly max: string;
|
||||
}): string;
|
||||
/**
|
||||
* `Validation error, errors: {{errors}}`
|
||||
*/
|
||||
["error.VALIDATION_ERROR"](options: {
|
||||
readonly errors: string;
|
||||
}): string;
|
||||
/**
|
||||
* `User not found.`
|
||||
*/
|
||||
@@ -7162,6 +7185,10 @@ export function useAFFiNEI18N(): {
|
||||
status: string;
|
||||
body: string;
|
||||
}>): string;
|
||||
/**
|
||||
* `Invalid auth state. You might start the auth progress from another device.`
|
||||
*/
|
||||
["error.INVALID_AUTH_STATE"](): string;
|
||||
/**
|
||||
* `Missing query parameter `{{name}}`.`
|
||||
*/
|
||||
@@ -7622,21 +7649,15 @@ export function useAFFiNEI18N(): {
|
||||
*/
|
||||
["error.NOTIFICATION_NOT_FOUND"](): string;
|
||||
/**
|
||||
* `Mention user do not have permission to access space {{spaceId}}.`
|
||||
* `Mentioned user can not access doc {{docId}}.`
|
||||
*/
|
||||
["error.MENTION_USER_SPACE_ACCESS_DENIED"](options: {
|
||||
readonly spaceId: string;
|
||||
["error.MENTION_USER_DOC_ACCESS_DENIED"](options: {
|
||||
readonly docId: string;
|
||||
}): string;
|
||||
/**
|
||||
* `You cannot mention yourself.`
|
||||
* `You can not mention yourself.`
|
||||
*/
|
||||
["error.MENTION_USER_ONESELF_DENIED"](): string;
|
||||
/**
|
||||
* `You do not have permission to access notification {{notificationId}}.`
|
||||
*/
|
||||
["error.NOTIFICATION_ACCESS_DENIED"](options: {
|
||||
readonly notificationId: string;
|
||||
}): string;
|
||||
} { const { t } = useTranslation(); return useMemo(() => createProxy((key) => t.bind(null, key)), [t]); }
|
||||
function createComponent(i18nKey: string) {
|
||||
return (props) => createElement(Trans, { i18nKey, shouldUnescape: true, ...props });
|
||||
@@ -8061,6 +8082,16 @@ export const TypedTrans: {
|
||||
}, {
|
||||
["1"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `<1>{{username}}</1> mentioned you in <2>{{docTitle}}</2>`
|
||||
*/
|
||||
["com.affine.notification.mention"]: ComponentType<TypedTransProps<Readonly<{
|
||||
username: string;
|
||||
docTitle: string;
|
||||
}>, {
|
||||
["1"]: JSX.Element;
|
||||
["2"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `Unable to join <1/> <2>{{workspaceName}}</2> due to insufficient seats available.`
|
||||
*/
|
||||
|
||||
@@ -1610,6 +1610,7 @@
|
||||
"com.affine.workspace.cloud": "Cloud workspaces",
|
||||
"com.affine.workspace.cloud.account.logout": "Sign out",
|
||||
"com.affine.workspace.cloud.account.settings": "Account settings",
|
||||
"com.affine.workspace.cloud.account.admin": "Admin panel",
|
||||
"com.affine.workspace.cloud.auth": "Sign up/ Sign in",
|
||||
"com.affine.workspace.cloud.description": "Sync with AFFiNE Cloud",
|
||||
"com.affine.workspace.cloud.join": "Join workspace",
|
||||
@@ -1774,6 +1775,7 @@
|
||||
"error.BAD_REQUEST": "Bad request.",
|
||||
"error.GRAPHQL_BAD_REQUEST": "GraphQL bad request, code: {{code}}, {{message}}",
|
||||
"error.QUERY_TOO_LONG": "Query is too long, max length is {{max}}.",
|
||||
"error.VALIDATION_ERROR": "Validation error, errors: {{errors}}",
|
||||
"error.USER_NOT_FOUND": "User not found.",
|
||||
"error.USER_AVATAR_NOT_FOUND": "User avatar not found.",
|
||||
"error.EMAIL_ALREADY_USED": "This email has already been registered.",
|
||||
@@ -1783,6 +1785,7 @@
|
||||
"error.OAUTH_STATE_EXPIRED": "OAuth state expired, please try again.",
|
||||
"error.INVALID_OAUTH_CALLBACK_STATE": "Invalid callback state parameter.",
|
||||
"error.INVALID_OAUTH_CALLBACK_CODE": "Invalid callback code parameter, provider response status: {{status}} and body: {{body}}.",
|
||||
"error.INVALID_AUTH_STATE": "Invalid auth state. You might start the auth progress from another device.",
|
||||
"error.MISSING_OAUTH_QUERY_PARAMETER": "Missing query parameter `{{name}}`.",
|
||||
"error.OAUTH_ACCOUNT_ALREADY_CONNECTED": "The third-party account has already been connected to another user.",
|
||||
"error.INVALID_EMAIL": "An invalid email provided: {{email}}",
|
||||
@@ -1875,7 +1878,6 @@
|
||||
"error.WORKSPACE_MEMBERS_EXCEED_LIMIT_TO_DOWNGRADE": "You cannot downgrade the workspace from team workspace because there are more than {{limit}} members that are currently active.",
|
||||
"error.UNSUPPORTED_CLIENT_VERSION": "Unsupported client with version [{{clientVersion}}], required version is [{{requiredVersion}}].",
|
||||
"error.NOTIFICATION_NOT_FOUND": "Notification not found.",
|
||||
"error.MENTION_USER_SPACE_ACCESS_DENIED": "Mention user do not have permission to access space {{spaceId}}.",
|
||||
"error.MENTION_USER_ONESELF_DENIED": "You cannot mention yourself.",
|
||||
"error.NOTIFICATION_ACCESS_DENIED": "You do not have permission to access notification {{notificationId}}."
|
||||
"error.MENTION_USER_DOC_ACCESS_DENIED": "Mentioned user can not access doc {{docId}}.",
|
||||
"error.MENTION_USER_ONESELF_DENIED": "You can not mention yourself."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user