mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 15:03:07 +00:00
Merge pull request #2018 from 4Science/CST-7217
Improve facet badges alignment
This commit is contained in:
@@ -2,13 +2,12 @@
|
||||
[tabIndex]="-1"
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="addQueryParams" queryParamsHandling="merge">
|
||||
<label class="mb-0">
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value px-1">
|
||||
<label class="mb-0 d-flex w-100">
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch filter-checkbox"/>
|
||||
<span class="w-100 pl-1 break-facet">
|
||||
<span class="float-right badge badge-secondary badge-pill mt-1 ml-1">{{filterValue.count | dsShortNumber}}</span>
|
||||
{{ 'search.filters.' + filterConfig.name + '.' + filterValue.value | translate: {default: filterValue.value} }}
|
||||
</span>
|
||||
</label>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
<span class="badge badge-secondary badge-pill">{{filterValue.count}}</span>
|
||||
</span>
|
||||
|
||||
</a>
|
||||
|
@@ -7,3 +7,11 @@ a {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
|
||||
.break-facet {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.filter-checkbox {
|
||||
height: fit-content;
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ import { SearchFacetOptionComponent } from './search-facet-option.component';
|
||||
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||
import { ShortNumberPipe } from '../../../../../utils/short-number.pipe';
|
||||
|
||||
describe('SearchFacetOptionComponent', () => {
|
||||
let comp: SearchFacetOptionComponent;
|
||||
@@ -89,7 +90,7 @@ describe('SearchFacetOptionComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||
declarations: [SearchFacetOptionComponent],
|
||||
declarations: [SearchFacetOptionComponent, ShortNumberPipe],
|
||||
providers: [
|
||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||
{ provide: Router, useValue: new RouterStub() },
|
||||
|
@@ -3,6 +3,6 @@
|
||||
[queryParams]="changeQueryParams" queryParamsHandling="merge">
|
||||
<span class="filter-value px-1">{{filterValue.label}}</span>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
<span class="badge badge-secondary badge-pill">{{filterValue.count}}</span>
|
||||
</span>
|
||||
<span class="badge badge-secondary badge-pill">{{filterValue.count | dsShortNumber}}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
@@ -15,10 +15,14 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
|
||||
import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { SearchFacetRangeOptionComponent } from './search-facet-range-option.component';
|
||||
import { RANGE_FILTER_MAX_SUFFIX, RANGE_FILTER_MIN_SUFFIX } from '../../search-range-filter/search-range-filter.component';
|
||||
import {
|
||||
RANGE_FILTER_MAX_SUFFIX,
|
||||
RANGE_FILTER_MIN_SUFFIX
|
||||
} from '../../search-range-filter/search-range-filter.component';
|
||||
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||
import { ShortNumberPipe } from '../../../../../utils/short-number.pipe';
|
||||
|
||||
describe('SearchFacetRangeOptionComponent', () => {
|
||||
let comp: SearchFacetRangeOptionComponent;
|
||||
@@ -60,7 +64,7 @@ describe('SearchFacetRangeOptionComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||
declarations: [SearchFacetRangeOptionComponent],
|
||||
declarations: [SearchFacetRangeOptionComponent, ShortNumberPipe],
|
||||
providers: [
|
||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||
{ provide: Router, useValue: new RouterStub() },
|
||||
|
@@ -2,9 +2,9 @@
|
||||
[tabIndex]="-1"
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="removeQueryParams" queryParamsHandling="merge">
|
||||
<label class="mb-0">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1 text-capitalize">
|
||||
<label class="mb-0 d-flex w-100">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch filter-checkbox"/>
|
||||
<span class="filter-value pl-1 text-capitalize break-facet">
|
||||
{{ 'search.filters.' + filterConfig.name + '.' + selectedValue.value | translate: {default: selectedValue.label} }}
|
||||
</span>
|
||||
</label>
|
||||
|
@@ -7,3 +7,11 @@ a {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
|
||||
.break-facet {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.filter-checkbox {
|
||||
height: fit-content;
|
||||
}
|
||||
|
@@ -245,9 +245,10 @@ import {
|
||||
} from './object-list/listable-notification-object/listable-notification-object.component';
|
||||
import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component';
|
||||
import { MetadataFieldWrapperComponent } from './metadata-field-wrapper/metadata-field-wrapper.component';
|
||||
import { LogInExternalProviderComponent } from './log-in/methods/log-in-external-provider/log-in-external-provider.component';
|
||||
|
||||
|
||||
import {
|
||||
LogInExternalProviderComponent
|
||||
} from './log-in/methods/log-in-external-provider/log-in-external-provider.component';
|
||||
import { ShortNumberPipe } from './utils/short-number.pipe';
|
||||
|
||||
const MODULES = [
|
||||
CommonModule,
|
||||
@@ -286,6 +287,7 @@ const PIPES = [
|
||||
ObjNgFor,
|
||||
BrowserOnlyPipe,
|
||||
MarkdownPipe,
|
||||
ShortNumberPipe
|
||||
];
|
||||
|
||||
const COMPONENTS = [
|
||||
|
96
src/app/shared/utils/short-number.pipe.spec.ts
Normal file
96
src/app/shared/utils/short-number.pipe.spec.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ShortNumberPipe } from './short-number.pipe';
|
||||
|
||||
describe('ShortNumber Pipe', () => {
|
||||
|
||||
let shortNumberPipe: ShortNumberPipe;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
ShortNumberPipe
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
shortNumberPipe = TestBed.inject(ShortNumberPipe);
|
||||
});
|
||||
|
||||
it('should not transform with an invalid number', async () => {
|
||||
await testTransform(
|
||||
'tre',
|
||||
'tre'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not transform with an empty string', async () => {
|
||||
await testTransform(
|
||||
'',
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
it('should not transform with zero', async () => {
|
||||
await testTransform(
|
||||
0,
|
||||
'0'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 1K', async () => {
|
||||
await testTransform(
|
||||
'1000',
|
||||
'1K'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 1K', async () => {
|
||||
await testTransform(
|
||||
1000,
|
||||
'1K'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 19.3K', async () => {
|
||||
await testTransform(
|
||||
19300,
|
||||
'19.3K'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 1M', async () => {
|
||||
await testTransform(
|
||||
1000000,
|
||||
'1M'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 1B', async () => {
|
||||
await testTransform(
|
||||
1000000000,
|
||||
'1B'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 1T', async () => {
|
||||
await testTransform(
|
||||
1000000000000,
|
||||
'1T'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render 1Q', async () => {
|
||||
await testTransform(
|
||||
1000000000000000,
|
||||
'1Q'
|
||||
);
|
||||
});
|
||||
|
||||
async function testTransform(input: any, output: string) {
|
||||
expect(
|
||||
await shortNumberPipe.transform(input)
|
||||
).toMatch(
|
||||
output
|
||||
);
|
||||
}
|
||||
});
|
40
src/app/shared/utils/short-number.pipe.ts
Normal file
40
src/app/shared/utils/short-number.pipe.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { isEmpty } from '../empty.util';
|
||||
|
||||
|
||||
@Pipe({
|
||||
name: 'dsShortNumber'
|
||||
})
|
||||
export class ShortNumberPipe implements PipeTransform {
|
||||
|
||||
transform(number: number, args?: any): any {
|
||||
// will only work value is a valid number
|
||||
if (isNaN(number) || isEmpty(number) || number === 0) {
|
||||
return number;
|
||||
}
|
||||
|
||||
let abs = Math.abs(number);
|
||||
const rounder = Math.pow(10, 1);
|
||||
const isNegative = number < 0; // will also work for Negetive numbers
|
||||
let key = '';
|
||||
|
||||
const powers = [
|
||||
{key: 'Q', value: Math.pow(10, 15)},
|
||||
{key: 'T', value: Math.pow(10, 12)},
|
||||
{key: 'B', value: Math.pow(10, 9)},
|
||||
{key: 'M', value: Math.pow(10, 6)},
|
||||
{key: 'K', value: 1000}
|
||||
];
|
||||
|
||||
for (let i = 0; i < powers.length; i++) {
|
||||
let reduced = abs / powers[i].value;
|
||||
reduced = Math.round(reduced * rounder) / rounder;
|
||||
if (reduced >= 1) {
|
||||
abs = reduced;
|
||||
key = powers[i].key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (isNegative ? '-' : '') + abs + key;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user