From b75d053eb208477d3f4f3d7b4b8abf058d444279 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 3 Jun 2026 13:36:30 +0200 Subject: [PATCH] Make collapsing log groups by default a user preference --- web/src/assets/locales/en.json | 7 +++++++ .../components/repo/pipeline/PipelineLog.vue | 9 ++++++--- web/src/compositions/useUserConfig.ts | 15 ++++++++++---- web/src/views/user/UserGeneral.vue | 20 +++++++++++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/web/src/assets/locales/en.json b/web/src/assets/locales/en.json index 9e5a2610efa..75a6d997f08 100644 --- a/web/src/assets/locales/en.json +++ b/web/src/assets/locales/en.json @@ -459,6 +459,13 @@ "light": "Light", "dark": "Dark", "auto": "Auto" + }, + "pipeline_logs": { + "pipeline_logs": "Pipeline logs", + "collapse_groups": { + "collapse": "Collapse log groups by default", + "desc": "When opening a finished step, collapse all command groups to show only the outline." + } } }, "secrets": { diff --git a/web/src/components/repo/pipeline/PipelineLog.vue b/web/src/components/repo/pipeline/PipelineLog.vue index be59e38a081..70bdde0dfba 100644 --- a/web/src/components/repo/pipeline/PipelineLog.vue +++ b/web/src/components/repo/pipeline/PipelineLog.vue @@ -179,6 +179,7 @@ import useApiClient from '~/compositions/useApiClient'; import useConfig from '~/compositions/useConfig'; import { requiredInject } from '~/compositions/useInjectProvide'; import useNotifications from '~/compositions/useNotifications'; +import useUserConfig from '~/compositions/useUserConfig'; import type { Pipeline, PipelineConfig, PipelineStep, PipelineWorkflow } from '~/lib/api/types'; import { debounce } from '~/lib/utils'; @@ -209,6 +210,7 @@ defineEmits<{ const notifications = useNotifications(); const i18n = useI18n(); +const { userConfig } = useUserConfig(); const pipeline = toRef(props, 'pipeline'); const stepId = toRef(props, 'stepId'); const repo = requiredInject('repo'); @@ -572,11 +574,12 @@ const expandLogGroupWithPageHash = (hash: string) => { } }; -// When user click on a step, if the step has already finished running, show user the -// only the outline by collapse all log groups +// When a user opens a step that has already finished running, collapse all log +// groups by default so they see only the command outline. This is opt-out via +// the "collapse log groups by default" user preference. watch(loadedLogs, async (isLoaded, wasLoaded) => { // Only trigger when transitioning from unloaded to loaded state - if (isLoaded && !wasLoaded) { + if (isLoaded && !wasLoaded && userConfig.value.collapseLogGroupsByDefault) { const isFinished = step.value && !['running', 'pending', 'started'].includes(step.value.state); if (isFinished) { // Wait for groupedLogs computed property to update diff --git a/web/src/compositions/useUserConfig.ts b/web/src/compositions/useUserConfig.ts index e9019aa5443..fcf6a406fba 100644 --- a/web/src/compositions/useUserConfig.ts +++ b/web/src/compositions/useUserConfig.ts @@ -4,12 +4,19 @@ import { computed } from 'vue'; interface UserConfig { isPipelineFeedOpen: boolean; redirectUrl: string; + collapseLogGroupsByDefault: boolean; } -const config = useStorage('woodpecker:user-config', { - isPipelineFeedOpen: false, - redirectUrl: '', -}); +const config = useStorage( + 'woodpecker:user-config', + { + isPipelineFeedOpen: false, + redirectUrl: '', + collapseLogGroupsByDefault: true, + }, + undefined, + { mergeDefaults: true }, +); export default () => ({ setUserConfig(key: T, value: UserConfig[T]): void { diff --git a/web/src/views/user/UserGeneral.vue b/web/src/views/user/UserGeneral.vue index 608456ff129..346e0948ef5 100644 --- a/web/src/views/user/UserGeneral.vue +++ b/web/src/views/user/UserGeneral.vue @@ -29,6 +29,14 @@ ]" /> + + + + @@ -38,15 +46,27 @@ import { SUPPORTED_LOCALES } from 'virtual:vue-i18n-supported-locales'; import { computed } from 'vue'; import { useI18n } from 'vue-i18n'; +import Checkbox from '~/components/form/Checkbox.vue'; import InputField from '~/components/form/InputField.vue'; import SelectField from '~/components/form/SelectField.vue'; import Settings from '~/components/layout/Settings.vue'; import { setI18nLanguage } from '~/compositions/useI18n'; import { useTheme } from '~/compositions/useTheme'; +import useUserConfig from '~/compositions/useUserConfig'; import { useWPTitle } from '~/compositions/useWPTitle'; const { locale, t } = useI18n(); const { storeTheme } = useTheme(); +const { userConfig, setUserConfig } = useUserConfig(); + +const collapseLogGroupsByDefault = computed({ + get() { + return userConfig.value.collapseLogGroupsByDefault; + }, + set(value) { + setUserConfig('collapseLogGroupsByDefault', value); + }, +}); const localeOptions = computed(() => SUPPORTED_LOCALES.map((supportedLocale) => ({