Skip to content

Commit e4f978a

Browse files
authored
Merge pull request KelvinTegelaar#5916 from KelvinTegelaar/dev
Dev to hotfix
2 parents 9f1cc80 + a1b630f commit e4f978a

5 files changed

Lines changed: 75 additions & 13 deletions

File tree

.github/workflows/cipp_frontend_build.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ jobs:
3838
- name: Build Project
3939
run: npm run build
4040

41+
# Update version.json with commit hash
42+
- name: Update version.json
43+
run: |
44+
VERSION=$(jq -r '.version' public/version.json)
45+
SHORT_SHA="${GITHUB_SHA::7}"
46+
echo "{\"version\": \"${VERSION}\", \"commit\": \"${SHORT_SHA}\"}" > out/version.json
47+
4148
# Create ZIP File in a New Source Directory
4249
- name: Prepare and Zip Build Files
4350
run: |

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cipp",
3-
"version": "10.4.0",
3+
"version": "10.4.1",
44
"author": "CIPP Contributors",
55
"homepage": "https://cipp.app/",
66
"bugs": {

public/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"version": "10.4.0"
2+
"version": "10.4.1"
33
}

src/components/CippTable/util-columnsFromAPI.js

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,31 @@ const MAX_COL_SIZE = 500
1818
// resize handle, filter icon). These sit alongside the header text and consume space.
1919
const HEADER_CHROME_PX = 75
2020

