Fix Apps UI: replace 'Managed' label with actual app name and unify app icons (#19897)
## 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.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { CurrentApplicationContext } from '@/applications/contexts/CurrentApplicationContext';
|
||||
import {
|
||||
useApplicationAvatarColors,
|
||||
type ApplicationAvatarColors,
|
||||
} from '@/applications/hooks/useApplicationAvatarColors';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type UseApplicationChipDataArgs = {
|
||||
applicationId: string;
|
||||
};
|
||||
|
||||
type ApplicationChipData = {
|
||||
name: string;
|
||||
seed: string;
|
||||
colors?: ApplicationAvatarColors;
|
||||
};
|
||||
|
||||
type UseApplicationChipDataReturnType = {
|
||||
applicationChipData: ApplicationChipData;
|
||||
};
|
||||
|
||||
export const useApplicationChipData = ({
|
||||
applicationId,
|
||||
}: UseApplicationChipDataArgs): UseApplicationChipDataReturnType => {
|
||||
const currentApplicationId = useContext(CurrentApplicationContext);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
|
||||
const application = currentWorkspace?.installedApplications.find(
|
||||
(installedApplication) => installedApplication.id === applicationId,
|
||||
);
|
||||
|
||||
const colors = useApplicationAvatarColors(application);
|
||||
|
||||
if (!isDefined(application)) {
|
||||
return {
|
||||
applicationChipData: {
|
||||
name: '',
|
||||
seed: applicationId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const isCurrent =
|
||||
isDefined(currentApplicationId) && currentApplicationId === applicationId;
|
||||
|
||||
return {
|
||||
applicationChipData: {
|
||||
name: isCurrent ? t`This app` : application.name,
|
||||
seed: application.universalIdentifier ?? application.name,
|
||||
colors,
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user