From 618beb12e12594c45a43ade144b9943e54f31111 Mon Sep 17 00:00:00 2001 From: Alan Greene Date: Thu, 16 Feb 2023 17:03:03 +0000 Subject: [PATCH] Add YAML mode for Create TaskRun Similar to Create PipelineRun, add a button to the Create TaskRun page allowing the user to switch to YAML mode for more advanced use cases not currently supported by the form-based UI. Also add the 'Edit and run' action on the TaskRuns page allowing users to create a new TaskRun based on an existing one. --- src/api/pipelineRuns.js | 7 +- src/api/taskRuns.js | 90 ++++++-- src/api/taskRuns.test.js | 210 +++++++++++++++++- src/api/utils.js | 20 ++ src/api/utils.test.js | 41 +++- .../CreatePipelineRun/CreatePipelineRun.js | 13 +- src/containers/CreateTaskRun/CreateTaskRun.js | 131 ++++++++++- src/containers/TaskRun/TaskRun.js | 16 ++ src/containers/TaskRuns/TaskRuns.js | 16 ++ src/containers/YAMLEditor/YAMLEditor.js | 4 +- src/nls/messages_de.json | 4 +- src/nls/messages_en.json | 4 +- src/nls/messages_es.json | 4 +- src/nls/messages_fr.json | 4 +- src/nls/messages_it.json | 4 +- src/nls/messages_ja.json | 4 +- src/nls/messages_ko.json | 4 +- src/nls/messages_pt.json | 4 +- src/nls/messages_zh-Hans.json | 4 +- src/nls/messages_zh-Hant.json | 4 +- 20 files changed, 535 insertions(+), 53 deletions(-) diff --git a/src/api/pipelineRuns.js b/src/api/pipelineRuns.js index 301a13581..135730988 100644 --- a/src/api/pipelineRuns.js +++ b/src/api/pipelineRuns.js @@ -19,6 +19,7 @@ import { getQueryParams, getTektonAPI, getTektonPipelinesAPIVersion, + removeSystemLabels, useCollection, useResource } from './utils'; @@ -197,11 +198,7 @@ export function generateNewPipelineRunPayload({ pipelineRun, rerun }) { payload.metadata.labels['dashboard.tekton.dev/rerunOf'] = name; } - Object.keys(payload.metadata.labels).forEach(label => { - if (label.startsWith('tekton.dev/')) { - delete payload.metadata.labels[label]; - } - }); + removeSystemLabels(payload); /* This is used by Tekton Pipelines as part of the conversion between v1beta1 diff --git a/src/api/taskRuns.js b/src/api/taskRuns.js index 9016b045d..41a5cd28b 100644 --- a/src/api/taskRuns.js +++ b/src/api/taskRuns.js @@ -19,6 +19,8 @@ import { getQueryParams, getTektonAPI, getTektonPipelinesAPIVersion, + removeSystemAnnotations, + removeSystemLabels, useCollection, useResource } from './utils'; @@ -76,7 +78,7 @@ export function cancelTaskRun({ name, namespace }) { return patch(uri, payload); } -export function createTaskRun({ +export function getTaskRunPayload({ kind, labels, namespace, @@ -84,7 +86,7 @@ export function createTaskRun({ params, serviceAccount, taskName, - taskRunName = `${taskName}-run-${Date.now()}`, + taskRunName = `${taskName ? `${taskName}-run` : 'run'}-${Date.now()}`, timeout }) { const payload = { @@ -92,19 +94,17 @@ export function createTaskRun({ kind: 'TaskRun', metadata: { name: taskRunName, - namespace, - labels + namespace }, spec: { - params: [], taskRef: { name: taskName, kind: kind || 'Task' } } }; - if (nodeSelector) { - payload.spec.podTemplate = { nodeSelector }; + if (labels) { + payload.metadata.labels = labels; } if (params) { payload.spec.params = Object.keys(params).map(name => ({ @@ -112,37 +112,95 @@ export function createTaskRun({ value: params[name] })); } + if (nodeSelector) { + payload.spec.podTemplate = { nodeSelector }; + } if (serviceAccount) { payload.spec.serviceAccountName = serviceAccount; } if (timeout) { payload.spec.timeout = timeout; } + + return payload; +} + +export function createTaskRun({ + kind, + labels, + namespace, + nodeSelector, + params, + serviceAccount, + taskName, + taskRunName = `${taskName}-run-${Date.now()}`, + timeout +}) { + const payload = getTaskRunPayload({ + kind, + labels, + namespace, + nodeSelector, + params, + serviceAccount, + taskName, + taskRunName, + timeout + }); const uri = getTektonAPI('taskruns', { namespace }); return post(uri, payload).then(({ body }) => body); } -export function rerunTaskRun(taskRun) { - const { annotations, labels, name, namespace } = taskRun.metadata; +export function createTaskRunRaw({ namespace, payload }) { + const uri = getTektonAPI('taskruns', { namespace }); + return post(uri, payload).then(({ body }) => body); +} + +export function generateNewTaskRunPayload({ taskRun, rerun }) { + const { annotations, labels, name, namespace, generateName } = + taskRun.metadata; const payload = deepClone(taskRun); payload.apiVersion = payload.apiVersion || `tekton.dev/${getTektonPipelinesAPIVersion()}`; payload.kind = payload.kind || 'TaskRun'; + + function getGenerateName() { + if (rerun) { + return getGenerateNamePrefixForRerun(name); + } + + return generateName || `${name}-`; + } + payload.metadata = { - annotations, - generateName: getGenerateNamePrefixForRerun(name), - labels: { - ...labels, - 'dashboard.tekton.dev/rerunOf': name - }, + annotations: annotations || {}, + generateName: getGenerateName(), + labels: labels || {}, namespace }; + if (rerun) { + payload.metadata.labels['dashboard.tekton.dev/rerunOf'] = name; + } - delete payload.metadata.labels['tekton.dev/task']; + removeSystemAnnotations(payload); + removeSystemLabels(payload); + + Object.keys(payload.metadata).forEach( + i => payload.metadata[i] === undefined && delete payload.metadata[i] + ); delete payload.status; + delete payload.spec?.status; + return { namespace, payload }; +} + +export function rerunTaskRun(taskRun) { + const { namespace, payload } = generateNewTaskRunPayload({ + taskRun, + rerun: true + }); const uri = getTektonAPI('taskruns', { namespace }); return post(uri, payload).then(({ body }) => body); diff --git a/src/api/taskRuns.test.js b/src/api/taskRuns.test.js index 2bcc8ad8c..c2a3bb814 100644 --- a/src/api/taskRuns.test.js +++ b/src/api/taskRuns.test.js @@ -11,6 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import yaml from 'js-yaml'; import * as API from './taskRuns'; import * as utils from './utils'; import * as comms from './comms'; @@ -158,6 +159,36 @@ describe('createTaskRun', () => { }); }); +it('createTaskRunRaw', () => { + const taskRunRaw = { + apiVersion: 'tekton.dev/v1beta1', + kind: 'TaskRun', + metadata: { name: 'test-task-run-name', namespace: 'test-namespace' }, + spec: { + taskSpec: { + steps: [ + { + image: 'busybox', + name: 'echo', + script: '#!/bin/ash\necho "Hello World!"\n' + } + ] + } + } + }; + jest + .spyOn(comms, 'post') + .mockImplementation((uri, body) => Promise.resolve(body)); + + return API.createTaskRunRaw({ + namespace: 'test-namespace', + payload: taskRunRaw + }).then(() => { + expect(comms.post).toHaveBeenCalled(); + expect(comms.post.mock.lastCall[1]).toEqual(taskRunRaw); + }); +}); + it('deleteTaskRun', () => { const name = 'foo'; const data = { fake: 'taskRun' }; @@ -254,7 +285,7 @@ it('rerunTaskRun', () => { apiVersion: 'tekton.dev/v1beta1', kind: 'TaskRun', metadata: { - annotations: undefined, + annotations: {}, generateName: `${originalTaskRun.metadata.name}-r-`, labels: { 'dashboard.tekton.dev/rerunOf': originalTaskRun.metadata.name @@ -269,3 +300,180 @@ it('rerunTaskRun', () => { expect(comms.post.mock.lastCall[1]).toEqual(rerun); }); }); + +describe('generateNewTaskRunPayload', () => { + it('rerun with minimum possible fields', () => { + const taskRun = { + apiVersion: 'tekton.dev/v1beta1', + kind: 'TaskRun', + metadata: { + name: 'test', + namespace: 'test-namespace' + }, + spec: { + taskRef: { + name: 'simple' + } + } + }; + const { namespace, payload } = API.generateNewTaskRunPayload({ + taskRun, + rerun: true + }); + const expected = `apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + annotations: {} + generateName: test-r- + labels: + dashboard.tekton.dev/rerunOf: test + namespace: test-namespace +spec: + taskRef: + name: simple +`; + expect(namespace).toEqual('test-namespace'); + expect(yaml.dump(payload)).toEqual(expected); + }); + + it('rerun with all processed fields', () => { + const taskRun = { + apiVersion: 'tekton.dev/v1beta1', + kind: 'TaskRun', + metadata: { + name: 'test', + namespace: 'test-namespace', + annotations: { + keya: 'valuea', + 'kubectl.kubernetes.io/last-applied-configuration': + '{"apiVersion": "tekton.dev/v1beta1", "keya": "valuea"}' + }, + labels: { + key1: 'valuel', + key2: 'value2', + 'tekton.dev/task': 'foo' + }, + uid: '111-233-33', + resourceVersion: 'aaaa' + }, + spec: { + taskRef: { + name: 'simple' + }, + params: [{ name: 'param-1' }, { name: 'param-2' }] + }, + status: { startTime: '0' } + }; + const { namespace, payload } = API.generateNewTaskRunPayload({ + taskRun, + rerun: true + }); + const expected = `apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + annotations: + keya: valuea + generateName: test-r- + labels: + key1: valuel + key2: value2 + dashboard.tekton.dev/rerunOf: test + namespace: test-namespace +spec: + taskRef: + name: simple + params: + - name: param-1 + - name: param-2 +`; + expect(namespace).toEqual('test-namespace'); + expect(yaml.dump(payload)).toEqual(expected); + }); + + it('edit with minimum possible fields', () => { + const taskRun = { + apiVersion: 'tekton.dev/v1beta1', + kind: 'TaskRun', + metadata: { + name: 'test', + namespace: 'test-namespace' + }, + spec: { + taskRef: { + name: 'simple' + } + } + }; + const { namespace, payload } = API.generateNewTaskRunPayload({ + taskRun, + rerun: false + }); + const expected = `apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + annotations: {} + generateName: test- + labels: {} + namespace: test-namespace +spec: + taskRef: + name: simple +`; + expect(namespace).toEqual('test-namespace'); + expect(yaml.dump(payload)).toEqual(expected); + }); + + it('edit with all processed fields', () => { + const taskRun = { + apiVersion: 'tekton.dev/v1beta1', + kind: 'TaskRun', + metadata: { + annotations: { + keya: 'valuea', + 'kubectl.kubernetes.io/last-applied-configuration': + '{"apiVersion": "tekton.dev/v1beta1", "keya": "valuea"}' + }, + labels: { + key1: 'valuel', + key2: 'value2', + 'tekton.dev/task': 'foo', + 'tekton.dev/run': 'bar' + }, + name: 'test', + namespace: 'test-namespace', + uid: '111-233-33', + resourceVersion: 'aaaa' + }, + spec: { + taskRef: { + name: 'simple' + }, + params: [{ name: 'param-1' }, { name: 'param-2' }] + }, + status: { startTime: '0' } + }; + const { namespace, payload } = API.generateNewTaskRunPayload({ + taskRun, + rerun: false + }); + const expected = `apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + annotations: + keya: valuea + generateName: test- + labels: + key1: valuel + key2: value2 + namespace: test-namespace +spec: + taskRef: + name: simple + params: + - name: param-1 + - name: param-2 +`; + expect(namespace).toEqual('test-namespace'); + expect(yaml.dump(payload)).toEqual(expected); + }); +}); diff --git a/src/api/utils.js b/src/api/utils.js index c8a2bbca5..bc3ef8790 100644 --- a/src/api/utils.js +++ b/src/api/utils.js @@ -324,3 +324,23 @@ export function isLogTimestampsEnabled() { export function setLogTimestampsEnabled(enabled) { localStorage.setItem('tkn-logs-timestamps', enabled); } + +export function removeSystemAnnotations(resource) { + Object.keys(resource.metadata.annotations).forEach(annotation => { + if (annotation.startsWith('tekton.dev/')) { + delete resource.metadata.annotations[annotation]; // eslint-disable-line no-param-reassign + } + }); + + delete resource.metadata.annotations[ // eslint-disable-line no-param-reassign + 'kubectl.kubernetes.io/last-applied-configuration' + ]; +} + +export function removeSystemLabels(resource) { + Object.keys(resource.metadata.labels).forEach(label => { + if (label.startsWith('tekton.dev/')) { + delete resource.metadata.labels[label]; // eslint-disable-line no-param-reassign + } + }); +} diff --git a/src/api/utils.test.js b/src/api/utils.test.js index 6d56e310b..1b298c596 100644 --- a/src/api/utils.test.js +++ b/src/api/utils.test.js @@ -1,5 +1,5 @@ /* -Copyright 2019-2022 The Tekton Authors +Copyright 2019-2023 The Tekton Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -17,6 +17,8 @@ import * as comms from './comms'; import * as utils from './utils'; import { getQueryParams, + removeSystemAnnotations, + removeSystemLabels, useCollection, useResource, useWebSocket @@ -480,3 +482,40 @@ describe('setLogTimestampsEnabled', () => { expect(localStorage.getItem('tkn-logs-timestamps')).toEqual('false'); }); }); + +it('removeSystemAnnotations', () => { + const customAnnotation = 'myCustomAnnotation'; + const kubectlAnnotation = 'kubectl.kubernetes.io/last-applied-configuration'; + const tektonAnnotation = 'tekton.dev/foo'; + const resource = { + metadata: { + annotations: { + [tektonAnnotation]: 'true', + [customAnnotation]: 'true', + [kubectlAnnotation]: 'true' + } + } + }; + removeSystemAnnotations(resource); + + expect(resource.metadata.annotations[customAnnotation]).toBeDefined(); + expect(resource.metadata.annotations[tektonAnnotation]).toBeUndefined(); + expect(resource.metadata.annotations[kubectlAnnotation]).toBeUndefined(); +}); + +it('removeSystemLabels', () => { + const customLabel = 'myCustomLabel'; + const tektonLabel = 'tekton.dev/foo'; + const resource = { + metadata: { + labels: { + [tektonLabel]: 'true', + [customLabel]: 'true' + } + } + }; + removeSystemLabels(resource); + + expect(resource.metadata.labels[customLabel]).toBeDefined(); + expect(resource.metadata.labels[tektonLabel]).toBeUndefined(); +}); diff --git a/src/containers/CreatePipelineRun/CreatePipelineRun.js b/src/containers/CreatePipelineRun/CreatePipelineRun.js index f336fa2a4..f40395570 100644 --- a/src/containers/CreatePipelineRun/CreatePipelineRun.js +++ b/src/containers/CreatePipelineRun/CreatePipelineRun.js @@ -469,10 +469,13 @@ function CreatePipelineRun() { }); payloadYaml = yaml.dump(payload); } - const loadingMessage = intl.formatMessage({ - id: 'dashboard.pipelineRun.loading', - defaultMessage: 'Loading PipelineRun…' - }); + const loadingMessage = intl.formatMessage( + { + id: 'dashboard.loading.resource', + defaultMessage: 'Loading {kind}…' + }, + { kind: 'PipelineRun' } + ); return ( {intl.formatMessage({ - id: 'dashboard.createPipelineRun.yamlModeButton', + id: 'dashboard.create.yamlModeButton', defaultMessage: 'YAML Mode' })} diff --git a/src/containers/CreateTaskRun/CreateTaskRun.js b/src/containers/CreateTaskRun/CreateTaskRun.js index f3b5719e8..65040d089 100644 --- a/src/containers/CreateTaskRun/CreateTaskRun.js +++ b/src/containers/CreateTaskRun/CreateTaskRun.js @@ -15,6 +15,7 @@ limitations under the License. import React, { useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom-v5-compat'; import keyBy from 'lodash.keyby'; +import yaml from 'js-yaml'; import { Button, Dropdown, @@ -37,9 +38,18 @@ import { ClusterTasksDropdown, NamespacesDropdown, ServiceAccountsDropdown, - TasksDropdown + TasksDropdown, + YAMLEditor } from '..'; -import { createTaskRun, useSelectedNamespace, useTaskByKind } from '../../api'; +import { + createTaskRun, + createTaskRunRaw, + generateNewTaskRunPayload, + getTaskRunPayload, + useSelectedNamespace, + useTaskByKind, + useTaskRun +} from '../../api'; import { isValidLabel } from '../../utils'; const clusterTaskItem = { id: 'clustertask', text: 'ClusterTask' }; @@ -90,6 +100,11 @@ function CreateTaskRun() { }; } + function getTaskRunName() { + const urlSearchParams = new URLSearchParams(location.search); + return urlSearchParams.get('taskRunName') || ''; + } + function getNamespace() { const urlSearchParams = new URLSearchParams(location.search); return ( @@ -98,6 +113,11 @@ function CreateTaskRun() { ); } + function isYAMLMode() { + const urlSearchParams = new URLSearchParams(location.search); + return urlSearchParams.get('mode') === 'yaml'; + } + const { kind: initialTaskKind, taskName: taskRefFromDetails } = getTaskDetails(); const [ @@ -141,8 +161,15 @@ function CreateTaskRun() { }) }); + function switchToYamlMode() { + const queryParams = new URLSearchParams(location.search); + queryParams.set('mode', 'yaml'); + const browserURL = location.pathname.concat(`?${queryParams.toString()}`); + navigate(browserURL); + } + function checkFormValidation() { - // Namespace, PipelineRef, and Params must all have values + // Namespace, taskRef, and Params must all have values const validNamespace = !!namespace; const validTaskRef = !!taskRef; @@ -275,6 +302,24 @@ function CreateTaskRun() { }); } + function handleCloseYAMLEditor() { + let url = urls.taskRuns.all(); + if (defaultNamespace && defaultNamespace !== ALL_NAMESPACES) { + url = urls.taskRuns.byNamespace({ namespace: defaultNamespace }); + } + navigate(url); + } + + function handleCreate({ resource }) { + const resourceNamespace = resource?.metadata?.namespace; + return createTaskRunRaw({ + namespace: resourceNamespace, + payload: resource + }).then(() => { + navigate(urls.taskRuns.byNamespace({ namespace: resourceNamespace })); + }); + } + function handleNamespaceChange({ selectedItem }) { const { text = '' } = selectedItem || {}; if (text !== namespace) { @@ -405,6 +450,74 @@ function CreateTaskRun() { }); } + if (isYAMLMode()) { + const externalTaskRunName = getTaskRunName(); + if (externalTaskRunName) { + const { data: taskRunObject, isLoading } = useTaskRun( + { + name: externalTaskRunName, + namespace: getNamespace() + }, + { disableWebSocket: true } + ); + let payloadYaml = null; + if (taskRunObject) { + const { payload } = generateNewTaskRunPayload({ + taskRun: taskRunObject, + rerun: false + }); + payloadYaml = yaml.dump(payload); + } + const loadingMessage = intl.formatMessage( + { + id: 'dashboard.loading.resource', + defaultMessage: 'Loading {kind}…' + }, + { kind: 'TaskRun' } + ); + + return ( + + ); + } + + const taskRun = getTaskRunPayload({ + kind, + labels: labels.reduce((acc, { key, value }) => { + acc[key] = value; + return acc; + }, {}), + namespace, + nodeSelector: nodeSelector.length + ? nodeSelector.reduce((acc, { key, value }) => { + acc[key] = value; + return acc; + }, {}) + : null, + params, + serviceAccount, + taskName: taskRef, + taskRunName: taskRunName || undefined, + timeout + }); + + return ( + + ); + } + return (
@@ -414,6 +527,18 @@ function CreateTaskRun() { defaultMessage: 'Create TaskRun' })} +
+ +
{taskError && ( diff --git a/src/containers/TaskRun/TaskRun.js b/src/containers/TaskRun/TaskRun.js index fc6852d6a..4729bd036 100644 --- a/src/containers/TaskRun/TaskRun.js +++ b/src/containers/TaskRun/TaskRun.js @@ -256,6 +256,14 @@ export function TaskRunContainer() { }); } + function editAndRun() { + navigate( + `${urls.taskRuns.create()}?mode=yaml&taskRunName=${ + taskRun.metadata.name + }&namespace=${taskRun.metadata.namespace}` + ); + } + function taskRunActions() { if (isReadOnly) { return []; @@ -269,6 +277,14 @@ export function TaskRunContainer() { }), disable: resource => !!resource.metadata.labels?.['tekton.dev/pipeline'] }, + { + action: editAndRun, + actionText: intl.formatMessage({ + id: 'dashboard.editAndRun.actionText', + defaultMessage: 'Edit and run' + }), + disable: resource => !!resource.metadata.labels?.['tekton.dev/pipeline'] + }, { actionText: intl.formatMessage({ id: 'dashboard.cancelTaskRun.actionText', diff --git a/src/containers/TaskRuns/TaskRuns.js b/src/containers/TaskRuns/TaskRuns.js index c9c4ed078..f9d8b5c5d 100644 --- a/src/containers/TaskRuns/TaskRuns.js +++ b/src/containers/TaskRuns/TaskRuns.js @@ -165,6 +165,14 @@ function TaskRuns() { setCancelSelection(() => handleCancelSelection); } + function editAndRun(taskRun) { + navigate( + `${urls.taskRuns.create()}?mode=yaml&taskRunName=${ + taskRun.metadata.name + }&namespace=${taskRun.metadata.namespace}` + ); + } + function taskRunActions() { if (isReadOnly) { return []; @@ -178,6 +186,14 @@ function TaskRuns() { }), disable: resource => !!resource.metadata.labels?.['tekton.dev/pipeline'] }, + { + actionText: intl.formatMessage({ + id: 'dashboard.editAndRun.actionText', + defaultMessage: 'Edit and run' + }), + action: editAndRun, + disable: resource => !!resource.metadata.labels?.['tekton.dev/pipeline'] + }, { actionText: intl.formatMessage({ id: 'dashboard.cancelTaskRun.actionText', diff --git a/src/containers/YAMLEditor/YAMLEditor.js b/src/containers/YAMLEditor/YAMLEditor.js index bc76be7e1..a81c20e00 100644 --- a/src/containers/YAMLEditor/YAMLEditor.js +++ b/src/containers/YAMLEditor/YAMLEditor.js @@ -58,7 +58,7 @@ export default function YAMLEditor({ return null; } - function validateEmptyYaml() { + function validateEmptyYAML() { if (!code) { return { valid: false, @@ -74,7 +74,7 @@ export default function YAMLEditor({ function handleSubmit(event) { event.preventDefault(); // Check form validation - let validationResult = validateEmptyYaml(); + let validationResult = validateEmptyYAML(); if (validationResult && !validationResult.valid) { setValidationErrorMessage(validationResult.message); return; diff --git a/src/nls/messages_de.json b/src/nls/messages_de.json index ce3b5fa37..1842137d2 100644 --- a/src/nls/messages_de.json +++ b/src/nls/messages_de.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "Aktionen", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "Fehler beim Laden von PipelineRun", "dashboard.pipelineRun.failed": "PipelineRun kann nicht geladen werden", "dashboard.pipelineRun.failedMessage": "Details der PipelineRun können nicht geladen werden: {reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "Keine Protokollausgabe", "dashboard.pipelineRun.logFailed": "Das Protokoll kann nicht abgerufen werden", "dashboard.pipelineRun.notFound": "PipelineRun nicht gefunden", diff --git a/src/nls/messages_en.json b/src/nls/messages_en.json index 241b73446..cd31fe815 100644 --- a/src/nls/messages_en.json +++ b/src/nls/messages_en.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "No ClusterTasks found", "dashboard.clusterTasksDropdown.label": "Select ClusterTask", "dashboard.clusterTriggerBinding.noParams": "No parameters found for this ClusterTriggerBinding.", + "dashboard.create.yamlModeButton": "YAML Mode", "dashboard.createPipelineRun.createError": "Error creating PipelineRun", "dashboard.createPipelineRun.disabled": "Disabled", "dashboard.createPipelineRun.enabled": "Enabled", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "Ensure the selected ServiceAccount (or the default if none selected) has permissions for creating PipelineRuns and for anything else your PipelineRun interacts with.", "dashboard.createPipelineRun.status.pending": "Create PipelineRun in pending state", "dashboard.createPipelineRun.title": "Create PipelineRun", - "dashboard.createPipelineRun.yamlModeButton": "YAML Mode", "dashboard.createResource.nameError": "Must consist of lower case alphanumeric characters, '-' or '.', start and end with an alphanumeric character, and be at most 63 characters", "dashboard.createRun.invalidNamespace": "Namespace cannot be empty", "dashboard.createRun.invalidParams": "Params cannot be empty", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "Actions", "dashboard.loading": "Loading…", "dashboard.loading.config": "Loading configuration…", + "dashboard.loading.resource": "Loading {kind}…", "dashboard.logo.alt": "Tekton logo", "dashboard.logo.tooltip": "Meow", "dashboard.logs.downloadButtonTooltip": "Download logs", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "Error loading PipelineRun", "dashboard.pipelineRun.failed": "Cannot load PipelineRun", "dashboard.pipelineRun.failedMessage": "Unable to load PipelineRun: {reason}", - "dashboard.pipelineRun.loading": "Loading PipelineRun…", "dashboard.pipelineRun.logEmpty": "No log available", "dashboard.pipelineRun.logFailed": "Unable to fetch log", "dashboard.pipelineRun.notFound": "PipelineRun not found", diff --git a/src/nls/messages_es.json b/src/nls/messages_es.json index 3a7a51344..e048d42fb 100644 --- a/src/nls/messages_es.json +++ b/src/nls/messages_es.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "Acciones", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "Error al cargar PipelineRun", "dashboard.pipelineRun.failed": "No se puede cargar PipelineRun", "dashboard.pipelineRun.failedMessage": "No se han podido cargar los detalles de PipelineRun: {reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "No hay salida de registros", "dashboard.pipelineRun.logFailed": "No se puede recuperar el registro", "dashboard.pipelineRun.notFound": "No se ha encontrado PipelineRun", diff --git a/src/nls/messages_fr.json b/src/nls/messages_fr.json index eb20fa9fb..d673d65d2 100644 --- a/src/nls/messages_fr.json +++ b/src/nls/messages_fr.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "Actions", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "Une erreur s'est produite lors du chargement de PipelineRun", "dashboard.pipelineRun.failed": "Impossible de charger PipelineRun", "dashboard.pipelineRun.failedMessage": "Impossible de charger les détails de PipelineRun : {reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "Aucune sortie de journal", "dashboard.pipelineRun.logFailed": "Impossible d'extraire le journal", "dashboard.pipelineRun.notFound": "PipelineRun introuvable", diff --git a/src/nls/messages_it.json b/src/nls/messages_it.json index 2d91107b3..0fa25473a 100644 --- a/src/nls/messages_it.json +++ b/src/nls/messages_it.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "Azioni", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "Errore nel caricamento dell'esecuzione pipeline", "dashboard.pipelineRun.failed": "Impossibile caricare l'esecuzione pipeline", "dashboard.pipelineRun.failedMessage": "Impossibile caricare i dettagli dell'esecuzione pipeline: {reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "Nessun output di log", "dashboard.pipelineRun.logFailed": "Impossibile richiamare il log", "dashboard.pipelineRun.notFound": "Esecuzione pipeline non trovata", diff --git a/src/nls/messages_ja.json b/src/nls/messages_ja.json index 9888e5dd2..8efc6c641 100644 --- a/src/nls/messages_ja.json +++ b/src/nls/messages_ja.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "ClusterTaskが見つかりません", "dashboard.clusterTasksDropdown.label": "ClusterTaskを選択", "dashboard.clusterTriggerBinding.noParams": "このClusterTriggerBindingのパラメータが見つかりません", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "PipelineRunの作成中にエラーが発生しました", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "選択したServiceAccount(選択していない場合はデフォルト)に、PipelineRunの作成およびPipelineRunに関するリソースに対する権限があることを確認してください。", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "PipelineRunを作成", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "小文字英数字およびハイフン(64文字未満)", "dashboard.createRun.invalidNamespace": "Namespaceは必須です", "dashboard.createRun.invalidParams": "パラメータは必須です", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "アクション", "dashboard.loading": "読み込み中…", "dashboard.loading.config": "構成をロード中…", + "dashboard.loading.resource": "", "dashboard.logo.alt": "Tektonロゴ", "dashboard.logo.tooltip": "ニャー", "dashboard.logs.downloadButtonTooltip": "ログをダウンロード", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "PipelineRunのロード中にエラーが発生しました", "dashboard.pipelineRun.failed": "PipelineRunをロードできません", "dashboard.pipelineRun.failedMessage": "PipelineRunをロードできません:{reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "ログがありません", "dashboard.pipelineRun.logFailed": "ログを取得できません", "dashboard.pipelineRun.notFound": "PipelineRunが見つかりません", diff --git a/src/nls/messages_ko.json b/src/nls/messages_ko.json index 9c27240f5..287640b26 100644 --- a/src/nls/messages_ko.json +++ b/src/nls/messages_ko.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "조치", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "PipelineRun 로드 중 오류 발생", "dashboard.pipelineRun.failed": "PipelineRun을 로드할 수 없음", "dashboard.pipelineRun.failedMessage": "PipelineRun 세부사항을 로드할 수 없습니다. {reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "로그 출력이 없음", "dashboard.pipelineRun.logFailed": "로그를 페치할 수 없음", "dashboard.pipelineRun.notFound": "PipelineRun을 찾을 수 없음", diff --git a/src/nls/messages_pt.json b/src/nls/messages_pt.json index 20ad39c19..e9051386f 100644 --- a/src/nls/messages_pt.json +++ b/src/nls/messages_pt.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "Ações", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "Erro ao carregar o PipelineRun", "dashboard.pipelineRun.failed": "Não é possível carregar PipelineRun", "dashboard.pipelineRun.failedMessage": "Não é possível carregar detalhes de PipelineRun: {reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "Nenhuma saída de log", "dashboard.pipelineRun.logFailed": "Não é possível buscar o log", "dashboard.pipelineRun.notFound": "PipelineRun não localizado", diff --git a/src/nls/messages_zh-Hans.json b/src/nls/messages_zh-Hans.json index 06bc6f4d6..c6cf963fd 100644 --- a/src/nls/messages_zh-Hans.json +++ b/src/nls/messages_zh-Hans.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "未找到 ClusterTask", "dashboard.clusterTasksDropdown.label": "选择 ClusterTask", "dashboard.clusterTriggerBinding.noParams": "未找到该 ClusterTriggerBinding 的参数。", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "创建 PipelineRun 时失败", "dashboard.createPipelineRun.disabled": "禁用", "dashboard.createPipelineRun.enabled": "启用", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "确保所选的 ServiceAccount(如果没有选择,则为默认值)具有创建 PipelineRun 和与 PipelineRun 交互的任何其他权限。", "dashboard.createPipelineRun.status.pending": "创建处于暂挂状态的 PipelineRun", "dashboard.createPipelineRun.title": "创建 PipelineRun", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "必须少于 64 个字符,且只包含小写字母、数字或 -", "dashboard.createRun.invalidNamespace": "Namespace 不能为空", "dashboard.createRun.invalidParams": "Params 不能为空", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "操作", "dashboard.loading": "加载中", "dashboard.loading.config": "加载配置中", + "dashboard.loading.resource": "", "dashboard.logo.alt": "Tekton 标志", "dashboard.logo.tooltip": "Meow", "dashboard.logs.downloadButtonTooltip": "下载日志", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "加载 PipelineRun 时出错", "dashboard.pipelineRun.failed": "无法加载 PipelineRun", "dashboard.pipelineRun.failedMessage": "无法加载 PipelineRun 详细信息:{reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "没有日志输出", "dashboard.pipelineRun.logFailed": "无法访问日志", "dashboard.pipelineRun.notFound": "未找到 PipelineRun", diff --git a/src/nls/messages_zh-Hant.json b/src/nls/messages_zh-Hant.json index 5b7bd0ce1..2225888dd 100644 --- a/src/nls/messages_zh-Hant.json +++ b/src/nls/messages_zh-Hant.json @@ -49,6 +49,7 @@ "dashboard.clusterTasksDropdown.empty": "", "dashboard.clusterTasksDropdown.label": "", "dashboard.clusterTriggerBinding.noParams": "", + "dashboard.create.yamlModeButton": "", "dashboard.createPipelineRun.createError": "", "dashboard.createPipelineRun.disabled": "", "dashboard.createPipelineRun.enabled": "", @@ -57,7 +58,6 @@ "dashboard.createPipelineRun.serviceAccountHelperText": "", "dashboard.createPipelineRun.status.pending": "", "dashboard.createPipelineRun.title": "", - "dashboard.createPipelineRun.yamlModeButton": "", "dashboard.createResource.nameError": "", "dashboard.createRun.invalidNamespace": "", "dashboard.createRun.invalidParams": "", @@ -143,6 +143,7 @@ "dashboard.list.menu.tooltip": "動作", "dashboard.loading": "", "dashboard.loading.config": "", + "dashboard.loading.resource": "", "dashboard.logo.alt": "", "dashboard.logo.tooltip": "", "dashboard.logs.downloadButtonTooltip": "", @@ -173,7 +174,6 @@ "dashboard.pipelineRun.error": "載入 PipelineRun 時發生錯誤", "dashboard.pipelineRun.failed": "無法載入 PipelineRun", "dashboard.pipelineRun.failedMessage": "無法載入 PipelineRun 詳細資料:{reason}", - "dashboard.pipelineRun.loading": "", "dashboard.pipelineRun.logEmpty": "沒有日誌輸出", "dashboard.pipelineRun.logFailed": "無法提取日誌", "dashboard.pipelineRun.notFound": "找不到 PipelineRun",