Sunday 19 September 2021

RXJS: Filter => These operators provide techniques for accepting values from an observable source



import { fromof } from 'rxjs';
import { filterfirstlastsingleskipskipWhile
    distinct,taketakeLast  } from 'rxjs/operators';

const source = from([12345]);
const source$ = of(12345);
//filter out non-even numbers
let example = source.pipe(filter(num => num % 2 === 0));
//output: "Even number: 2", "Even number: 4"
//no arguments, emit first value
example = source.pipe(first());
//output: "First value: 1"
example = source.pipe(last());
//output: "Last value: 5"
//emit one item that matches predicate
example = source.pipe(single(val => val === 4));
//output: 4
//skip the first 2 emitted values
example = source.pipe(skip(2));
//output: 3...4...5...
//skip emitted values from source until inner observable emits (6s)
example = source.pipe(skipWhile(a => a < 3));
//output: 3...4...5
of(1234512345).pipe(distinct()).subscribe(console.log);
// OUTPUT: 1,2,3,4,5
//take the first emitted value then complete
example = source$.pipe(take(1));
//output: 1
// take the last 2 emitted values
example = source$.pipe(takeLast(2));
//output: 4,5

Tuesday 20 April 2021

Time ago pipe : A really simple, lightweight Angular pipe for converting a date string into a time ago

import {
  Pipe,
  PipeTransform,
  NgZone,
  ChangeDetectorRef,
  OnDestroy
from "@angular/core";
import * as moment from 'moment-timezone';
@Pipe({
  name: "timeAgo",
  pure: false
})
export class TimeAgoPipe implements PipeTransformOnDestroy {
  private timernumber;
  constructor(
    private changeDetectorRefChangeDetectorRef,
    private ngZoneNgZone
  ) {}
  transform(valuestringtimeZonestring = '') {
    this.removeTimer();
    let d = new Date(value);
    let now = new Date();
    let sign = Math.sign((now.getTime() - d.getTime()) / 1000);
    let seconds = Math.round(Math.abs((now.getTime() - d.getTime()) / 1000));
    
    if (timeZone) {
      d = moment(value).tz(timeZone);
      now = moment().tz(timeZone);
      sign = Math.sign((now.valueOf() - d.valueOf()) / 1000);
      seconds = Math.round(Math.abs((now.valueOf() - d.valueOf()) / 1000));
    }

    let timeToUpdate = Number.isNaN(seconds) ? 1000 : this.getSecondsUntilUpdate(seconds) * 1000;
    
    this.timer = this.ngZone.runOutsideAngular(() => {
      if (typeof window !== "undefined") {
        return window.setTimeout(() => {
          this.ngZone.run(() => this.changeDetectorRef.markForCheck());
        }, timeToUpdate);
      }
      return null;
    });
    
    let minutes = Math.round(Math.abs(seconds / 60));
    let hours = Math.round(Math.abs(minutes / 60));
    let days = Math.round(Math.abs(hours / 24));
    let months = Math.round(Math.abs(days / 30.416));
    let years = Math.round(Math.abs(days / 365));
    let future = false;
    
    if (sign === -1) {
      future = true;
    }
    
    if (Number.isNaN(seconds)) {
      return "";
    } else if (seconds <= 45) {
      return "just now";
    } else if (seconds <= 90) {
      return (future) ? "Starts in 1 min" : "a minute ago";
    } else if (minutes <= 45) {
      return (future) ? "Starts in " + minutes + " mins" : minutes + " minutes ago";
    } else if (minutes <= 90) {
      return (future) ? "Starts in 1 hour" : "an hour ago";
    } else if (hours <= 22) {
      return (future) ? "Starts in " + hours + " hours" : hours + " hours ago";
    } else if (hours <= 36) {
      return (future) ? "Starts in 1 day" : "a day ago";
    } else if (days <= 25) {
      return (future) ? "Starts in " + days + " days" : days + " days ago";
    } else if (days <= 45) {
      return (future) ? "Starts in 1 month" : "a month ago";
    } else if (days <= 345) {
      return (future) ? "Starts in " + months + " months" : months + " months ago";
    } else if (days <= 545) {
      return (future) ? "a year later" : "a year ago";
    } else {
      // (days > 545)
      return (future) ? years + " years later" :   years + " years ago";
    }
  }
  ngOnDestroy(): void {
    this.removeTimer();
  }
  private removeTimer() {
    if (this.timer) {
      window.clearTimeout(this.timer);
      this.timer = null;
    }
  }
  private getSecondsUntilUpdate(secondsnumber) {
    let min = 60;
    let hr = min * 60;
    let day = hr * 24;
    if (seconds < min) {
      // less than 1 min, update every 2 secs
      return 2;
    } else if (seconds < hr) {
      // less than an hour, update every 30 secs
      return 30;
    } else if (seconds < day) {
      // less then a day, update every 5 mins
      return 300;
    } else {
      // update every hour
      return 3600;
    }
  }
}