Tom Butcher d02895b78d
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
Add Timeline View Support to ObjectTable and Enhance CSS Styles
- Introduced a new timeline view in the ObjectTable component, allowing users to visualize data over time.
- Updated view mode utilities to include timeline-specific settings for start and end dates, and color properties.
- Enhanced ObjectTableViewButton to manage timeline settings and integrate timeline icon.
- Added CSS styles for timeline components to improve layout and visual feedback.
- Refactored StateTag component to utilize a utility function for state representation, improving maintainability.
2026-09-03 22:25:46 +01:00

129 lines
3.6 KiB
JavaScript

export const DEFAULT_VIEW_MODE = { type: 'list' }
/** Property types that can be used as kanban column categories. */
export const KANBAN_CATEGORY_PROPERTY_TYPES = ['state', 'tags']
export const TIMELINE_COLOR_PROPERTY_TYPES = ['color', 'state']
export const TIMELINE_DATE_PROPERTY_TYPES = ['dateTime']
export const KANBAN_DEFAULT_COLUMN_WIDTH = 360
export const KANBAN_MIN_COLUMN_WIDTH = 200
export const isKanbanCategoryProperty = (property) =>
KANBAN_CATEGORY_PROPERTY_TYPES.includes(property?.type)
export const isTimelineColorProperty = (property) =>
TIMELINE_COLOR_PROPERTY_TYPES.includes(property?.type)
export const isTimelineDateProperty = (property) =>
TIMELINE_DATE_PROPERTY_TYPES.includes(property?.type)
export const normalizeViewMode = (value) => {
if (!value) return DEFAULT_VIEW_MODE
if (typeof value === 'string') {
return {
type: ['cards', 'kanban', 'timeline'].includes(value) ? value : 'list'
}
}
if (value?.type) return value
return DEFAULT_VIEW_MODE
}
export const isCardsView = (vm) => normalizeViewMode(vm).type === 'cards'
export const isKanbanView = (vm) => normalizeViewMode(vm).type === 'kanban'
export const isTimelineView = (vm) => normalizeViewMode(vm).type === 'timeline'
export const getViewModeType = (vm) => normalizeViewMode(vm).type
export const toCategoryFilterValue = (value) => {
if (Array.isArray(value)) {
return value.map(toCategoryFilterValue)
}
if (value && typeof value === 'object') {
return value.type ?? value._id ?? JSON.stringify(value)
}
return String(value)
}
export const getCategoryValueKey = (value) => {
if (
value &&
typeof value === 'object' &&
!Array.isArray(value) &&
value.type != null
) {
return String(value.type)
}
if (value != null) return String(value)
return 'null'
}
/**
* Column keys for a category property value. Multi-value properties (e.g. tags)
* can map an item to multiple columns.
*/
export const getCategoryColumnKeys = (value) => {
if (value === undefined) return []
if (Array.isArray(value)) {
return [
...new Set(
value
.filter((entry) => entry != null && entry !== '')
.map(getCategoryValueKey)
)
]
}
return [getCategoryValueKey(value)]
}
/**
* Merge fetched category values with persisted kanban column order/widths.
* Unknown stored columns are dropped; new values are appended with the default width.
*/
export const resolveKanbanColumns = (
categoryValues = [],
storedColumns = []
) => {
const byKey = new Map(
categoryValues.map((value) => [getCategoryValueKey(value), value])
)
const seen = new Set()
const ordered = []
for (const column of storedColumns || []) {
if (column == null || column.value == null) continue
const key = String(column.value)
if (!byKey.has(key) || seen.has(key)) continue
const width =
typeof column.width === 'number' && column.width > 0
? column.width
: KANBAN_DEFAULT_COLUMN_WIDTH
ordered.push({
key,
value: byKey.get(key),
width: Math.max(KANBAN_MIN_COLUMN_WIDTH, width)
})
seen.add(key)
}
for (const value of categoryValues) {
const key = getCategoryValueKey(value)
if (seen.has(key)) continue
ordered.push({
key,
value,
width: KANBAN_DEFAULT_COLUMN_WIDTH
})
seen.add(key)
}
return ordered
}
export const toKanbanColumnsConfig = (columns) =>
(columns || []).map(({ key, width }) => ({
value: key,
width:
typeof width === 'number' && width > 0
? Math.max(KANBAN_MIN_COLUMN_WIDTH, width)
: KANBAN_DEFAULT_COLUMN_WIDTH
}))