Enhance ObjectList and ObjectProperty components with hyperlink support
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Updated ObjectList to accept a new prop, showHyperlink, allowing for conditional rendering of hyperlinks for object items.
- Modified ObjectProperty to pass the showHyperlink prop to ObjectList and ObjectSelect components, enhancing their functionality.
- Improved error handling in ApiServerContext by adding detailed logging for error responses.
- Updated various database models to include showHyperlink attribute for object lists, improving user navigation and interaction.
- Enhanced CSS styles for the permissions matrix table to improve visual clarity and user experience.
This commit is contained in:
Tom Butcher 2026-08-20 17:26:36 +01:00
parent f07b0d5eef
commit 0b501a11c6
12 changed files with 137 additions and 18 deletions

View File

@ -1337,6 +1337,64 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
vertical-align: middle;
}
.permissions-matrix-table .permissions-matrix-group-row > .ant-table-cell {
font-weight: 600;
background-color: color-mix(
in srgb,
var(--color-text) 6%,
var(--layout-header-bg)
);
}
.permissions-matrix-table
.permissions-matrix-group-row
> .ant-table-cell.ant-table-cell-row-hover {
background: color-mix(
in srgb,
var(--color-text) 10%,
var(--layout-header-bg)
);
}
.permissions-matrix-table .ant-table-row-expand-icon,
.permissions-matrix-table .ant-table-row-indent {
display: none;
}
.permissions-matrix-expand-button.ant-btn {
width: 22px;
min-width: 22px;
height: 22px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
color: inherit;
}
.permissions-matrix-expand-button.ant-btn:hover,
.permissions-matrix-expand-button.ant-btn:focus,
.permissions-matrix-expand-button.ant-btn:focus-visible {
color: inherit;
}
.permissions-matrix-expand-spacer {
display: inline-block;
width: 18px;
height: 22px;
flex-shrink: 0;
}
.permissions-matrix-expand-icon {
font-size: 12px !important;
color: inherit;
transition: transform 0.2s ease;
}
.permissions-matrix-expand-icon-open {
transform: rotate(90deg);
}
.permissions-matrix-table .ant-table-thead > tr > th {
vertical-align: bottom;
padding-top: 12px;

View File

@ -4,7 +4,7 @@ import { Space, Typography } from 'antd'
const { Text } = Typography
const ObjectList = ({ value, objectType, style }) => {
const ObjectList = ({ value, objectType, style, showHyperlink = false }) => {
if (!value || !Array.isArray(value) || value.length === 0) {
return <Text type='secondary'>n/a</Text>
}
@ -12,7 +12,12 @@ const ObjectList = ({ value, objectType, style }) => {
return (
<Space size={'small'} wrap style={style}>
{value.map((item) => (
<ObjectDisplay object={item} objectType={objectType} key={item._id} />
<ObjectDisplay
object={item}
objectType={objectType}
key={item._id}
showHyperlink={showHyperlink}
/>
))}
</Space>
)
@ -21,7 +26,8 @@ const ObjectList = ({ value, objectType, style }) => {
ObjectList.propTypes = {
value: PropTypes.array,
objectType: PropTypes.string,
style: PropTypes.object
style: PropTypes.object,
showHyperlink: PropTypes.bool
}
export default ObjectList

View File

@ -475,7 +475,13 @@ const ObjectProperty = ({
}
}
case 'objectList': {
return <ObjectList value={value} objectType={objectType} />
return (
<ObjectList
value={value}
objectType={objectType}
showHyperlink={showHyperlink}
/>
)
}
case 'objectChildren': {
return (
@ -958,7 +964,14 @@ const ObjectProperty = ({
<ObjectTypeSelect masterFilter={masterFilter} {...inputProps} />
)
case 'objectList':
return <ObjectSelect type={objectType} multiple {...inputProps} />
return (
<ObjectSelect
type={objectType}
multiple
showHyperlink={showHyperlink}
{...inputProps}
/>
)
case 'tags':
return (
<TagsInput

View File

@ -1015,6 +1015,16 @@ const ApiServerProvider = ({ children }) => {
const showError = useCallback(
(error, callback = null) => {
console.error(error)
console.error(error.response)
console.error(error.response.data)
console.error(error.response.data.code)
console.error(error.response.data.error)
console.error(error.response.data.message)
console.error(error.response.data.status)
console.error(error.response.data.timestamp)
console.error(error.response.data.path)
console.error(error.response.data.method)
const code = error.response.data.code || 'UNKNOWN'
if (code == 'UNAUTHORIZED') {
setUnauthenticated()

View File

@ -208,7 +208,8 @@ export const DocumentTemplate = {
label: 'Document Printers',
required: false,
type: 'objectList',
objectType: 'documentPrinter'
objectType: 'documentPrinter',
showHyperlink: true
},
{
name: 'content',

View File

@ -1,7 +1,8 @@
import { createElement, lazy } from 'react'
const FilamentProfileInfo = lazy(
() => import('../../components/Dashboard/Production/FilamentProfiles/FilamentProfileInfo')
() =>
import('../../components/Dashboard/Production/FilamentProfiles/FilamentProfileInfo')
)
import FilamentProfileIcon from '../../components/Icons/FilamentProfileIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
@ -75,7 +76,14 @@ export const FilamentProfile = {
content: () => createElement(FilamentProfileInfo)
}
],
columns: ['_reference', 'name', 'filamentType', 'filament', 'createdAt', 'updatedAt'],
columns: [
'_reference',
'name',
'filamentType',
'filament',
'createdAt',
'updatedAt'
],
filters: ['_id', 'name', 'createdAt', 'updatedAt', '_reference'],
sorters: ['name', 'createdAt', 'updatedAt'],
properties: [
@ -1203,7 +1211,8 @@ export const FilamentProfile = {
type: 'objectList',
objectType: 'printerProfile',
span: 2,
columnWidth: 220
columnWidth: 220,
showHyperlink: true
},
{
name: 'compatiblePrintersCondition',

View File

@ -270,7 +270,8 @@ export const Host = {
objectType: 'file',
required: false,
readOnly: true,
columnWidth: 200
columnWidth: 200,
showHyperlink: true
}
]
}

View File

@ -245,7 +245,8 @@ export const Job = {
type: 'objectList',
objectType: 'printer',
required: true,
columnWidth: 200
columnWidth: 200,
showHyperlink: true
}
],
stats: [

View File

@ -4,7 +4,8 @@ const ListingInfo = lazy(
() => import('../../components/Dashboard/Sales/Listings/ListingInfo')
)
const NewListingVarient = lazy(
() => import('../../components/Dashboard/Sales/ListingVarients/NewListingVarient')
() =>
import('../../components/Dashboard/Sales/ListingVarients/NewListingVarient')
)
const PublishListing = lazy(
() => import('../../components/Dashboard/Sales/Listings/PublishListing')
@ -76,7 +77,11 @@ export const Listing = {
label: 'New Listing Varient',
icon: PlusIcon,
content: (objectData, { onOk } = {}) => {
return createElement(NewListingVarient, { defaultValues: { listing: objectData }, onOk, reset: true })
return createElement(NewListingVarient, {
defaultValues: { listing: objectData },
onOk,
reset: true
})
}
},
{ type: 'divider' },
@ -308,7 +313,7 @@ export const Listing = {
name: 'courierServices',
label: 'Courier Services',
type: 'objectList',
multiple: true,
showHyperlink: true,
objectType: 'courierService',
readOnly: false,
required: true,

View File

@ -482,6 +482,7 @@ export const Printer = {
name: 'queue',
label: 'Queue',
type: 'objectList',
showHyperlink: true,
objectType: 'subJob',
required: false,
readOnly: true,

View File

@ -185,6 +185,7 @@ export const User = {
name: 'groups',
label: 'Groups',
type: 'objectList',
showHyperlink: true,
objectType: 'userGroup',
span: 2,
columnWidth: 250

View File

@ -75,8 +75,20 @@ export const UserGroup = {
content: () => createElement(UserGroupInfo)
}
],
columns: ['_reference', 'name', 'permissionSettings', 'createdAt', 'updatedAt'],
filters: ['name', 'permissionSettings', 'createdAt', 'updatedAt', '_reference'],
columns: [
'_reference',
'name',
'permissionSettings',
'createdAt',
'updatedAt'
],
filters: [
'name',
'permissionSettings',
'createdAt',
'updatedAt',
'_reference'
],
sorters: ['name', 'createdAt', '_id', 'updatedAt'],
properties: [
{
@ -126,7 +138,8 @@ export const UserGroup = {
type: 'objectList',
objectType: 'permissionSetting',
span: 2,
columnWidth: 250
columnWidth: 250,
showHyperlink: true
},
{
name: 'permissions',