Skip to content

Commit b4abd13

Browse files
frano-mMillenniumFalconMechanic
authored andcommitted
Handle long values in the Project Label section on the project detail page. Resolves #986. (#988)
1 parent 178b6ef commit b4abd13

File tree

5 files changed

+163
-24
lines changed

5 files changed

+163
-24
lines changed

spa/src/app/files/hca-project/hca-project-mapper.mock.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ export const PROJECT_DETAIL_NULL_VALUES = {
239239
// Example of project detail with specific values,
240240
// sample entity type as "specimens",
241241
// workflow as "Unspecified"
242+
// projectShortname as sentence case e.g. "Healthy and type 2 diabetes pancreas"
242243
export const PROJECT_DETAIL_SPECIFIC_VALUES = {
243244
"ageUnit": "month",
244245
"arrayExpressAccessions": "E-AAAA-00",
@@ -271,7 +272,7 @@ export const PROJECT_DETAIL_SPECIFIC_VALUES = {
271272
"otherCount": 16,
272273
"pairedEnd": "false",
273274
"projectDescription": "Contains a small file set from the dataset: 4k PBMCs from a Healthy Donor, a Single Cell Gene Expression Dataset by Cell Ranger 2.1.0. Peripheral blood mononuclear cells (PBMCs) were taken from a healthy donor (same donor as pbmc8k). PBMCs are primary cells with relatively small amounts of RNA (~1pg RNA/cell). Data/Analysis can be found here https://support.10xgenomics.com/single-cell-gene-expression/datasets/2.1.0/pbmc4k and all data is licensed under the creative commons attribution license (https://creativecommons.org/licenses/by/4.0/). This test also contains extensive metadata for browser testing. Metadata is fabricated.",
274-
"projectShortname": "integration/optimus/2019-09-24T11:02:18Z",
275+
"projectShortname": "Healthy and type 2 diabetes pancreas",
275276
"projectTitle": "Tabula Muris: Transcriptomic characterization of 20 organs and tissues from Mus musculus at single cell resolution",
276277
"publications": [
277278
{

spa/src/app/files/hca-project/hca-project.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ <h4 class="fontsize-m semi-bold">Project Details</h4>
161161
{{getColumnDisplayName('projectShortname')}}
162162
</hca-tooltip>
163163
</p>
164-
<p class="fontsize-xs rhs">{{state.project.project.projectShortname}}</p>
164+
<p [ngClass]="{'fontsize-xxs rhs': true, 'break': !isShortNameSentence(state.project.project.projectShortname)}">{{state.project.project.projectShortname}}</p>
165165
</div>
166166
<div>
167167
<p class="fontsize-xs semi-bold lhs">

spa/src/app/files/hca-project/hca-project.component.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,14 @@
240240
.rhs {
241241
box-sizing: border-box;
242242
width: 100%;
243+
244+
/* Break word */
245+
&.break {
246+
word-break: break-all;
247+
}
243248
}
244249

250+
/* Species matrix url */
245251
.species-matrix-url {
246252
transition: background-color 400ms cubic-bezier(0.25, 0.8, 0.25, 1);
247253
&:hover {
@@ -277,6 +283,7 @@
277283
.rhs {
278284
flex: 1;
279285
max-width: 400px;
286+
min-width: 200px; /* Required for downloads */
280287
padding-left: 16px;
281288
}
282289

spa/src/app/files/hca-project/hca-project.component.spec.ts

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ describe("HCAProjectComponent", () => {
5050
testConfig.getPortalURL.and.returnValue("https://test.com");
5151

5252
// Class names
53+
const CLASSNAME_BREAK = "break";
5354
const CLASSNAME_CITATION = ".citation";
5455
const CLASSNAME_CITATION_URL = ".citation .url";
5556
const CLASSNAME_PROJECT_DETAILS_LHS = ".project-details .lhs";
@@ -190,6 +191,28 @@ describe("HCAProjectComponent", () => {
190191
expect(projectUrl).toEqual(TEST_VALUE_CITATION_URL);
191192
});
192193

194+
/**
195+
* Confirm is short name sentence returns true when project label is sentence case.
196+
*/
197+
it("should is short name sentence returns true when project label is sentence case", () => {
198+
199+
const shortNameSentence = component.isShortNameSentence(PROJECT_DETAIL_SPECIFIC_VALUES.projectShortname);
200+
201+
// Confirm true is returned
202+
expect(shortNameSentence).toEqual(true);
203+
});
204+
205+
/**
206+
* Confirm is short name sentence returns false when project label is not sentence case.
207+
*/
208+
it("should is short name sentence returns false when project label is not sentence case", () => {
209+
210+
const shortNameSentence = component.isShortNameSentence(PROJECT_DETAIL_SINGLE_VALUES.projectShortname);
211+
212+
// Confirm false is returned
213+
expect(shortNameSentence).toEqual(false);
214+
});
215+
193216
/**
194217
* Confirm "Citation" is displayed.
195218
*/
@@ -268,6 +291,67 @@ describe("HCAProjectComponent", () => {
268291
expect(getComponentInputPropertyValue(copyToClipboard, COMPONENT_INPUT_PROPERTY_COPY_TO_CLIPBOARD_LINK)).toEqual(TEST_VALUE_CITATION_URL);
269292
});
270293

294+
/**
295+
* Confirm "Project Label" is displayed.
296+
*/
297+
it(`should display "Project Label"`, () => {
298+
299+
testStore.pipe
300+
.and.returnValues(
301+
of(PROJECT_DETAIL_SINGLE_VALUES), // selected project detail
302+
of(PROJECT_MATRIX_URLS_SINGLE_SPECIES), // project matrix URLs
303+
of([]), // project ids
304+
of([]) // integrations
305+
);
306+
307+
fixture.detectChanges();
308+
309+
// Confirm "Project Label" is displayed
310+
expect(isProjectDetailLabelDisplayed(PROJECT_LABEL_PROJECT_SHORTNAME, CLASSNAME_PROJECT_DETAILS_LHS)).toEqual(true);
311+
});
312+
313+
/**
314+
* Confirm class "break" is not displayed when "projectShortname" is sentence case.
315+
*/
316+
it(`should not display class "break" when "projectShortname" is sentence case`, () => {
317+
318+
testStore.pipe
319+
.and.returnValues(
320+
of(PROJECT_DETAIL_SPECIFIC_VALUES), // selected project detail
321+
of(PROJECT_MATRIX_URLS_SINGLE_SPECIES), // project matrix URLs
322+
of([]), // project ids
323+
of([]) // integrations
324+
);
325+
326+
fixture.detectChanges();
327+
328+
const projectDetailClasses = getProjectDetailClasses(PROJECT_LABEL_PROJECT_SHORTNAME);
329+
330+
// Confirm class is not displayed
331+
expect(projectDetailClasses[CLASSNAME_BREAK]).toEqual(false);
332+
});
333+
334+
/**
335+
* Confirm class "break" is displayed when "projectShortname" is not sentence case.
336+
*/
337+
it(`should display class "break" when "projectShortname" is not sentence case`, () => {
338+
339+
testStore.pipe
340+
.and.returnValues(
341+
of(PROJECT_DETAIL_SINGLE_VALUES), // selected project detail
342+
of(PROJECT_MATRIX_URLS_SINGLE_SPECIES), // project matrix URLs
343+
of([]), // project ids
344+
of([]) // integrations
345+
);
346+
347+
fixture.detectChanges();
348+
349+
const projectDetailClasses = getProjectDetailClasses(PROJECT_LABEL_PROJECT_SHORTNAME);
350+
351+
// Confirm class is displayed
352+
expect(projectDetailClasses[CLASSNAME_BREAK]).toEqual(true);
353+
});
354+
271355
/**
272356
* Confirm "Sample Type" is displayed.
273357
*/
@@ -660,12 +744,12 @@ describe("HCAProjectComponent", () => {
660744
}
661745

662746
/**
663-
* Returns the project detail value for the specified project detail.
747+
* Returns the project detail for the specified project detail label.
664748
*
665749
* @param {string} projectDetailLabel
666-
* @returns {any}
750+
* @returns {DebugElement}
667751
*/
668-
function getProjectDetailValue(projectDetailLabel: string): any {
752+
function getProjectDetail(projectDetailLabel: string): DebugElement {
669753

670754
const projectDetailValueEls = fixture.debugElement.queryAll(By.css(CLASSNAME_PROJECT_DETAILS_RHS));
671755

@@ -676,7 +760,43 @@ describe("HCAProjectComponent", () => {
676760

677761
const projectDetailIndex = PROJECT_DETAIL_DISPLAY_ORDER.indexOf(projectDetailLabel);
678762

679-
return projectDetailValueEls[projectDetailIndex].nativeElement.innerText;
763+
return projectDetailValueEls[projectDetailIndex];
764+
}
765+
766+
/**
767+
* Returns the project detail classes for the specified project detail.
768+
*
769+
* @param {string} projectDetailLabel
770+
* @returns {Object}
771+
*/
772+
function getProjectDetailClasses(projectDetailLabel: string): Object {
773+
774+
const projectDetail = getProjectDetail(projectDetailLabel);
775+
776+
if ( !projectDetail ) {
777+
778+
return;
779+
}
780+
781+
return projectDetail.classes;
782+
}
783+
784+
/**
785+
* Returns the project detail value for the specified project detail.
786+
*
787+
* @param {string} projectDetailLabel
788+
* @returns {any}
789+
*/
790+
function getProjectDetailValue(projectDetailLabel: string): any {
791+
792+
const projectDetail = getProjectDetail(projectDetailLabel);
793+
794+
if ( !projectDetail ) {
795+
796+
return;
797+
}
798+
799+
return projectDetail.nativeElement.innerText;
680800
}
681801

682802

spa/src/app/files/hca-project/hca-project.component.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -176,23 +176,23 @@ export class HCAProjectComponent implements OnDestroy, OnInit {
176176
}
177177

178178
/**
179-
* Returns true if at least one data curator has been specified for this project.
179+
* Returns true if project collaborating organizations exist.
180180
*
181-
* @param {string[]} curators
181+
* @param {CollaboratingOrganizationView[]} collaboratingOrganzations
182182
* @returns {boolean}
183183
*/
184-
public isAnyDataCuratorAssociated(curators: string[]): boolean {
185-
return curators.length > 0;
184+
public isAnyCollaboratingOrganizationAssociated(collaboratingOrganzations: CollaboratingOrganizationView[]): boolean {
185+
return collaboratingOrganzations.length > 0;
186186
}
187187

188188
/**
189-
* Returns true if project collaborating organizations exist.
189+
* Returns true if project contacts exist.
190190
*
191-
* @param {CollaboratingOrganizationView[]} collaboratingOrganzations
191+
* @param {ContactView[]} contacts
192192
* @returns {boolean}
193193
*/
194-
public isAnyCollaboratingOrganizationAssociated(collaboratingOrganzations: CollaboratingOrganizationView[]): boolean {
195-
return collaboratingOrganzations.length > 0;
194+
public isAnyContactAssociated(contacts: ContactView[]): boolean {
195+
return contacts.length > 0;
196196
}
197197

198198
/**
@@ -205,6 +205,16 @@ export class HCAProjectComponent implements OnDestroy, OnInit {
205205
return contributors.length > 0;
206206
}
207207

208+
/**
209+
* Returns true if at least one data curator has been specified for this project.
210+
*
211+
* @param {string[]} curators
212+
* @returns {boolean}
213+
*/
214+
public isAnyDataCuratorAssociated(curators: string[]): boolean {
215+
return curators.length > 0;
216+
}
217+
208218
/**
209219
* Returns true if project publications exist.
210220
*
@@ -229,16 +239,6 @@ export class HCAProjectComponent implements OnDestroy, OnInit {
229239
return (isMobile || isTablet);
230240
}
231241

232-
/**
233-
* Returns true if project contacts exist.
234-
*
235-
* @param {ContactView[]} contacts
236-
* @returns {boolean}
237-
*/
238-
public isAnyContactAssociated(contacts: ContactView[]): boolean {
239-
return contacts.length > 0;
240-
}
241-
242242
/**
243243
* Returns true if project is a selected facet.
244244
*
@@ -262,6 +262,17 @@ export class HCAProjectComponent implements OnDestroy, OnInit {
262262
return sampleEntityType === "specimens";
263263
}
264264

265+
/**
266+
* Returns true if short name is spaced.
267+
*
268+
* @param {string} shortName
269+
* @returns {boolean}
270+
*/
271+
public isShortNameSentence(shortName: string): boolean {
272+
273+
return shortName.includes(" ");
274+
}
275+
265276
/**
266277
* Returns true if workflow is any value other than "Unspecified".
267278
*

0 commit comments

Comments
 (0)