| @@ -14,7 +14,7 @@ import { SelectEntitiesComponent } from './widgets/select-entities/select-entiti | |||
| import { CheckStatusComponent } from './widgets/check-status/check-status.component'; | |||
| import { TableComponent } from './widgets/table/table.component'; | |||
| import { KeyValueHolderComponent } from './widgets/key-value-holder/key-value-holder.component'; | |||
| import { DownloadButtonComponent } from './widgets/download-button/download-button.component'; | |||
| import { FileComponent } from './widgets/file/file.component'; | |||
| @NgModule({ | |||
| declarations: [ | |||
| @@ -29,7 +29,7 @@ import { DownloadButtonComponent } from './widgets/download-button/download-butt | |||
| CheckStatusComponent, | |||
| TableComponent, | |||
| KeyValueHolderComponent, | |||
| DownloadButtonComponent | |||
| FileComponent | |||
| ], | |||
| imports: [ | |||
| BrowserModule, | |||
| @@ -59,12 +59,13 @@ | |||
| <div class="table-holder"> | |||
| <app-table | |||
| [headings]="['A', 'B', 'C']" | |||
| [tableDetails]="[['Val 1', 'Val 2 ', 'Val 3'], ['V1', 'V2', 'V3'], ['A1', 'A2', 'A3']]"></app-table> | |||
| [headings]="['A', 'B', 'C']" | |||
| [tableDetails]="[['Val 1', 'Val 2 ', 'Val 3'], ['V1', 'V2', 'V3'], ['A1', 'A2', 'A3']]" | |||
| ></app-table> | |||
| </div> | |||
| <div class="key-value-holder"> | |||
| <app-key-value-holder [keyValues]="keyValues"></app-key-value-holder> | |||
| </div> | |||
| <app-download-button [fileDetails]="{name: 'Downladable Table', size: '30MB', extension: 'xls'}"></app-download-button> | |||
| <app-file [name]="'Downladable Table'" [sizeInBytes]="30000" [extension]="'xls'" [link]="'http://localhost:4200/assets/icons/bell.svg'"></app-file> | |||
| @@ -1,6 +1,6 @@ | |||
| <div class="container"> | |||
| <figure class="logo"> | |||
| <img src="assets/icons/logo.svg" alt="bizfile plus logo"> | |||
| <img src="./../../../assets/icons/logo.svg" alt="bizfile plus logo"> | |||
| </figure> | |||
| <section class="form"> | |||
| @@ -1,9 +0,0 @@ | |||
| <section class="download-button" *ngIf="fileDetails"> | |||
| <div class="extension"> | |||
| {{ fileDetails.extension }} | |||
| </div> | |||
| <div class="file-labels"> | |||
| <h5> {{ fileDetails.name }} </h5> | |||
| <p> {{ fileDetails.size }} </p> | |||
| </div> | |||
| </section> | |||
| @@ -1,43 +0,0 @@ | |||
| .download-button { | |||
| display: inline-flex; | |||
| border: 1px solid var(--border-grey); | |||
| border-radius: 1rem; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| cursor: pointer; | |||
| min-height: 4rem; | |||
| padding: 1rem; | |||
| &:hover{ | |||
| background-color: var(--border-grey); | |||
| } | |||
| .extension { | |||
| padding: 1rem; | |||
| text-align: center; | |||
| border: 1px solid var(--border-grey); | |||
| height: 2rem; | |||
| border-radius: 0.5rem; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| color: var(--dark-grey); | |||
| font-size: 1.4rem; | |||
| margin-right: 1rem; | |||
| } | |||
| .file-labels { | |||
| flex-grow: 1; | |||
| line-height: 1.5; | |||
| h5 { | |||
| font-size: 1.2rem; | |||
| color: var(--teal); | |||
| } | |||
| p { | |||
| font-size: 1.1rem; | |||
| color: var(--dark-grey); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,20 +0,0 @@ | |||
| import { Component, Input, OnInit } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-download-button', | |||
| templateUrl: './download-button.component.html', | |||
| styleUrls: ['./download-button.component.scss'] | |||
| }) | |||
| export class DownloadButtonComponent implements OnInit { | |||
| @Input() fileDetails: { | |||
| name: string, | |||
| size: string, | |||
| extension: string, | |||
| } | undefined = undefined; | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| } | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| <section class="file"> | |||
| <div class="file-avatar"> | |||
| <div class="file-outline"></div> | |||
| <section *ngIf="extension" class="extension"> | |||
| {{ extension }} | |||
| </section> | |||
| </div> | |||
| <div class="file-labels"> | |||
| <h5 *ngIf="name"> {{ name }} </h5> | |||
| <p *ngIf="readableSize"> {{ readableSize }} </p> | |||
| </div> | |||
| <a *ngIf="link" [href]="link" download class="download-button"> | |||
| <img src="assets/icons/chevron-down.svg" alt="chevron down image"> | |||
| </a> | |||
| </section> | |||
| @@ -0,0 +1,109 @@ | |||
| .file { | |||
| display: inline-flex; | |||
| border: 1px solid var(--border-grey); | |||
| border-radius: 1rem; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| height: 7rem; | |||
| padding-left: 1rem; | |||
| box-shadow: 0 0 3px rgba(0, 0, 0, 0.1); | |||
| .file-avatar { | |||
| position: relative; | |||
| width: 5rem; | |||
| height: 7rem; | |||
| .file-outline { | |||
| position: absolute; | |||
| top: 1.25rem; | |||
| left: 0; | |||
| width: 3.5rem; | |||
| height: 4.5rem; | |||
| border: 1px solid var(--border-grey); | |||
| &::before { | |||
| position: absolute; | |||
| top: -1px; | |||
| right: -1px; | |||
| width: 1rem; | |||
| height: 1rem; | |||
| display: block; | |||
| content: ""; | |||
| background-color: white; | |||
| } | |||
| &::after { | |||
| position: absolute; | |||
| top: -1px; | |||
| right: calc(-0.414rem - 1px); | |||
| width: 1.414rem; | |||
| height: 1px; | |||
| display: block; | |||
| content: ""; | |||
| background-color: var(--border-grey); | |||
| transform-origin: center left; | |||
| transform: rotate(45deg); | |||
| } | |||
| } | |||
| .extension { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| position: absolute; | |||
| right: 0.5rem; | |||
| bottom: 1.75rem; | |||
| border: 1px solid var(--border-grey); | |||
| text-align: center; | |||
| background-color: var(--highlight); | |||
| color: white; | |||
| letter-spacing: 0.1rem; | |||
| font-size: 1.2rem; | |||
| padding: 0.1rem 0.4rem; | |||
| padding-left: 0.6rem; | |||
| font-weight: bold; | |||
| } | |||
| } | |||
| .file-labels { | |||
| width: 12rem; | |||
| flex-grow: 1; | |||
| line-height: 1.5; | |||
| h5 { | |||
| font-size: 1.2rem; | |||
| color: var(--primary); | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| } | |||
| p { | |||
| font-size: 1.1rem; | |||
| color: var(--dark-grey); | |||
| } | |||
| } | |||
| .download-button { | |||
| height: 100%; | |||
| width: 3rem; | |||
| border-left: 1px solid var(--border-grey); | |||
| margin-left: 1rem; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| cursor: pointer; | |||
| &:hover{ | |||
| background-color: var(--border-grey); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,20 +1,20 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { DownloadButtonComponent } from './download-button.component'; | |||
| import { FileComponent } from './file.component'; | |||
| describe('DownloadButtonComponent', () => { | |||
| let component: DownloadButtonComponent; | |||
| let fixture: ComponentFixture<DownloadButtonComponent>; | |||
| describe('FileComponent', () => { | |||
| let component: FileComponent; | |||
| let fixture: ComponentFixture<FileComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ DownloadButtonComponent ] | |||
| declarations: [ FileComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(DownloadButtonComponent); | |||
| fixture = TestBed.createComponent(FileComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| @@ -0,0 +1,72 @@ | |||
| import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; | |||
| type SizeUnit = 'B' | 'KB' | 'MB' | 'GB' | 'TB'; | |||
| @Component({ | |||
| selector: 'app-file', | |||
| templateUrl: './file.component.html', | |||
| styleUrls: ['./file.component.scss'] | |||
| }) | |||
| export class FileComponent implements OnInit, OnChanges { | |||
| @Input() name = ''; | |||
| @Input() sizeInBytes = 0; | |||
| @Input() extension = ''; | |||
| @Input() link = ''; | |||
| readableSize = ''; | |||
| constructor() { } | |||
| getNextUnit(unit: SizeUnit): SizeUnit|undefined { | |||
| switch (unit) { | |||
| case 'B': | |||
| return 'KB'; | |||
| case 'KB': | |||
| return 'MB'; | |||
| case 'MB': | |||
| return 'GB'; | |||
| case 'GB': | |||
| return 'TB'; | |||
| case 'TB': | |||
| return undefined | |||
| default: | |||
| throw new Error('Unknown unit: ' + unit); | |||
| } | |||
| } | |||
| getReadableSize(sizeInBytes?: number) { | |||
| let unit: SizeUnit = 'B'; | |||
| if (typeof sizeInBytes === 'undefined') { | |||
| return ''; | |||
| } | |||
| let size: number = sizeInBytes; | |||
| while (size > 1024 && unit !== 'TB') { | |||
| size /= 1024; | |||
| const nextUnit = this.getNextUnit(unit); | |||
| if (typeof nextUnit === 'undefined') { | |||
| break; | |||
| } | |||
| unit = nextUnit; | |||
| } | |||
| return `${size.toFixed(1)} ${unit}`; | |||
| } | |||
| ngOnChanges(simpleChanges: SimpleChanges) { | |||
| if (simpleChanges.sizeInBytes && simpleChanges.sizeInBytes.currentValue !== simpleChanges.sizeInBytes.previousValue) { | |||
| this.readableSize = this.getReadableSize(simpleChanges.sizeInBytes.currentValue); | |||
| } | |||
| } | |||
| ngOnInit(): void { | |||
| if (typeof this.sizeInBytes !== 'undefined') { | |||
| this.readableSize = this.getReadableSize(this.sizeInBytes); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| <ul> | |||
| <li *ngFor="const entity of entities" (click)="selectEntity(entity)" | |||
| <li *ngFor="let entity of entities" (click)="selectEntity(entity)" | |||
| [ngClass]="{'isActive': entity.isSelected}"> | |||
| <img [src]="entity.avatar" alt="entity.name"> | |||
| <div class="user-data"> | |||