96fc98e710
## Summary
- The Data Model table was labeling core Twenty objects (e.g. Person,
Company) as **Managed** even though they are part of the standard
application. This PR teaches the frontend to resolve an `applicationId`
back to its real application name (`Standard`, `Custom`, or any
installed app), and removes the misleading **Managed** label entirely.
- Introduces a single, consistent way to render an "app badge" across
the settings UI:
- new `Avatar` variant `type="app"` (rounded 4px corners + 1px
deterministic border derived from `placeholderColorSeed`)
- new `AppChip` component (icon + name) backed by a new
`useApplicationChipData` hook
- new `useApplicationsByIdMap` hook + `CurrentApplicationContext` so the
chip can render **This app** when shown inside the matching app's detail
page
- Reuses these primitives on:
- the application detail page header (`SettingsApplicationDetailTitle`)
- the Installed / My apps tables (`SettingsApplicationTableRow`)
- the NPM packages list (`SettingsApplicationsDeveloperTab`)
- Backend: exposes a minimal `installedApplications { id name
universalIdentifier }` field on `Workspace` (resolved from the workspace
cache, soft-deleted entries filtered out) so the frontend can resolve
`applicationId` -> name without N+1 fetches.
- Cleanup: deletes `getItemTagInfo` and inlines its tiny
responsibilities into the components that need them, matching the
`RecordChip` pattern.
58 lines
1.5 KiB
TypeScript
58 lines
1.5 KiB
TypeScript
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
|
import {
|
|
type Application,
|
|
type Role,
|
|
type Workspace,
|
|
} from '~/generated-metadata/graphql';
|
|
|
|
export type CurrentWorkspace = Pick<
|
|
Workspace,
|
|
| 'id'
|
|
| 'inviteHash'
|
|
| 'logo'
|
|
| 'displayName'
|
|
| 'allowImpersonation'
|
|
| 'featureFlags'
|
|
| 'activationStatus'
|
|
| 'billingSubscriptions'
|
|
| 'billingEntitlements'
|
|
| 'currentBillingSubscription'
|
|
| 'workspaceMembersCount'
|
|
| 'isPublicInviteLinkEnabled'
|
|
| 'isGoogleAuthEnabled'
|
|
| 'isGoogleAuthBypassEnabled'
|
|
| 'isMicrosoftAuthEnabled'
|
|
| 'isMicrosoftAuthBypassEnabled'
|
|
| 'isPasswordAuthEnabled'
|
|
| 'isPasswordAuthBypassEnabled'
|
|
| 'isCustomDomainEnabled'
|
|
| 'hasValidEnterpriseKey'
|
|
| 'hasValidSignedEnterpriseKey'
|
|
| 'hasValidEnterpriseValidityToken'
|
|
| 'subdomain'
|
|
| 'customDomain'
|
|
| 'workspaceUrls'
|
|
| 'metadataVersion'
|
|
| 'isTwoFactorAuthenticationEnforced'
|
|
| 'trashRetentionDays'
|
|
| 'eventLogRetentionDays'
|
|
| 'fastModel'
|
|
| 'smartModel'
|
|
| 'aiAdditionalInstructions'
|
|
| 'editableProfileFields'
|
|
| 'enabledAiModelIds'
|
|
| 'useRecommendedModels'
|
|
> & {
|
|
defaultRole?: Omit<Role, 'workspaceMembers' | 'agents' | 'apiKeys'> | null;
|
|
workspaceCustomApplication: Pick<Application, 'id'> | null;
|
|
installedApplications: Pick<
|
|
Application,
|
|
'id' | 'name' | 'universalIdentifier'
|
|
>[];
|
|
};
|
|
|
|
export const currentWorkspaceState = createAtomState<CurrentWorkspace | null>({
|
|
key: 'currentWorkspaceState',
|
|
defaultValue: null,
|
|
});
|