Skip to content

Commit

Permalink
Improve URL addressability for the create pages
Browse files Browse the repository at this point in the history
Keep the URL in sync with the selected values in the following dropdowns
to provide bookmarkable URLs for commonly executed workloads:
- Namespaces dropdown (common to both PipelineRun and TaskRun)
- Kind dropdown (TaskRun only)
- Pipeline / Task / ClusterTask dropdown

Also update the respective buttons on the PipelineRuns and TaskRuns page
to ensure the namespace is included on the initial URL for consistency.

Add links to 'create' page from Tasks, ClusterTasks, and Pipelines lists

Provide a simple mechanism for users to get to the 'Create' page with
a preselected Task / ClusterTask / Pipeline from the corresponding row
on the list page for that resource type.

A future change may introduce a similar action on the details page for
a single resource's details page.
  • Loading branch information
AlanGreene authored and tekton-robot committed Dec 6, 2021
1 parent 94c0c04 commit be71bf0
Show file tree
Hide file tree
Showing 19 changed files with 242 additions and 92 deletions.
2 changes: 1 addition & 1 deletion packages/components/src/components/Table/Table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ limitations under the License.
.bx--data-table td {
&.cell-actions {
text-align: right;
width: 6rem;
width: 8rem;
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/containers/ClusterTasks/ClusterTasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
import { Button, Link as CarbonLink } from 'carbon-components-react';
import {
TrashCan16 as DeleteIcon,
PlayOutline16 as RunIcon,
Playlist16 as RunsIcon
} from '@carbon/icons-react';
import { getFilters, urls, useTitleSync } from '@tektoncd/dashboard-utils';
Expand Down Expand Up @@ -177,6 +178,28 @@ function ClusterTasksContainer({ intl }) {
tooltipPosition="left"
/>
) : null}
{!isReadOnly ? (
<Button
as={Link}
hasIconOnly
iconDescription={intl.formatMessage(
{
id: 'dashboard.actions.createRunButton',
defaultMessage: 'Create {kind}'
},
{ kind: 'TaskRun' }
)}
kind="ghost"
renderIcon={RunIcon}
size="sm"
to={`${urls.taskRuns.create()}?${new URLSearchParams({
kind: 'ClusterTask',
taskName: clusterTask.metadata.name
}).toString()}`}
tooltipAlignment="center"
tooltipPosition="left"
/>
) : null}
<Button
as={Link}
hasIconOnly
Expand Down
98 changes: 64 additions & 34 deletions src/containers/CreatePipelineRun/CreatePipelineRun.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,21 @@ const initialResourcesState = resourceSpecs => {
function CreatePipelineRun({ intl }) {
const history = useHistory();
const location = useLocation();
const { selectedNamespace: defaultNamespace } = useSelectedNamespace();

function getPipelineName() {
const urlSearchParams = new URLSearchParams(location.search);
return urlSearchParams.get('pipelineName') || '';
}

const { selectedNamespace: defaultNamespace } = useSelectedNamespace();
function getNamespace() {
const urlSearchParams = new URLSearchParams(location.search);
return (
urlSearchParams.get('namespace') ||
(defaultNamespace !== ALL_NAMESPACES ? defaultNamespace : '')
);
}

const [
{
creating,
Expand All @@ -118,8 +126,8 @@ function CreatePipelineRun({ intl }) {
setState
] = useState({
...initialState,
namespace: defaultNamespace !== ALL_NAMESPACES ? defaultNamespace : '',
pipelineRef: getPipelineName() || '',
namespace: getNamespace(),
pipelineRef: getPipelineName(),
params: initialParamsState(null),
resources: initialResourcesState(null)
});
Expand Down Expand Up @@ -237,13 +245,13 @@ function CreatePipelineRun({ intl }) {
function handleClose() {
const pipelineName = getPipelineName();
let url = urls.pipelineRuns.all();
if (pipelineName && defaultNamespace !== ALL_NAMESPACES) {
if (pipelineName && namespace && namespace !== ALL_NAMESPACES) {
url = urls.pipelineRuns.byPipeline({
namespace: defaultNamespace,
namespace,
pipelineName
});
} else if (defaultNamespace !== ALL_NAMESPACES) {
url = urls.pipelineRuns.byNamespace({ namespace: defaultNamespace });
} else if (namespace && namespace !== ALL_NAMESPACES) {
url = urls.pipelineRuns.byNamespace({ namespace });
}
history.push(url);
}
Expand Down Expand Up @@ -309,6 +317,16 @@ function CreatePipelineRun({ intl }) {
...initialState,
namespace: text
}));

const queryParams = new URLSearchParams(location.search);
if (text) {
queryParams.set('namespace', text);
} else {
queryParams.delete('namespace');
}
queryParams.delete('pipelineName');
const browserURL = location.pathname.concat(`?${queryParams.toString()}`);
history.push(browserURL);
}
}

Expand All @@ -324,6 +342,16 @@ function CreatePipelineRun({ intl }) {

function handlePipelineChange({ selectedItem }) {
const { text } = selectedItem || {};

const queryParams = new URLSearchParams(location.search);
if (text) {
queryParams.set('pipelineName', text);
} else {
queryParams.delete('pipelineName');
}
const browserURL = location.pathname.concat(`?${queryParams.toString()}`);
history.push(browserURL);

if (text && text !== pipelineRef) {
setState(state => {
return {
Expand Down Expand Up @@ -416,33 +444,6 @@ function CreatePipelineRun({ intl }) {
defaultMessage: 'Create PipelineRun'
})}
</h1>
<Button
iconDescription={intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
kind="secondary"
onClick={handleClose}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
</Button>
<Button
iconDescription={intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
onClick={handleSubmit}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
</Button>
</div>
<Form>
{pipelineError && (
Expand Down Expand Up @@ -700,6 +701,35 @@ function CreatePipelineRun({ intl }) {
})}
/>
</FormGroup>

<Button
iconDescription={intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
onClick={handleSubmit}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
</Button>

<Button
iconDescription={intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
kind="secondary"
onClick={handleClose}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
</Button>
</Form>
</div>
);
Expand Down
102 changes: 69 additions & 33 deletions src/containers/CreateTaskRun/CreateTaskRun.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const itemToString = ({ text }) => text;
function CreateTaskRun({ intl }) {
const history = useHistory();
const location = useLocation();
const { selectedNamespace: defaultNamespace } = useSelectedNamespace();

function getTaskDetails() {
const urlSearchParams = new URLSearchParams(location.search);
Expand All @@ -112,7 +113,14 @@ function CreateTaskRun({ intl }) {
};
}

const { selectedNamespace: defaultNamespace } = useSelectedNamespace();
function getNamespace() {
const urlSearchParams = new URLSearchParams(location.search);
return (
urlSearchParams.get('namespace') ||
(defaultNamespace !== ALL_NAMESPACES ? defaultNamespace : '')
);
}

const { kind: initialTaskKind, taskName: taskRefFromDetails } =
getTaskDetails();
const [
Expand All @@ -137,7 +145,7 @@ function CreateTaskRun({ intl }) {
] = useState({
...initialState,
kind: initialTaskKind || 'Task',
namespace: defaultNamespace !== ALL_NAMESPACES ? defaultNamespace : '',
namespace: getNamespace(),
taskRef: taskRefFromDetails,
params: initialParamsState(null),
resources: initialResourcesState(null)
Expand Down Expand Up @@ -245,15 +253,15 @@ function CreateTaskRun({ intl }) {
function handleClose() {
const { kind: taskKind, taskName } = getTaskDetails();
let url = urls.taskRuns.all();
if (taskName && defaultNamespace !== ALL_NAMESPACES) {
if (taskName && namespace && namespace !== ALL_NAMESPACES) {
url = urls.taskRuns[
taskKind === 'ClusterTask' ? 'byClusterTask' : 'byTask'
]({
namespace: defaultNamespace,
namespace,
taskName
});
} else if (defaultNamespace !== ALL_NAMESPACES) {
url = urls.taskRuns.byNamespace({ namespace: defaultNamespace });
} else if (namespace && namespace !== ALL_NAMESPACES) {
url = urls.taskRuns.byNamespace({ namespace });
}
history.push(url);
}
Expand Down Expand Up @@ -319,6 +327,16 @@ function CreateTaskRun({ intl }) {
kind: state.kind,
namespace: text
}));

const queryParams = new URLSearchParams(location.search);
if (text) {
queryParams.set('namespace', text);
} else {
queryParams.delete('namespace');
}
queryParams.delete('taskName');
const browserURL = location.pathname.concat(`?${queryParams.toString()}`);
history.push(browserURL);
}
}

Expand All @@ -330,6 +348,13 @@ function CreateTaskRun({ intl }) {
...initialState,
kind: text
}));

const queryParams = new URLSearchParams(location.search);
queryParams.set('kind', text);
queryParams.delete('namespace');
queryParams.delete('taskName');
const browserURL = location.pathname.concat(`?${queryParams.toString()}`);
history.push(browserURL);
}
}

Expand All @@ -345,6 +370,16 @@ function CreateTaskRun({ intl }) {

function handleTaskChange({ selectedItem }) {
const { text } = selectedItem || {};

const queryParams = new URLSearchParams(location.search);
if (text) {
queryParams.set('taskName', text);
} else {
queryParams.delete('taskName');
}
const browserURL = location.pathname.concat(`?${queryParams.toString()}`);
history.push(browserURL);

if (text && text !== taskRef) {
setState(state => {
return {
Expand Down Expand Up @@ -432,33 +467,6 @@ function CreateTaskRun({ intl }) {
defaultMessage: 'Create TaskRun'
})}
</h1>
<Button
iconDescription={intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
kind="secondary"
onClick={handleClose}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
</Button>
<Button
iconDescription={intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
onClick={handleSubmit}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
</Button>
</div>
<Form>
{taskError && (
Expand Down Expand Up @@ -759,6 +767,34 @@ function CreateTaskRun({ intl }) {
}
/>
</FormGroup>

<Button
iconDescription={intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
onClick={handleSubmit}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
})}
</Button>
<Button
iconDescription={intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
kind="secondary"
onClick={handleClose}
disabled={creating}
>
{intl.formatMessage({
id: 'dashboard.modal.cancelButton',
defaultMessage: 'Cancel'
})}
</Button>
</Form>
</div>
);
Expand Down
14 changes: 11 additions & 3 deletions src/containers/PipelineRuns/PipelineRuns.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,19 @@ export function PipelineRuns({ intl }) {
? []
: [
{
onClick: () =>
onClick: () => {
let queryString;
if (namespace !== ALL_NAMESPACES) {
queryString = new URLSearchParams({
namespace,
...(pipelineName && { pipelineName })
}).toString();
}
history.push(
urls.pipelineRuns.create() +
(pipelineName ? `?pipelineName=${pipelineName}` : '')
),
(queryString ? `?${queryString}` : '')
);
},
text: intl.formatMessage({
id: 'dashboard.actions.createButton',
defaultMessage: 'Create'
Expand Down
Loading

0 comments on commit be71bf0

Please sign in to comment.