Skip to content

feat: Seed List#2776

Merged
gardener-prow[bot] merged 13 commits into
masterfrom
enh/seed-list
Mar 3, 2026
Merged

feat: Seed List#2776
gardener-prow[bot] merged 13 commits into
masterfrom
enh/seed-list

Conversation

@petersutter
Copy link
Copy Markdown
Member

@petersutter petersutter commented Feb 13, 2026

What this PR does / why we need it:

Which issue(s) this PR fixes:
Fixes #

Special notes for your reviewer:

Release note:

The dashboard now displays seeds in a dedicated table

Summary by CodeRabbit

  • New Features

    • Seeds management view with sortable, filterable table, customizable columns, persistent preferences and a dedicated Seeds route
    • Reusable table search UI with examples, syntax help and URL‑synced query
    • New row and status components for seed listings with richer status popovers
  • Improvements

    • Main navigation split into namespaced and non‑namespaced sections with clearer icons/titles
    • Enhanced sorting/filtering (readiness, last operation, semantic versions) and persistent seed sort/columns
  • Tests

    • Added extensive unit tests for sorting, filtering, and search parsing

@gardener-prow gardener-prow Bot added do-not-merge/needs-kind Indicates a PR lacks a `kind/foo` label and requires one. cla: yes Indicates the PR's author has signed the cla-assistant.io CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Feb 13, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Seeds management UI and SeedList route plus multiple new components and composables for sorting, filtering, status normalization, and URL-synced search; updates navigation, routes, store persistence, and adds comprehensive unit tests for the new helpers and composables. (50 words)

Changes

