1518 extensibility front add an application section in settings (#15056)

Protected by IS_APPLICATION_ENABLED featureFlag

Add `Application` section in settings

<img width="301" height="137" alt="image"
src="https://github.com/user-attachments/assets/ee53bdd2-36f6-45c6-8646-17b1e08abf00"
/>


A `settings/applications` route listing all installed applications

<img width="661" height="428" alt="image"
src="https://github.com/user-attachments/assets/69d534c4-4e9e-452a-a3d9-ded0223bb457"
/>

Introduce a new Tag for application managed items

<img width="885" height="759" alt="image"
src="https://github.com/user-attachments/assets/19767be5-61e5-4bd2-a51d-54ed9bfb1923"
/>



A `settings/applications/<application_id>` details setting page listing
all objects, serverlessFunctions and agents created by the application:

<img width="917" height="778" alt="image"
src="https://github.com/user-attachments/assets/7fc056a6-1d73-4242-b2eb-6f8955d8597d"
/>

A `settings/applications/<application_id>/<serverless_function_id>`

<img width="905" height="652" alt="image"
src="https://github.com/user-attachments/assets/56ca0021-26bf-42cb-9abf-34879f16050a"
/>

Add trigger tab in serverless function details (readonly for now)

<img width="899" height="724" alt="image"
src="https://github.com/user-attachments/assets/5eeefa35-f2a4-4fd8-a640-7b5c5891f226"
/>

Set object, serverless and agent setting detail pages readonly for
managed items
<img width="1075" height="859" alt="image"
src="https://github.com/user-attachments/assets/57c73d69-4980-47a2-b752-8dc5ab494530"
/>
<img width="648" height="582" alt="image"
src="https://github.com/user-attachments/assets/5ad5f3f7-3bc3-4e40-870a-4981c6492524"
/>
<img width="982" height="692" alt="image"
src="https://github.com/user-attachments/assets/7ad756c4-5d33-4a0a-9eb8-416c040362b9"
/>
<img width="1077" height="647" alt="image"
src="https://github.com/user-attachments/assets/e086b9f5-4062-4d10-82a9-4023de3cad3f"
/>
This commit is contained in:
martmull
2025-10-15 17:13:29 +02:00
committed by GitHub
parent c0ed246a03
commit b16ab1b7c9
109 changed files with 2464 additions and 1357 deletions
@@ -0,0 +1,112 @@
import { Select } from '@/ui/input/components/Select';
import { isDefined } from 'twenty-shared/utils';
import { IconButton, type SelectOption } from 'twenty-ui/input';
import {
IconBox,
IconNorthStar,
IconPlus,
IconTrash,
useIcons,
} from 'twenty-ui/display';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import styled from '@emotion/styled';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
const OBJECT_DROPDOWN_WIDTH = 340;
const ACTION_DROPDOWN_WIDTH = 140;
const OBJECT_MOBILE_WIDTH = 150;
const ACTION_MOBILE_WIDTH = 140;
const StyledFilterRow = styled.div<{ isMobile: boolean }>`
display: grid;
grid-template-columns: ${({ isMobile }) =>
isMobile
? `${OBJECT_MOBILE_WIDTH}px ${ACTION_MOBILE_WIDTH}px auto`
: `${OBJECT_DROPDOWN_WIDTH}px ${ACTION_DROPDOWN_WIDTH}px auto`};
gap: ${({ theme }) => theme.spacing(2)};
margin-bottom: ${({ theme }) => theme.spacing(2)};
align-items: center;
`;
const StyledPlaceholder = styled.div`
height: ${({ theme }) => theme.spacing(8)};
width: ${({ theme }) => theme.spacing(8)};
`;
export const SettingsDatabaseEventsForm = ({
events,
updateOperation,
removeOperation,
disabled = false,
}: {
events: { object: string | null; action: string }[];
updateOperation?: (
index: number,
field: 'object' | 'action',
value: string | null,
) => void;
removeOperation?: (index: number) => void;
disabled?: boolean;
}) => {
const isMobile = useIsMobile();
const { objectMetadataItems } = useObjectMetadataItems();
const { getIcon } = useIcons();
const objectOptions: SelectOption<string>[] = [
{ label: 'All Objects', value: '*', Icon: IconNorthStar },
...objectMetadataItems.map((item) => ({
label: item.labelPlural,
value: item.nameSingular,
Icon: getIcon(item.icon),
})),
];
const actionOptions: SelectOption<string>[] = [
{ label: 'All', value: '*', Icon: IconNorthStar },
{ label: 'Created', value: 'created', Icon: IconPlus },
{ label: 'Updated', value: 'updated', Icon: IconBox },
{ label: 'Deleted', value: 'deleted', Icon: IconTrash },
];
return (
<>
{events.map((operation, index) => (
<StyledFilterRow key={index} isMobile={isMobile}>
<Select
dropdownId={`object-webhook-type-select-${index}`}
value={operation.object}
options={objectOptions}
onChange={(newValue) =>
updateOperation?.(index, 'object', newValue)
}
fullWidth
emptyOption={{ label: 'Object', value: null }}
disabled={disabled}
/>
<Select
dropdownId={`operation-webhook-type-select-${index}`}
value={operation.action}
options={actionOptions}
onChange={(newValue) =>
updateOperation?.(index, 'action', newValue)
}
fullWidth
disabled={disabled}
/>
{isDefined(operation.object) && !disabled ? (
<IconButton
Icon={IconTrash}
variant="tertiary"
size="medium"
onClick={() => removeOperation?.(index)}
/>
) : (
<StyledPlaceholder />
)}
</StyledFilterRow>
))}
</>
);
};
@@ -0,0 +1,27 @@
import { Tag } from 'twenty-ui/components';
import { getItemTagInfo } from '@/settings/data-model/utils/getItemTagInfo';
type SettingsItemTypeTagProps = {
item: {
isCustom?: boolean;
isRemote?: boolean;
applicationId?: string | null;
};
className?: string;
};
export const SettingsItemTypeTag = ({
className,
item: { isCustom, isRemote, applicationId },
}: SettingsItemTypeTagProps) => {
const itemTagInfo = getItemTagInfo({ isCustom, isRemote, applicationId });
return (
<Tag
className={className}
color={itemTagInfo.labelColor}
text={itemTagInfo.labelText}
weight="medium"
/>
);
};