Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Modal for adding a pipeline to a collection #1084

Merged
merged 2 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions app/components/collection/modal/add-to-collection/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { createCollectionBody, getCollectionsWithoutPipeline } from './util';

export default class CollectionModalAddToCollectionModalComponent extends Component {
@service shuttle;

@tracked errorMessage;

@tracked newCollectionName = '';

@tracked newCollectionDescription = '';

@tracked selectedCollections = [];

@tracked wasActionSuccessful = false;

@tracked collectionsWithoutPipeline = [];

failedToAddToCollections = [];

constructor() {
super(...arguments);

const collections = this.args.collections || [];

this.collectionsWithoutPipeline = getCollectionsWithoutPipeline(
collections,
this.args.pipeline.id
);
this.errorMessage = this.args.errorMessage;
}

get isSubmitButtonDisabled() {
if (this.isAwaitingResponse) {
return true;
}

return !(
this.newCollectionName.length > 0 || this.selectedCollections.length > 0
);
}

get hasCollections() {
return this.collectionsWithoutPipeline.length > 0;
}

async createCollection() {
if (this.newCollectionName.length > 0) {
await this.shuttle
.fetchFromApi(
'post',
'/collections',
createCollectionBody(
this.newCollectionName,
this.newCollectionDescription,
this.args.pipeline.id
)
)
.then(() => {
this.newCollectionName = '';
this.newCollectionDescription = '';
})
.catch(() => {
this.errorMessage = `Failed to create new collection: ${this.newCollectionName}`;
});
}
}

async addToCollections() {
const promises = [];

if (this.selectedCollections.length > 0) {
this.failedToAddToCollections = [];

this.selectedCollections.forEach(collection => {
promises.push(
this.shuttle
.fetchFromApi('put', `/collections/${collection.id}`, {
pipelineIds: collection.pipelineIds.concat(this.args.pipeline.id)
})
.catch(() => {
this.failedToAddToCollections.push(collection.name);
})
);
});
}

return Promise.all(promises);
}

@action
async submitCollections() {
this.isAwaitingResponse = true;
this.errorMessage = null;

return new Promise(resolve => {
Promise.allSettled([
this.createCollection(),
this.addToCollections()
]).then(() => {
this.isAwaitingResponse = false;

if (this.failedToAddToCollections.length > 0) {
if (this.errorMessage) {
this.errorMessage += `. Also failed to add pipeline to collections: ${this.failedToAddToCollections.join(
', '
)}`;
} else {
this.errorMessage = `Failed to add pipeline to collections: ${this.failedToAddToCollections.join(
', '
)}`;
}
} else {
this.selectedCollections.forEach(collection => {
document.getElementById(
`collection-${collection.id}`
).disabled = true;
});
this.selectedCollections = [];
}
resolve();
});
});
}
}
59 changes: 59 additions & 0 deletions app/components/collection/modal/add-to-collection/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@use 'screwdriver-colors' as colors;
@use 'screwdriver-button' as button;

@mixin styles {
#add-to-collection-modal {
.modal-dialog {
max-width: 50%;

@include button.styles;

.modal-body {
.modal-title {
font-size: 1.75rem;
padding-bottom: 0.75rem;
}

.create-new-collection {
label {
display: flex;
justify-content: space-between;

> div {
margin: auto;
padding-right: 0.25rem;
}

input {
flex: 1;
border-radius: 4px;
border: 1px solid colors.$sd-text-med;
padding-left: 0.5rem;
margin-left: 0.25rem;
}
}
}

.select-collections {
max-height: 10rem;
overflow: scroll;

.btn-group {
display: flex;
flex-direction: column;

> .btn {
border-radius: 3px;
margin: 0.25rem;

&.active {
background-color: rgba(colors.$sd-running, 0.75);
color: colors.$sd-white;
}
}
}
}
}
}
}
}
72 changes: 72 additions & 0 deletions app/components/collection/modal/add-to-collection/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<BsModal
id="add-to-collection-modal"
@onHide={{fn @closeModal}}
as |modal|
>
<modal.body>
{{#if this.errorMessage}}
<InfoMessage
@message={{this.errorMessage}}
@type="warning"
@icon="exclamation-triangle"
/>
{{/if}}
<div class="modal-title">Add to collection(s)</div>
<div class="create-new-collection">
<label>
<div>Collection name:</div>
<Input
id="new-collection-name-input"
@type="text"
@value={{this.newCollectionName}}
placeholder="Please enter a name for your new collection"
/>
</label>
<label>
<div>Collection description:</div>
<Input
@type="text"
@value={{this.newCollectionDescription}}
placeholder="Optional: enter a name description for your new collection"
/>
</label>
</div>

{{#if this.hasCollections}}
<hr />

<div class="select-collections">
<BsButtonGroup
@value={{this.selectedCollections}}
@type="checkbox"
@onChange={{fn (mut this.selectedCollections)}}
as |bg|
>
{{#each this.collectionsWithoutPipeline as |collection|}}
<bg.button
id="collection-{{collection.id}}"
@type="primary"
@outline={{true}}
@value={{collection}}
>
{{collection.name}}
</bg.button>
{{/each}}
</BsButtonGroup>
</div>
{{/if}}

</modal.body>
<modal.footer>
<BsButton
id="submit-collections"
class="confirm"
disabled={{this.isSubmitButtonDisabled}}
@defaultText="Add to collection(s)"
@pendingText="Adding to collection(s)..."
@fulfilledText="Added to collection(s)"
@type="primary"
@onClick={{this.submitCollections}}
/>
</modal.footer>
</BsModal>
26 changes: 26 additions & 0 deletions app/components/collection/modal/add-to-collection/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const getCollectionsWithoutPipeline = (collections, pipelineId) => {
const collectionsWithoutPipeline = [];

collections.forEach(collection => {
if (!collection.pipelineIds.includes(pipelineId)) {
collectionsWithoutPipeline.push(collection);
}
});

collectionsWithoutPipeline.sort((a, b) => a.name.localeCompare(b.name));

return collectionsWithoutPipeline;
};

export const createCollectionBody = (
collectionName,
collectionDescription,
pipelineId
) => {
return {
name: collectionName,
description: collectionDescription,
pipelineIds: [pipelineId],
type: 'normal'
};
};
5 changes: 5 additions & 0 deletions app/components/collection/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@use 'modal/add-to-collection/styles' as modal;

@mixin styles {
@include modal.styles;
}
2 changes: 2 additions & 0 deletions app/components/styles.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@use 'collection/styles' as collection;
@use 'pipeline/styles' as pipeline;

@mixin styles {
@include collection.styles;
@include pipeline.styles;
}
Loading