fix: update settings page for mobile viewport (#18991)
## Description - This PR fixes https://github.com/twentyhq/core-team-issues/issues/2313#issuecomment-4116380772 - Fixes Admin Panel Apps table, Data model table and Roles table - made data model table scrollable for mobile viewport keeping name column fixed. ## Visual Appearance ## Before - Roles Table <img width="636" height="1039" alt="Screenshot 2026-03-26 at 1 28 30 PM" src="https://github.com/user-attachments/assets/fa7532bd-aeb0-4c8f-a40e-08cc976cd2c2" /> - Admin Apps table <img width="610" height="998" alt="Screenshot 2026-03-26 at 1 28 12 PM" src="https://github.com/user-attachments/assets/8712473c-350f-46f8-9e68-9cb0a5fa9d80" /> - Data Model table https://github.com/user-attachments/assets/c48075c5-56dd-4b76-acd4-76330d6dab94 ## After - Roles Table <img width="761" height="1045" alt="Screenshot 2026-03-26 at 1 23 19 PM" src="https://github.com/user-attachments/assets/17099956-816a-4d41-b987-563f6931a995" /> - Admin Apps table <img width="794" height="1044" alt="Screenshot 2026-03-26 at 1 23 34 PM" src="https://github.com/user-attachments/assets/0463a087-2363-4192-9adb-7d27076f303a" /> - Data model Table https://github.com/user-attachments/assets/fd44e353-cc7c-44cf-bda0-d2f3cd531f2e --------- Co-authored-by: Charles Bochet <charles@twenty.com> Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
@@ -6,7 +6,11 @@ import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField
|
||||
import { useCombinedGetTotalCount } from '@/object-record/multiple-objects/hooks/useCombinedGetTotalCount';
|
||||
import { SettingsObjectMetadataItemTableRow } from '@/settings/data-model/object-details/components/SettingsObjectItemTableRow';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS } from '@/settings/data-model/object-details/components/SettingsObjectItemTableRowStyledComponents';
|
||||
import {
|
||||
SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS,
|
||||
SETTINGS_OBJECT_TABLE_ROW_MOBILE_MIN_WIDTH,
|
||||
StyledStickyFirstCell,
|
||||
} from '@/settings/data-model/object-details/components/SettingsObjectItemTableRowStyledComponents';
|
||||
import { SettingsObjectInactiveMenuDropDown } from '@/settings/data-model/objects/components/SettingsObjectInactiveMenuDropDown';
|
||||
import { getItemTagInfo } from '@/settings/data-model/utils/getItemTagInfo';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
@@ -26,7 +30,11 @@ import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { IconArchive, IconChevronRight, IconSettings } from 'twenty-ui/display';
|
||||
import { SearchInput } from 'twenty-ui/input';
|
||||
import { MenuItemToggle } from 'twenty-ui/navigation';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import {
|
||||
MOBILE_VIEWPORT,
|
||||
ThemeContext,
|
||||
themeCssVariables,
|
||||
} from 'twenty-ui/theme-constants';
|
||||
import { GET_SETTINGS_OBJECT_TABLE_METADATA } from '~/pages/settings/data-model/constants/SettingsObjectTableMetadata';
|
||||
import type { SettingsObjectTableItem } from '~/pages/settings/data-model/types/SettingsObjectTableItem';
|
||||
import { normalizeSearchText } from '~/utils/normalizeSearchText';
|
||||
@@ -39,6 +47,19 @@ const StyledSearchInputContainer = styled.div`
|
||||
padding-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledScrollWrapper = styled.div`
|
||||
@media (max-width: ${MOBILE_VIEWPORT}px) {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledScrollableContent = styled.div`
|
||||
@media (max-width: ${MOBILE_VIEWPORT}px) {
|
||||
min-width: ${SETTINGS_OBJECT_TABLE_ROW_MOBILE_MIN_WIDTH};
|
||||
}
|
||||
`;
|
||||
|
||||
export const SettingsObjectTable = ({
|
||||
objectMetadataItems,
|
||||
withSearchBar = true,
|
||||
@@ -170,74 +191,98 @@ export const SettingsObjectTable = ({
|
||||
</StyledSearchInputContainer>
|
||||
)}
|
||||
|
||||
<Table>
|
||||
<TableRow
|
||||
gridTemplateColumns={SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS}
|
||||
>
|
||||
{GET_SETTINGS_OBJECT_TABLE_METADATA.fields.map(
|
||||
(settingsObjectsTableMetadataField) => (
|
||||
<SortableTableHeader
|
||||
key={settingsObjectsTableMetadataField.fieldName}
|
||||
fieldName={settingsObjectsTableMetadataField.fieldName}
|
||||
label={t(settingsObjectsTableMetadataField.fieldLabel)}
|
||||
tableId={GET_SETTINGS_OBJECT_TABLE_METADATA.tableId}
|
||||
align={settingsObjectsTableMetadataField.align}
|
||||
initialSort={GET_SETTINGS_OBJECT_TABLE_METADATA.initialSort}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
<TableHeader></TableHeader>
|
||||
</TableRow>
|
||||
{filteredObjectSettingsItems.map((objectSettingsItem) => {
|
||||
const isActive = objectSettingsItem.objectMetadataItem.isActive;
|
||||
|
||||
return (
|
||||
<SettingsObjectMetadataItemTableRow
|
||||
key={objectSettingsItem.objectMetadataItem.namePlural}
|
||||
objectMetadataItem={objectSettingsItem.objectMetadataItem}
|
||||
totalObjectCount={objectSettingsItem.totalObjectCount}
|
||||
action={
|
||||
isActive ? (
|
||||
<StyledIconChevronRightContainer>
|
||||
<IconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
<StyledScrollWrapper>
|
||||
<StyledScrollableContent>
|
||||
<Table>
|
||||
<TableRow
|
||||
gridTemplateColumns={
|
||||
SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS
|
||||
}
|
||||
>
|
||||
{GET_SETTINGS_OBJECT_TABLE_METADATA.fields.map(
|
||||
(settingsObjectsTableMetadataField, index) =>
|
||||
index === 0 ? (
|
||||
<StyledStickyFirstCell
|
||||
key={settingsObjectsTableMetadataField.fieldName}
|
||||
>
|
||||
<SortableTableHeader
|
||||
fieldName={settingsObjectsTableMetadataField.fieldName}
|
||||
label={t(settingsObjectsTableMetadataField.fieldLabel)}
|
||||
tableId={GET_SETTINGS_OBJECT_TABLE_METADATA.tableId}
|
||||
align={settingsObjectsTableMetadataField.align}
|
||||
initialSort={
|
||||
GET_SETTINGS_OBJECT_TABLE_METADATA.initialSort
|
||||
}
|
||||
/>
|
||||
</StyledStickyFirstCell>
|
||||
) : (
|
||||
<SortableTableHeader
|
||||
key={settingsObjectsTableMetadataField.fieldName}
|
||||
fieldName={settingsObjectsTableMetadataField.fieldName}
|
||||
label={t(settingsObjectsTableMetadataField.fieldLabel)}
|
||||
tableId={GET_SETTINGS_OBJECT_TABLE_METADATA.tableId}
|
||||
align={settingsObjectsTableMetadataField.align}
|
||||
initialSort={
|
||||
GET_SETTINGS_OBJECT_TABLE_METADATA.initialSort
|
||||
}
|
||||
/>
|
||||
</StyledIconChevronRightContainer>
|
||||
) : (
|
||||
<SettingsObjectInactiveMenuDropDown
|
||||
isCustomObject={
|
||||
objectSettingsItem.objectMetadataItem.isCustom
|
||||
}
|
||||
objectMetadataItemNamePlural={
|
||||
objectSettingsItem.objectMetadataItem.namePlural
|
||||
}
|
||||
onActivate={() =>
|
||||
updateOneObjectMetadataItem({
|
||||
idToUpdate: objectSettingsItem.objectMetadataItem.id,
|
||||
updatePayload: { isActive: true },
|
||||
})
|
||||
}
|
||||
onDelete={() =>
|
||||
deleteOneObjectMetadataItem(
|
||||
objectSettingsItem.objectMetadataItem.id,
|
||||
)
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
link={
|
||||
isActive
|
||||
? getSettingsPath(SettingsPath.ObjectDetail, {
|
||||
objectNamePlural:
|
||||
objectSettingsItem.objectMetadataItem.namePlural,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Table>
|
||||
),
|
||||
)}
|
||||
<TableHeader></TableHeader>
|
||||
</TableRow>
|
||||
{filteredObjectSettingsItems.map((objectSettingsItem) => {
|
||||
const isActive = objectSettingsItem.objectMetadataItem.isActive;
|
||||
|
||||
return (
|
||||
<SettingsObjectMetadataItemTableRow
|
||||
key={objectSettingsItem.objectMetadataItem.namePlural}
|
||||
objectMetadataItem={objectSettingsItem.objectMetadataItem}
|
||||
totalObjectCount={objectSettingsItem.totalObjectCount}
|
||||
action={
|
||||
isActive ? (
|
||||
<StyledIconChevronRightContainer>
|
||||
<IconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
</StyledIconChevronRightContainer>
|
||||
) : (
|
||||
<SettingsObjectInactiveMenuDropDown
|
||||
isCustomObject={
|
||||
objectSettingsItem.objectMetadataItem.isCustom
|
||||
}
|
||||
objectMetadataItemNamePlural={
|
||||
objectSettingsItem.objectMetadataItem.namePlural
|
||||
}
|
||||
onActivate={() =>
|
||||
updateOneObjectMetadataItem({
|
||||
idToUpdate:
|
||||
objectSettingsItem.objectMetadataItem.id,
|
||||
updatePayload: { isActive: true },
|
||||
})
|
||||
}
|
||||
onDelete={() =>
|
||||
deleteOneObjectMetadataItem(
|
||||
objectSettingsItem.objectMetadataItem.id,
|
||||
)
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
link={
|
||||
isActive
|
||||
? getSettingsPath(SettingsPath.ObjectDetail, {
|
||||
objectNamePlural:
|
||||
objectSettingsItem.objectMetadataItem.namePlural,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Table>
|
||||
</StyledScrollableContent>
|
||||
</StyledScrollWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user