Cohort / File(s) Summary
Tests
frontend/__tests__/composables/useSeedTableSorting.spec.js, frontend/__tests__/composables/useTableFilter/helper.spec.js, frontend/__tests__/composables/useTableFilter/index.spec.js, frontend/__tests__/composables/useTableSorting.spec.js, frontend/__tests__/stores/shoot.spec.js
Added extensive unit tests for sorting/filtering helpers and composables; removed legacy parseSearch tests from shoot store tests.
Views & List UI
frontend/src/views/GSeedList.vue, frontend/src/components/GSeedListRow.vue, frontend/src/components/GTableSearch.vue
New Seeds view and row/status-aware row component; new reusable table search component with URL binding, examples, and emit handling; integrates filtering, sorting, persistent columns, and row rendering.
Status & Row Components
frontend/src/components/GSeedStatus.vue, frontend/src/components/GSeedStatusTag.vue, frontend/src/components/GSeedStatusTags.vue, frontend/src/components/GShootStatus.vue, frontend/src/components/GStatusTags.vue, frontend/src/components/GShootListRow.vue, frontend/src/components/ShootDetails/GShootMonitoringCard.vue, frontend/src/components/ShootDetails/GShootInfrastructureCard.vue
Added GSeedStatus and GSeedListRow; migrated multiple components to use composables (useOperationStatus, useStatusConditions); changed props/interfaces (e.g., identifier, isStaleShoot), removed popper-key uses, and adjusted icons/template bindings.
Composables — Core
frontend/src/composables/useTableSorting/index.js, frontend/src/composables/useTableSorting/helper.js, frontend/src/composables/useTableFilter/index.js, frontend/src/composables/useTableFilter/helper.js, frontend/src/composables/useUrlSearchSync.js
New generic composables for table sorting (compare helpers, semantic version compare), filtering (tokenize/parse/search query), and URL-synced search; exported APIs: useTableSorting, getReadiness/lastOperation helpers, useTableFilter, tokenizeSearch/SearchQuery/parseSearch, useUrlSearchSync.
Composables — Seed-specific & Status
frontend/src/composables/useSeedTableSorting.js, frontend/src/composables/useSeedItem.js, frontend/src/composables/useOperationStatus.js, frontend/src/composables/useStatusConditions.js
Seed-specific sorting/comparators and seed-item helpers added; operation-status abstraction and status-condition normalization composables introduced and exported.
Sorting Helpers
frontend/src/composables/useTableSorting/helper.js, frontend/src/composables/useTableSorting/index.js
Added getReadinessSortVal and getLastOperationSortVal with multi-branch sort value logic; exposed compareValues and compareSemanticVersions and reactive sortBy handling.
Store & Persistence
frontend/src/store/localStorage.js, frontend/src/store/shoot/helper.js, frontend/src/store/config.js
Persisted seedSelectedColumns and seedSortBy added; shoot helper delegated readiness/lastOperation sort logic to external helpers and removed inline search parsing; config condition lookup fallback adjusted.
Navigation, Router & Breadcrumbs
frontend/src/components/GMainNavigation.vue, frontend/src/router/routes.js, frontend/src/router/breadcrumbs.js
Navigation split into namespaced vs non-namespaced groups; added SeedList route with admin guard and breadcrumbs; removed usage/export of namespacedRoute helper.
Utilities
frontend/src/utils/index.js
Removed exported namespacedRoute helper; components now use local menu-route builders.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant View as GSeedList
    participant UrlSync as useUrlSearchSync
    participant Filter as useTableFilter
    participant Sorting as useSeedTableSorting
    participant Store as LocalStore

    User->>View: open Seeds view
    View->>UrlSync: init search sync (param 'q')
    UrlSync-->>View: reactive search ref
    View->>Sorting: init sorting (load seedSortBy)
    Sorting->>Store: read seedSortBy
    Sorting-->>View: sortBy & comparators
    View->>Filter: init filtering (items, filterFn, searchQuery)
    Filter-->>View: filteredItems
    User->>View: change search / change sort / toggle columns
    View->>UrlSync: update search -> sync URL
    View->>Filter: compute filtered items
    View->>Sorting: sort filtered items -> sorted items
    View->>Store: persist selectedColumns, seedSortBy
    View-->>User: render updated table
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇
I nibble code in tidy rows,
Seeds and routes where data grows.
Search that hums and sort that sings,
Composables hop on nimble springs.
A rabbit cheers — may tests pass swift!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete. While a release note is provided, the critical sections 'What this PR does / why we need it' and 'Which issue(s) this PR fixes' are left blank, missing key information about implementation rationale and issue linkage. Fill in the 'What this PR does / why we need it' section with a detailed explanation of the implementation. Add the issue number(s) this PR fixes in the 'Which issue(s) this PR fixes' section.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Seed List' clearly summarizes the main change—adding a new Seed List feature to the dashboard. It directly reflects the primary objective and is concise and specific.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch enh/seed-list

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@petersutter petersutter added the kind/enhancement Enhancement, improvement, extension label Feb 13, 2026
@gardener-prow gardener-prow Bot removed the do-not-merge/needs-kind Indicates a PR lacks a `kind/foo` label and requires one. label Feb 13, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In `@frontend/src/components/GSeedStatus.vue`:
- Around line 140-142: The computed property popoverKey accesses
seedMetadata.value.uid directly which will throw if seedMetadata.value is
undefined; update the popoverKey computed (the computed named popoverKey) to
safely handle missing seedMetadata.value by checking for existence (or using a
fallback/empty string or 'unknown' id) before concatenating the UID so the
template doesn't error when seedMetadata.value is undefined.
- Around line 106-118: The component defines a required prop popperKey but never
uses it—popoverKey is computed from seedMetadata.value.uid instead—so either
remove the unused prop or use it; to fix, pick one: (a) delete the popperKey
entry from defineProps and update any parent usages, or (b) change the computed
popoverKey to use the prop (popperKey) as the primary value (falling back to
seedMetadata.value.uid if needed) and remove the required flag if fallback is
allowed; locate defineProps, the computed popoverKey, and any references to
seedMetadata.value.uid to implement the chosen option.

