Skip to content

Commit

Permalink
Feature/collection add and remove entry (#537)
Browse files Browse the repository at this point in the history
* can remove an entry from a collection

* add tool to collection

* ability to edit collection information on the collection page
  • Loading branch information
agduncan94 authored Feb 1, 2019
1 parent 928bc53 commit 13f4e9a
Show file tree
Hide file tree
Showing 28 changed files with 623 additions and 80 deletions.
50 changes: 50 additions & 0 deletions cypress/integration/group3/organizations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,56 @@ describe('Dockstore my workflows', () => {
});
});

describe('should be able to view a collection', () => {
it('be able to see collection information', () => {
cy.visit('/organizations/1/collections/1');
cy.contains('veryFakeCollectionName').click();
// Should retrieve the organisation
cy.contains('Potatoe');

// Should retrieve the collection
cy.contains('veryFakeCollectionName');
cy.contains('very fake collection description');

// Should have no entries
cy.contains('This collection has no associated entries');
});

it('be able to edit collection information', () => {
// Should be able to edit the collection description and see the changes reflected
cy.get('#editCollection').click();
cy.get('#createOrUpdateCollectionButton').should('be.visible').should('not.be.disabled');
typeInInput('Name', 'veryFakeCollectionName');
typeInTextArea('Description', 'very fake collection description2');
cy.get('#createOrUpdateCollectionButton').should('be.visible').should('not.be.disabled').click();
cy.contains('veryFakeCollectionName');
cy.contains('very fake collection description2');
});

it('be able to add an entry to the collection', () => {
cy.visit('/containers/quay.io/garyluu/dockstore-cgpmap/cgpmap-cramOut:3.0.0-rc8?tab=info');
cy.get('#addToolToCollectionButton').should('be.visible').click();
cy.get('#addEntryToCollectionButton').should('be.disabled');
cy.get('#selectOrganization').click();
cy.get('mat-option').contains('Potatoe').click();

cy.get('#addEntryToCollectionButton').should('be.disabled');
cy.get('#selectCollection').click();
cy.get('mat-option').contains('veryFakeCollectionName').click();
cy.get('#addEntryToCollectionButton').should('not.be.disabled').click();
});

it('be able to remove an entry from a collection', () => {
cy.visit('/organizations/1/collections/1');
cy.contains('quay.io/garyluu/dockstore-cgpmap/cgpmap-cramOut');
cy.get('#removeToolButton').click();
cy.get('#accept-remove-entry-from-org').click();
cy.contains('This collection has no associated entries');
cy.visit('/organizations/1');
});
});


