mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
[CST-7217] Implement short number pipe
This commit is contained in:
@@ -100,19 +100,19 @@ import {
|
|||||||
CreateCommunityParentSelectorComponent
|
CreateCommunityParentSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component';
|
} from './dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component';
|
||||||
import {
|
import {
|
||||||
ThemedCreateCommunityParentSelectorComponent
|
ThemedCreateCommunityParentSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/create-community-parent-selector/themed-create-community-parent-selector.component';
|
} from './dso-selector/modal-wrappers/create-community-parent-selector/themed-create-community-parent-selector.component';
|
||||||
import {
|
import {
|
||||||
CreateItemParentSelectorComponent
|
CreateItemParentSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component';
|
} from './dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component';
|
||||||
import {
|
import {
|
||||||
ThemedCreateItemParentSelectorComponent
|
ThemedCreateItemParentSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/create-item-parent-selector/themed-create-item-parent-selector.component';
|
} from './dso-selector/modal-wrappers/create-item-parent-selector/themed-create-item-parent-selector.component';
|
||||||
import {
|
import {
|
||||||
CreateCollectionParentSelectorComponent
|
CreateCollectionParentSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component';
|
} from './dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component';
|
||||||
import {
|
import {
|
||||||
ThemedCreateCollectionParentSelectorComponent
|
ThemedCreateCollectionParentSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/create-collection-parent-selector/themed-create-collection-parent-selector.component';
|
} from './dso-selector/modal-wrappers/create-collection-parent-selector/themed-create-collection-parent-selector.component';
|
||||||
import {
|
import {
|
||||||
CommunitySearchResultListElementComponent
|
CommunitySearchResultListElementComponent
|
||||||
@@ -124,19 +124,19 @@ import {
|
|||||||
EditItemSelectorComponent
|
EditItemSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component';
|
} from './dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component';
|
||||||
import {
|
import {
|
||||||
ThemedEditItemSelectorComponent
|
ThemedEditItemSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/edit-item-selector/themed-edit-item-selector.component';
|
} from './dso-selector/modal-wrappers/edit-item-selector/themed-edit-item-selector.component';
|
||||||
import {
|
import {
|
||||||
EditCommunitySelectorComponent
|
EditCommunitySelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component';
|
} from './dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component';
|
||||||
import {
|
import {
|
||||||
ThemedEditCommunitySelectorComponent
|
ThemedEditCommunitySelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/edit-community-selector/themed-edit-community-selector.component';
|
} from './dso-selector/modal-wrappers/edit-community-selector/themed-edit-community-selector.component';
|
||||||
import {
|
import {
|
||||||
EditCollectionSelectorComponent
|
EditCollectionSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component';
|
} from './dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component';
|
||||||
import {
|
import {
|
||||||
ThemedEditCollectionSelectorComponent
|
ThemedEditCollectionSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/edit-collection-selector/themed-edit-collection-selector.component';
|
} from './dso-selector/modal-wrappers/edit-collection-selector/themed-edit-collection-selector.component';
|
||||||
import { RoleDirective } from './roles/role.directive';
|
import { RoleDirective } from './roles/role.directive';
|
||||||
import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component';
|
import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component';
|
||||||
@@ -242,9 +242,10 @@ import {
|
|||||||
} from './object-list/listable-notification-object/listable-notification-object.component';
|
} from './object-list/listable-notification-object/listable-notification-object.component';
|
||||||
import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component';
|
import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component';
|
||||||
import { MetadataFieldWrapperComponent } from './metadata-field-wrapper/metadata-field-wrapper.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 = [
|
const MODULES = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -283,6 +284,7 @@ const PIPES = [
|
|||||||
ObjNgFor,
|
ObjNgFor,
|
||||||
BrowserOnlyPipe,
|
BrowserOnlyPipe,
|
||||||
MarkdownPipe,
|
MarkdownPipe,
|
||||||
|
ShortNumberPipe
|
||||||
];
|
];
|
||||||
|
|
||||||
const COMPONENTS = [
|
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