21+
// Extra pixels per chip for icon + internal padding + margin.
22+
const CHIP_CHROME_PX = 45
23+
24+
// DateTime columns render as relative time (e.g. "about 2 months ago"). Use a fixed
25+
// character length instead of measuring the raw ISO date string.
26+
const RELATIVE_TIME_CHARS = 20
27+
28+
// Known datetime accessor names and pattern — must stay in sync with get-cipp-formatting.js
29+
const TIME_AGO_NAMES = new Set([
30+
'ExecutedTime', 'ScheduledTime', 'Timestamp', 'timestamp', 'DateTime', 'LastRun',
31+
'LastRefresh', 'createdDateTime', 'activatedDateTime', 'lastModifiedDateTime',
32+
'endDateTime', 'ReceivedTime', 'Expires', 'updatedAt', 'createdAt', 'Received',
33+
'Date', 'WhenCreated', 'WhenChanged', 'CreationTime', 'renewalDate',
34+
'commitmentTerm.renewalConfiguration.renewalDate', 'purchaseDate', 'NextOccurrence',
35+
'LastOccurrence', 'NotBefore', 'NotAfter', 'latestDataCollection',
36+
'requestDate', 'reviewedDate', 'GeneratedAt',
37+
])
38+
const MATCH_DATE_TIME = /([dD]ate[tT]ime|[Ee]xpiration|[Tt]imestamp|[sS]tart[Dd]ate)/
39+
const isDateTimeColumn = (key) => TIME_AGO_NAMES.has(key) || MATCH_DATE_TIME.test(key)
40+
2141
// Measure the pixel width a column needs based on its header and sampled cell values.
2242
// rawValues are the original data values (before formatting) — if they contain arrays or
2343
// complex objects the column renders as a button/chip list, so we cap to header width.
2444
// Returns { size, minSize } where minSize is always header-width + chrome safe space.
25-
const measureColumnSize = (header, valuesForColumn, rawValues) => {
45+
const measureColumnSize = (header, valuesForColumn, rawValues, accessorKey) => {
2646
const headerLen = header ? header.length : 6
2747
const headerPx = Math.round(headerLen * CHAR_WIDTH + CELL_PADDING + HEADER_CHROME_PX)
2848
const minSize = Math.max(MIN_COL_SIZE, headerPx)
@@ -40,34 +60,64 @@ const measureColumnSize = (header, valuesForColumn, rawValues) => {
4060
// "X items" button (CippDataTableButton), so size to the button width.
4161
const allObjectLike = rawValues.every((v) => {
4262
if (v === null || v === undefined) return true // nulls are fine, they show "No items"
43-
if (Array.isArray(v)) return v.some((el) => typeof el === 'object' && el !== null)
63+
if (Array.isArray(v)) return v.length === 0 || v.some((el) => typeof el === 'object' && el !== null)
4464
return typeof v === 'object'
4565
})
4666
if (allObjectLike) {
47-
// "X items" button is roughly 80-100px wide — just use header width
48-
return { size: minSize, minSize }
67+
// The formatted text tells us how this column actually renders:
68+
// - JSON strings (starts with [ or {) → CippDataTableButton ("X items"), compact
69+
// - Comma-separated text → chips/inline content, needs real measurement
70+
const looksLikeButton = valuesForColumn.every((t) => {
71+
if (t === null || t === undefined || t === '' || t === 'No data') return true
72+
if (Array.isArray(t)) return true // handler returned a raw array (e.g. [])
73+
const s = typeof t === 'string' ? t.trim() : ''
74+
return s.startsWith('[') || s.startsWith('{') || s === 'Password hidden'
75+
})
76+
if (looksLikeButton) {
77+
return { size: minSize, minSize }
78+
}
79+
// Object arrays that render as chips — measure the longest item from the
80+
// comma-separated text representation.
81+
let longestObjItem = headerLen
82+
for (const t of valuesForColumn) {
83+
if (typeof t !== 'string') continue
84+
const parts = t.split(',')
85+
for (const p of parts) {
86+
const len = p.trim().length
87+
if (len > longestObjItem) longestObjItem = len
88+
}
89+
}
90+
const objChipPx = Math.round(longestObjItem * CHAR_WIDTH + CELL_PADDING + CHIP_CHROME_PX + HEADER_CHROME_PX)
91+
const objSize = Math.max(minSize, Math.min(MAX_COL_SIZE, objChipPx))
92+
return { size: objSize, minSize }
4993
}
5094

51-
// String/primitive arrays → rendered as chip list. Measure longest chip,
52-
// but cap per-chip text since chips truncate long values (e.g. email addresses).
53-
const MAX_CHIP_TEXT = 15
95+
// String/primitive arrays → rendered as chip list. Measure the longest
96+
// single item across all rows, then size like a regular text column.
5497
let longestItem = headerLen
5598
for (let i = 0; i < rawValues.length; i++) {
5699
const v = rawValues[i]
57100
if (Array.isArray(v)) {
58101
for (const el of v) {
59102
const s = typeof el === 'string' ? el : el != null ? String(el) : ''
60-
const len = Math.min(s.length, MAX_CHIP_TEXT)
61-
if (len > longestItem) longestItem = len
103+
if (s.length > longestItem) longestItem = s.length
62104
}
63105
}
64106
}
65-
const chipPx = Math.round(longestItem * CHAR_WIDTH + CELL_PADDING)
107+
const chipPx = Math.round(longestItem * CHAR_WIDTH + CELL_PADDING + CHIP_CHROME_PX + HEADER_CHROME_PX)
66108
const size = Math.max(minSize, Math.min(MAX_COL_SIZE, chipPx))
67109
return { size, minSize }
68110
}
69111
}
70112

113+
// DateTime columns render as relative time — use a fixed width instead of the raw string.
114+
if (accessorKey && isDateTimeColumn(accessorKey)) {
115+
const dtLen = Math.max(headerLen, RELATIVE_TIME_CHARS)
116+
const dtPx = Math.round(dtLen * CHAR_WIDTH + CELL_PADDING)
117+
const size = Math.max(minSize, Math.min(MAX_COL_SIZE, dtPx))
118+
return { size, minSize }
119+
}
120+
71121
const sample =
72122
valuesForColumn.length > MAX_SIZE_SAMPLE
73123
? valuesForColumn.slice(0, MAX_SIZE_SAMPLE)
@@ -214,7 +264,7 @@ export const utilColumnsFromAPI = (dataArray) => {
214264
// Measure content width from formatted text values for this column.
215265
const textValues = valuesForColumn.map((v) => getCippFormatting(v, accessorKey, 'text'))
216266
const header = getCippTranslation(accessorKey)
217-
const measuredSize = measureColumnSize(header, textValues, valuesForColumn)
267+
const measuredSize = measureColumnSize(header, textValues, valuesForColumn, accessorKey)
218268

219269
// Allow per-column size overrides for columns whose rendered output
220270
// doesn't match text width (icons, progress bars, etc.).

src/utils/get-cipp-column-size.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export const getCippColumnSize = (accessorKey, header) => {
2323
case 'info.logoUrl':
2424
return { size: 'header', minSize: 'header' }
2525

26+
// String arrays that named handlers transform into CippDataTableButton
27+
// ("X items" button) — don't measure the raw text.
28+
case 'proxyAddresses':
29+
return { size: 'header', minSize: 'header' }
30+
2631
default:
2732
return null
2833
}

0 commit comments

Comments
 (0)