describe('Should be able to CRUD user', () => {
beforeEach(() => {
cy.contains('Members').click();
Expand Down
8 changes: 8 additions & 0 deletions src/app/container/container.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,14 @@ <h3>Source Repositories</h3>
</div>
</div>
</div>
<div class="panel panel-default mb-3" *ngIf="isLoggedIn">
<div class="panel-heading">
<h3>Collections</h3>
</div>
<div class="p-3 panel-body">
<button fxFlex mat-raised-button color="default" matTooltip="Add the tool to a collection" (click)="addEntryToCollection()" id="addToolToCollectionButton"><mat-icon>add</mat-icon>Add to collection</button>
</div>
</div>
<app-verified-by *ngIf="selectedVersion" [version]="selectedVersion"></app-verified-by>
<div class="panel panel-default mb-3" *ngIf="tool">
<div class="panel-heading">
Expand Down
11 changes: 9 additions & 2 deletions src/app/container/container.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component } from '@angular/core';
import { MatChipInputEvent } from '@angular/material';
import { MatChipInputEvent, MatDialog } from '@angular/material';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
Expand Down Expand Up @@ -47,6 +47,7 @@ import { EmailService } from './email.service';
import { AlertService } from '../shared/alert/state/alert.service';
import { HttpErrorResponse } from '@angular/common/http';
import { AlertQuery } from '../shared/alert/state/alert.query';
import { AddEntryComponent } from '../organizations/collection/add-entry/add-entry.component';

@Component({
selector: 'app-container',
Expand Down Expand Up @@ -90,7 +91,7 @@ export class ContainerComponent extends Entry {
location: Location,
activatedRoute: ActivatedRoute, protected sessionService: SessionService, protected sessionQuery: SessionQuery,
protected gA4GHFilesService: GA4GHFilesService, private toolQuery: ToolQuery, private alertService: AlertService,
private extendedDockstoreToolQuery: ExtendedDockstoreToolQuery, private alertQuery: AlertQuery) {
private extendedDockstoreToolQuery: ExtendedDockstoreToolQuery, private alertQuery: AlertQuery, public dialog: MatDialog) {
super(trackLoginService, providerService, router, dateService, urlResolverService, activatedRoute,
location, sessionService, sessionQuery, gA4GHFilesService);
this.isRefreshing$ = this.alertQuery.showInfo$;
Expand Down Expand Up @@ -356,4 +357,10 @@ export class ContainerComponent extends Entry {
return true;
}
}

addEntryToCollection() {
this.dialog.open(AddEntryComponent, {
data: { entryId: this.tool.id }, width: '500px'
});
}
}
2 changes: 1 addition & 1 deletion src/app/container/info-tab/info-tab.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div *ngIf="tool">
<mat-card>
<mat-card-header>
<mat-card-title>Workflow Information</mat-card-title>
<mat-card-title>Tool Information</mat-card-title>
</mat-card-header>
<mat-card-content class="p-3">
<ul class="list-unstyled container-info">
Expand Down
21 changes: 17 additions & 4 deletions src/app/organizations/collection.module.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CollectionComponent } from './collection/collection.component';
import { MatCardModule, MatProgressBarModule, MatIconModule, MatChipsModule } from '@angular/material';
import { CollectionComponent, CollectionRemoveEntryDialogComponent } from './collection/collection.component';
import { MatCardModule, MatProgressBarModule, MatIconModule, MatChipsModule, MatButtonModule, MatTooltipModule,
MatDialogModule } from '@angular/material';
import { HeaderModule } from '../shared/modules/header.module';
import { FlexLayoutModule } from '@angular/flex-layout';
import { RouterModule } from '@angular/router';
import { CreateCollectionModule } from './collections/create-collection.module';

@NgModule({
imports: [ CommonModule, HeaderModule,
MatCardModule, MatProgressBarModule, MatIconModule,
FlexLayoutModule, RouterModule, MatChipsModule ],
declarations: [ CollectionComponent ]
FlexLayoutModule, RouterModule, MatChipsModule, MatButtonModule,
MatIconModule, MatTooltipModule, MatDialogModule, CreateCollectionModule ],
declarations: [
CollectionComponent,
CollectionRemoveEntryDialogComponent
],
exports: [
CollectionComponent,
CollectionRemoveEntryDialogComponent
],
entryComponents: [
CollectionRemoveEntryDialogComponent
]
})
export class CollectionModule { }
13 changes: 13 additions & 0 deletions src/app/organizations/collection/add-entry.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AddEntryComponent } from './add-entry/add-entry.component';
import { CustomMaterialModule } from '../../shared/modules/material.module';
import { FlexLayoutModule } from '@angular/flex-layout';
import { RefreshAlertModule } from '../../shared/alert/alert.module';

@NgModule({
imports: [ CommonModule, CustomMaterialModule, FlexLayoutModule, RefreshAlertModule ],
declarations: [ AddEntryComponent ],
entryComponents: [ AddEntryComponent ]
})
export class AddEntryModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<h1 mat-dialog-title>Add to collection</h1>
<div mat-dialog-content>

<ng-template #loading>
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</ng-template>

<div *ngIf="!(isLoading$ | async); else loading">
<div fxLayout="column" fxLayoutGap="15px">
<div fxFlex *ngIf="(memberships$ | async) as memberships">
<ng-template #noMemberships>
<mat-card class="alert alert-info" role="alert">
<mat-icon>info</mat-icon> You must be part of an organization to add to a collection
</mat-card>
</ng-template>
<mat-form-field *ngIf="memberships && memberships.length > 0; else noMemberships">
<mat-select id="selectOrganization" placeholder="Organization" [(value)]="selectedOrganisationId" (selectionChange)="onOrganisationChange($event)">
<mat-option *ngFor="let membership of memberships" [value]="membership.organisation.id">
{{membership.organisation.name}}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<div fxFlex *ngIf="(collections$ | async) as collections">
<ng-template #noCollections>
<mat-card class="alert alert-info" role="alert">
<mat-icon>info</mat-icon> The selected organization has no collections
</mat-card>
</ng-template>
<mat-form-field id="selectCollection" *ngIf="selectedOrganisationId && collections && collections.length > 0; else noCollections">
<mat-select placeholder="Collection" [(value)]="selectedCollectionId" [disabled]="!selectedOrganisationId">
<mat-option *ngFor="let collection of collections" [value]="collection.id">
{{collection.name}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
</div>

<div mat-dialog-actions align="end">
<button mat-button id="closeDialogButton" (click)="closeDialog()">Close</button>
<button mat-flat-button id="addEntryToCollectionButton" color="primary" [disabled]="!selectedOrganisationId || !selectedCollectionId" (click)="addToCollection()">
<mat-icon>add</mat-icon>Add to collection
</button>
</div>
Empty file.
55 changes: 55 additions & 0 deletions src/app/organizations/collection/add-entry/add-entry.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Component, OnInit, Inject } from '@angular/core';
import { AddEntryService } from '../state/add-entry.service';
import { AddEntryQuery } from '../state/add-entry.query';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { Observable } from 'rxjs';
import { OrganisationUser, Collection } from '../../../shared/swagger';

@Component({
selector: 'add-entry',
templateUrl: './add-entry.component.html',
styleUrls: ['./add-entry.component.scss']
})
export class AddEntryComponent implements OnInit {
public memberships$: Observable<Array<OrganisationUser>>;
public collections$: Observable<Array<Collection>>;
isLoading$: Observable<boolean>;
selectedOrganisationId: number;
selectedCollectionId: number;
constructor(private addEntryQuery: AddEntryQuery,
private addEntryService: AddEntryService,
@Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<AddEntryComponent>
) { }

ngOnInit() {
this.isLoading$ = this.addEntryQuery.isLoading$;
this.addEntryService.updateMemberships();
this.memberships$ = this.addEntryQuery.memberships$;
this.collections$ = this.addEntryQuery.collections$;
}

/**
* Called when organisation is selected from dropdown
* @param event event.value is the id of the organisation to add
*/
onOrganisationChange(event) {
this.selectedCollectionId = null;
this.addEntryService.updateCollections(event.value);
this.collections$ = this.addEntryQuery.collections$;
}

/**
* Attempts to add the entry to the selected collection
*/
addToCollection() {
if (this.selectedCollectionId && this.selectedOrganisationId) {
this.addEntryService.addEntryToCollection(this.selectedOrganisationId, this.selectedCollectionId, this.data.entryId);
}
}

closeDialog(): void {
this.dialogRef.close();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<h1 mat-dialog-title>Remove Entry</h1>

<div mat-dialog-content>
<p>Are you sure you want to <strong>remove</strong> the entry <strong>{{data.entryName}}</strong> from the collection <strong>{{data.collectionName}}</strong>?</p>
</div>
<div mat-dialog-actions>
<div fxFlex></div>
<button mat-button (click)="onNoClick()">Cancel</button>
<button mat-flat-button id="accept-remove-entry-from-org" [mat-dialog-close]="{ 'organizationId': data.organizationId, 'collectionId': data.collectionId, 'entryId': data.entryId, 'entryName': data.entryName }">Remove</button>
</div>
Loading

0 comments on commit 13f4e9a

Please sign in to comment.