All files / src/app/services/list-formatter.service list-formatter.service.ts

100% Statements 44/44
100% Branches 34/34
100% Functions 13/13
100% Lines 41/41
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x         31x 1x   7x 7x 5x 5x     1x 23x 3x   20x               31x 5x 15x 15x 15x       31x 15x 15x 15x     31x 19x 12x   7x 6x   1x     1x 9x       31x 19x   19x 10x     9x 8x   1x       31x 8x 8x 8x 7x       1x  
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
 
import { IFileInfo } from '../../model/fileInfo.model';
 
@Injectable()
export class ListFormatterService {
 
  public process(files$: Observable<IFileInfo[]>): Observable<IFileInfo[]> {
    return files$
      .map(files => files.sort(this.fileInfoComparer))
      .map(files => this.applySequence(files));
  }
 
  fileInfoComparer(a: IFileInfo, b: IFileInfo): number {
    if (!a.effectiveDate || !b.effectiveDate) {
      throw new Error('Effective dates not valid. a: ' + a + ', b: ' + b);
    }
    return a.effectiveDate > b.effectiveDate ? -1 :             // Latest date on top
            a.effectiveDate < b.effectiveDate ? 1 :
              a.namePrefix < b.namePrefix ? -1 :                // then sort by name prefix to keep similar files together
                a.namePrefix > b.namePrefix ? 1 :
                  a.effectiveTime > b.effectiveTime ? -1 :      // then the latest time (version)
                    a.effectiveTime < b.effectiveTime ? 1 : 0;
  }
 
  applySequence = (files: IFileInfo[]): IFileInfo[] => {
    return files.reduce((acc, current) => {
      const previous = acc[acc.length - 1];
      const sequenced = this.sequencer(previous, current);
      return [...acc, sequenced];
    }, []);
  }
 
  sequencer = (previous: IFileInfo, current: IFileInfo): IFileInfo => {
    current.sequenceNo = this.getSequenceNo(previous, current);
    this.setDisplayName(current);
    return current;
  }
 
  getSequenceNo = (previous: IFileInfo, current: IFileInfo): number => {
    if (!previous || !current || !current.effectiveTime) {
      return 0;
    }
    if (!this.hasSameFileNameAndDate(previous, current)) {
      return 0;
    }
    return previous.sequenceNo + 1;
  }
 
  hasSameFileNameAndDate(previous: IFileInfo, current: IFileInfo): boolean {
    return previous.baseName === current.baseName &&
      previous.effectiveDate.getTime() === current.effectiveDate.getTime();
  }
 
  setDisplayName = (fileInfo: IFileInfo) => {
    fileInfo.displayName = fileInfo.name;
 
    if (!fileInfo.effectiveTime || fileInfo.sequenceNo === undefined || fileInfo.sequenceNo < 0) {
      return;
    }
 
    if (fileInfo.sequenceNo === 0) {
      this.removeTimeFromDisplayName(fileInfo);
    } else {
      fileInfo.displayName = '...';
    }
  }
 
  removeTimeFromDisplayName = (fileInfo) => {
    const timeAsInFileName = fileInfo.effectiveTime.replace(':', '.');
    const timePos = fileInfo.name.indexOf(timeAsInFileName);
    if (timePos !== -1) {
      fileInfo.displayName = fileInfo.name.replace(` - ${timeAsInFileName}`, '').trimWithMask( '- ' );
    }
  }
 
}