In `@frontend/src/components/GTableSearch.vue`:
- Around line 10-26: The Esc key handler currently emits null which breaks the
String-typed v-model contract; update the `@keyup.esc` handler on the v-text-field
(the element binding tooltipProps and :model-value="modelValue") to emit an
empty string instead of null (i.e., emit('update:modelValue', '') ) so
modelValue remains a String default ('') and downstream code keeps correct
types.

In `@frontend/src/composables/useOperationStatus.js`:
- Around line 23-29: The computed getters operationType and operationState (and
similarly defaultLastMessage) assume lastOperation.value is non-null and will
throw if it's null/undefined; update them to defensively access
lastOperation.value by checking existence first (e.g., use lastOperation.value
&& lastOperation.value.type / .state or optional chaining
lastOperation.value?.type) and fall back to the existing defaults ('Create' and
'Pending' and defaultLastMessage's fallback) so the computed functions return
safe values when lastOperation.value is null/undefined; ensure you update the
operationType, operationState, and defaultLastMessage definitions accordingly.

In `@frontend/src/composables/useTableSorting/helper.js`:
- Around line 19-42: In getReadinessSortVal's iteratee,
configStore.conditionForType(type) can be undefined causing .sortOrder to throw;
change the code to safely resolve a default sortOrder when
conditionForType(type) is missing (e.g. use optional chaining or a nullish
coalescing fallback and a numeric/default string like 99999999), then padStart
that resolved value and proceed—update the iteratee in getReadinessSortVal to
call configStore.conditionForType(type)?.sortOrder ?? <default> and use that
instead of accessing .sortOrder directly.
- Around line 44-83: In getLastOperationSortVal update the inProgress checks so
0 is treated as in-progress by testing for null/undefined rather than
truthiness; replace occurrences of "!!operation.progress" with a explicit
null/undefined check (e.g., operation.progress !== null && operation.progress
!== undefined) and ensure the existing check operation.progress !== 100 remains,
so inProgress becomes operation.progress !== null && operation.progress !==
undefined && operation.progress !== 100 && operation.state !== 'Failed'.

In `@frontend/src/router/routes.js`:
- Around line 281-301: The SeedList route (seedListRoute) currently only hides
the menu via meta but allows direct access; replace its beforeEnter:
addNamespaceToUrl with an admin-checking guard (or a composed guard) that first
verifies authnStore.isAdmin and aborts/redirects non-admins (e.g., next({ name:
'NotFound' }) or redirect to home), and only if the user is admin invoke
addNamespaceToUrl to continue; update the route's beforeEnter to call this admin
guard (or compose requireAdminBeforeEnter with addNamespaceToUrl) so non-admins
cannot navigate directly to the SeedList view.
🧹 Nitpick comments (2)
frontend/__tests__/composables/useTableFilter/index.spec.js (1)

117-133: Consider adding tests for ref validation.

The composable throws TypeError when items or searchQuery are not refs, but these error paths are not tested. Adding tests for these cases would improve coverage.

📝 Suggested additional test cases
it('should throw error when items is not a ref', () => {
  const searchQuery = ref('')
  const filterFn = (item, query) => item.name.includes(query)

  expect(() => {
    useTableFilter({ items: [], searchQuery, filterFn })
  }).toThrow('items must be a ref object')
})

it('should throw error when searchQuery is not a ref', () => {
  const items = ref([])
  const filterFn = (item, query) => item.name.includes(query)

  expect(() => {
    useTableFilter({ items, searchQuery: '', filterFn })
  }).toThrow('searchQuery must be a ref object')
})
frontend/src/composables/useTableSorting/index.js (1)

13-24: Avoid mutating caller-provided defaultSortBy

ref(defaultSortBy) keeps the same array reference; downstream mutations can leak back to the caller. A shallow copy prevents accidental coupling.

♻️ Suggested change
-  const sortBy = ref(defaultSortBy)
+  const sortBy = ref(defaultSortBy.map(item => ({ ...item })))

Comment thread frontend/src/components/GSeedStatus.vue
Comment on lines +140 to +142
const popoverKey = computed(() => {
return `g-seed-status:${seedMetadata.value.uid}`
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add null safety for seedMetadata.value access.

If seedMetadata.value is undefined, accessing .uid will throw a runtime error.

🛡️ Proposed fix
 const popoverKey = computed(() => {
-  return `g-seed-status:${seedMetadata.value.uid}`
+  return `g-seed-status:${seedMetadata.value?.uid ?? ''}`
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const popoverKey = computed(() => {
return `g-seed-status:${seedMetadata.value.uid}`
})
const popoverKey = computed(() => {
return `g-seed-status:${seedMetadata.value?.uid ?? ''}`
})
🤖 Prompt for AI Agents
In `@frontend/src/components/GSeedStatus.vue` around lines 140 - 142, The computed
property popoverKey accesses seedMetadata.value.uid directly which will throw if
seedMetadata.value is undefined; update the popoverKey computed (the computed
named popoverKey) to safely handle missing seedMetadata.value by checking for
existence (or using a fallback/empty string or 'unknown' id) before
concatenating the UID so the template doesn't error when seedMetadata.value is
undefined.

Comment thread frontend/src/components/GTableSearch.vue
Comment on lines +23 to +29
const operationType = computed(() => {
return lastOperation.value.type || 'Create'
})

const operationState = computed(() => {
return lastOperation.value.state || 'Pending'
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add null safety for lastOperation.value access.

If lastOperation.value is null or undefined, accessing .type or .state will throw a runtime error. Consider adding defensive checks.

🛡️ Proposed fix
 const operationType = computed(() => {
-  return lastOperation.value.type || 'Create'
+  return lastOperation.value?.type || 'Create'
 })

 const operationState = computed(() => {
-  return lastOperation.value.state || 'Pending'
+  return lastOperation.value?.state || 'Pending'
 })

Also apply similar changes to defaultLastMessage:

 const defaultLastMessage = computed(() => {
-  return lastOperation.value.description || 'No description'
+  return lastOperation.value?.description || 'No description'
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const operationType = computed(() => {
return lastOperation.value.type || 'Create'
})
const operationState = computed(() => {
return lastOperation.value.state || 'Pending'
})
const operationType = computed(() => {
return lastOperation.value?.type || 'Create'
})
const operationState = computed(() => {
return lastOperation.value?.state || 'Pending'
})
🤖 Prompt for AI Agents
In `@frontend/src/composables/useOperationStatus.js` around lines 23 - 29, The
computed getters operationType and operationState (and similarly
defaultLastMessage) assume lastOperation.value is non-null and will throw if
it's null/undefined; update them to defensively access lastOperation.value by
checking existence first (e.g., use lastOperation.value &&
lastOperation.value.type / .state or optional chaining
lastOperation.value?.type) and fall back to the existing defaults ('Create' and
'Pending' and defaultLastMessage's fallback) so the computed functions return
safe values when lastOperation.value is null/undefined; ensure you update the
operationType, operationState, and defaultLastMessage definitions accordingly.

Comment on lines +19 to +42
export function getReadinessSortVal ({
conditions,
lastOperationTime,
creationTime,
isErrorFn,
configStore,
}) {
if (!conditions.length) {
// items without conditions have medium priority
const priority = '00000100'
const time = lastOperationTime ?? creationTime
return `${priority}-${time}`
}
const iteratee = ({ type, status = 'True', lastTransitionTime = '1970-01-01T00:00:00Z' }) => {
const isError = isErrorFn(status)
// items without any error have lowest priority
const priority = !isError
? '99999999'
: padStart(configStore.conditionForType(type).sortOrder, 8, '0')
return `${priority}-${lastTransitionTime}`
}
// the condition with the lowest priority and transitionTime is used
return head(conditions.map(iteratee).sort())
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against unknown condition types to avoid sort crashes

configStore.conditionForType(type) can be undefined for new/unknown condition types, which will throw on .sortOrder and break list rendering. Please add a safe fallback.

🛠️ Suggested hardening
-    const priority = !isError
-      ? '99999999'
-      : padStart(configStore.conditionForType(type).sortOrder, 8, '0')
+    const sortOrder = configStore?.conditionForType?.(type)?.sortOrder
+    const priority = !isError
+      ? '99999999'
+      : padStart(sortOrder ?? 0, 8, '0')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function getReadinessSortVal ({
conditions,
lastOperationTime,
creationTime,
isErrorFn,
configStore,
}) {
if (!conditions.length) {
// items without conditions have medium priority
const priority = '00000100'
const time = lastOperationTime ?? creationTime
return `${priority}-${time}`
}
const iteratee = ({ type, status = 'True', lastTransitionTime = '1970-01-01T00:00:00Z' }) => {
const isError = isErrorFn(status)
// items without any error have lowest priority
const priority = !isError
? '99999999'
: padStart(configStore.conditionForType(type).sortOrder, 8, '0')
return `${priority}-${lastTransitionTime}`
}
// the condition with the lowest priority and transitionTime is used
return head(conditions.map(iteratee).sort())
}
export function getReadinessSortVal ({
conditions,
lastOperationTime,
creationTime,
isErrorFn,
configStore,
}) {
if (!conditions.length) {
// items without conditions have medium priority
const priority = '00000100'
const time = lastOperationTime ?? creationTime
return `${priority}-${time}`
}
const iteratee = ({ type, status = 'True', lastTransitionTime = '1970-01-01T00:00:00Z' }) => {
const isError = isErrorFn(status)
// items without any error have lowest priority
const sortOrder = configStore?.conditionForType?.(type)?.sortOrder
const priority = !isError
? '99999999'
: padStart(sortOrder ?? 0, 8, '0')
return `${priority}-${lastTransitionTime}`
}
// the condition with the lowest priority and transitionTime is used
return head(conditions.map(iteratee).sort())
}
🤖 Prompt for AI Agents
In `@frontend/src/composables/useTableSorting/helper.js` around lines 19 - 42, In
getReadinessSortVal's iteratee, configStore.conditionForType(type) can be
undefined causing .sortOrder to throw; change the code to safely resolve a
default sortOrder when conditionForType(type) is missing (e.g. use optional
chaining or a nullish coalescing fallback and a numeric/default string like
99999999), then padStart that resolved value and proceed—update the iteratee in
getReadinessSortVal to call configStore.conditionForType(type)?.sortOrder ??
<default> and use that instead of accessing .sortOrder directly.

Comment on lines +44 to +83
export function getLastOperationSortVal ({
operation = {},
lastErrors = [],
metadata = {},
status = {},
isUserErrorFn = ({ lastErrors }) => isUserError(errorCodesFromArray(lastErrors)),
}) {
const isError = operation.state === 'Failed' || lastErrors.length
const ignoredFromReconciliation = isReconciliationDeactivated(metadata)

if (ignoredFromReconciliation) {
return isError
? 400
: 450
}

const userError = isUserErrorFn({
operation,
lastErrors,
metadata,
status,
})
const inProgress = operation.progress !== 100 && operation.state !== 'Failed' && !!operation.progress

if (userError) {
return inProgress
? Number('3' + padStart(operation.progress, 2, '0'))
: 200
}
if (isError) {
return inProgress
? Number('1' + padStart(operation.progress, 2, '0'))
: 0
}
return inProgress
? Number('6' + padStart(operation.progress, 2, '0'))
: isStatusHibernated(status)
? 500
: 700
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Treat 0% progress as in-progress

!!operation.progress ignores 0, so a 0%-progress operation gets sorted like a completed one. Consider checking for null/undefined instead.

🛠️ Suggested fix
-  const inProgress = operation.progress !== 100 && operation.state !== 'Failed' && !!operation.progress
+  const hasProgress = operation.progress !== undefined && operation.progress !== null
+  const inProgress = hasProgress && operation.progress !== 100 && operation.state !== 'Failed'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function getLastOperationSortVal ({
operation = {},
lastErrors = [],
metadata = {},
status = {},
isUserErrorFn = ({ lastErrors }) => isUserError(errorCodesFromArray(lastErrors)),
}) {
const isError = operation.state === 'Failed' || lastErrors.length
const ignoredFromReconciliation = isReconciliationDeactivated(metadata)
if (ignoredFromReconciliation) {
return isError
? 400
: 450
}
const userError = isUserErrorFn({
operation,
lastErrors,
metadata,
status,
})
const inProgress = operation.progress !== 100 && operation.state !== 'Failed' && !!operation.progress
if (userError) {
return inProgress
? Number('3' + padStart(operation.progress, 2, '0'))
: 200
}
if (isError) {
return inProgress
? Number('1' + padStart(operation.progress, 2, '0'))
: 0
}
return inProgress
? Number('6' + padStart(operation.progress, 2, '0'))
: isStatusHibernated(status)
? 500
: 700
}
export function getLastOperationSortVal ({
operation = {},
lastErrors = [],
metadata = {},
status = {},
isUserErrorFn = ({ lastErrors }) => isUserError(errorCodesFromArray(lastErrors)),
}) {
const isError = operation.state === 'Failed' || lastErrors.length
const ignoredFromReconciliation = isReconciliationDeactivated(metadata)
if (ignoredFromReconciliation) {
return isError
? 400
: 450
}
const userError = isUserErrorFn({
operation,
lastErrors,
metadata,
status,
})
const hasProgress = operation.progress !== undefined && operation.progress !== null
const inProgress = hasProgress && operation.progress !== 100 && operation.state !== 'Failed'
if (userError) {
return inProgress
? Number('3' + padStart(operation.progress, 2, '0'))
: 200
}
if (isError) {
return inProgress
? Number('1' + padStart(operation.progress, 2, '0'))
: 0
}
return inProgress
? Number('6' + padStart(operation.progress, 2, '0'))
: isStatusHibernated(status)
? 500
: 700
}
🤖 Prompt for AI Agents
In `@frontend/src/composables/useTableSorting/helper.js` around lines 44 - 83, In
getLastOperationSortVal update the inProgress checks so 0 is treated as
in-progress by testing for null/undefined rather than truthiness; replace
occurrences of "!!operation.progress" with a explicit null/undefined check
(e.g., operation.progress !== null && operation.progress !== undefined) and
ensure the existing check operation.progress !== 100 remains, so inProgress
becomes operation.progress !== null && operation.progress !== undefined &&
operation.progress !== 100 && operation.state !== 'Failed'.

Comment thread frontend/src/router/routes.js
@ghost
Copy link
Copy Markdown

ghost commented Feb 16, 2026

@holgerkoser, @klocke-io, @grolu You have pull request review open invite, please check

Comment thread frontend/src/components/GMainNavigation.vue
@grolu
Copy link
Copy Markdown
Member

grolu commented Mar 3, 2026

/approve

@gardener-prow
Copy link
Copy Markdown

gardener-prow Bot commented Mar 3, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: grolu

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@gardener-prow gardener-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 3, 2026
@grolu
Copy link
Copy Markdown
Member

grolu commented Mar 3, 2026

/lgtm

@gardener-prow gardener-prow Bot added the lgtm Indicates that a PR is ready to be merged. label Mar 3, 2026
@gardener-prow
Copy link
Copy Markdown

gardener-prow Bot commented Mar 3, 2026

LGTM label has been added.

DetailsGit tree hash: aad5c81d4928e363336e63c5a78489745f58f9bf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cla: yes Indicates the PR's author has signed the cla-assistant.io CLA. kind/enhancement Enhancement, improvement, extension lgtm Indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants