typescript 用于在输入中显示/隐藏密码的Angular7指令

用于在输入中显示/隐藏密码的Angular7指令

input-password.directive.spec.ts
import {Directive, ElementRef} from '@angular/core';

@Directive({
  selector: '[appInputPassword]'
})
export class InputPasswordDirective {

  private _shown = false;

  private eyeTemplateShow = '<div class="icon brand-background" style="-webkit-mask: url(/assets/svg/view.svg) no-repeat center; mask: url(/assets/svg/view.svg) no-repeat center; width: 30px; height: 30px; float: right; position: relative; margin-top: -31px; right: 10px; cursor:pointer"></div>'
  private eyeTemplateHide = '<div class="icon brand-background" style="-webkit-mask: url(/assets/svg/hide.svg) no-repeat center; mask: url(/assets/svg/hide.svg) no-repeat center; width: 31px; height: 30px; float: right; position: relative; margin-top: -31px; right: 10px; cursor:pointer"></div>'

  constructor(private el: ElementRef) {
    this.setup();
  }

  toggle(span: HTMLElement) {
    this._shown = !this._shown;
    if (this._shown) {
      this.el.nativeElement.setAttribute('type', 'text');
      span.innerHTML = this.eyeTemplateHide;
    } else {
      this.el.nativeElement.setAttribute('type', 'password');
      span.innerHTML = this.eyeTemplateShow;
    }
  }

  setup() {
    const parent = this.el.nativeElement.parentNode;
    const span = document.createElement('span');

    span.innerHTML = this.eyeTemplateShow;
    span.addEventListener('click', (event) => {
      this.toggle(span);
    });
    parent.appendChild(span);
  }
}

typescript 用于在输入中显示/隐藏密码的Angular7指令

用于在输入中显示/隐藏密码的Angular7指令

input-password.directive.spec.ts
import {Directive, ElementRef} from '@angular/core';

@Directive({
  selector: '[appInputPassword]'
})
export class InputPasswordDirective {

  private _shown = false;

  private eyeTemplateShow = '<div class="icon brand-background" style="-webkit-mask: url(/assets/svg/view.svg) no-repeat center; mask: url(/assets/svg/view.svg) no-repeat center; width: 30px; height: 30px; float: right; position: relative; margin-top: -31px; right: 10px; cursor:pointer"></div>'
  private eyeTemplateHide = '<div class="icon brand-background" style="-webkit-mask: url(/assets/svg/hide.svg) no-repeat center; mask: url(/assets/svg/hide.svg) no-repeat center; width: 31px; height: 30px; float: right; position: relative; margin-top: -31px; right: 10px; cursor:pointer"></div>'

  constructor(private el: ElementRef) {
    this.setup();
  }

  toggle(span: HTMLElement) {
    this._shown = !this._shown;
    if (this._shown) {
      this.el.nativeElement.setAttribute('type', 'text');
      span.innerHTML = this.eyeTemplateHide;
    } else {
      this.el.nativeElement.setAttribute('type', 'password');
      span.innerHTML = this.eyeTemplateShow;
    }
  }

  setup() {
    const parent = this.el.nativeElement.parentNode;
    const span = document.createElement('span');

    span.innerHTML = this.eyeTemplateShow;
    span.addEventListener('click', (event) => {
      this.toggle(span);
    });
    parent.appendChild(span);
  }
}

typescript 函数返回一个对象,该对象的键是输入对象的值

函数返回一个对象,该对象的键是输入对象的值

typescript_dynamic-key-function.ts
/**
* Declare the type for the following fuction
* e.g. const mappingFunc = obj => ({[obj.name]: true})
**/

const mappingFunc = <T extends string>(arg: {name: T}): Record<T, boolean> => ({
  [arg.name]: true
})

const obj = {
  name: 'foo' as 'foo' // <-- narrow down the type from `string` to `"foo"` (String Literal Type)
}

const output = mappingFunc<typeof obj.name>(obj);
console.log(output.foo) // true
console.log(output.bar) // error:  TS2339: Property 'bar' does not exist on type 'Record<"foo", boolean>'.

typescript 使用Day.js为Angular Material MatDatepicker自定义DateFormats和DateAdapter

使用Day.js为Angular Material MatDatepicker自定义DateFormats和DateAdapter

date-formats.ts
import { Platform } from '@angular/cdk/platform';
import { NativeDateAdapter } from '@angular/material';
import * as dayjs from 'dayjs';
import 'dayjs/locale/de';
import * as customParseFormat from 'dayjs/plugin/customParseFormat';
import * as localizedFormat from 'dayjs/plugin/localizedFormat';


/**
* Custom Date-Formats and Adapter (using https://github.com/iamkun/dayjs)
*/

export const AppDateFormats = {
  parse: {
    dateInput: 'DD.MM.YYYY',
  },
  display: {
    dateInput: 'DD.MM.YYYY',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  }
}

export class AppDateAdapter extends NativeDateAdapter {

  constructor(matDateLocale: string, platform: Platform) {
    super(matDateLocale, platform)

    // Initalize DayJS-Parser
    dayjs.locale('de')
    dayjs.extend(customParseFormat)
    dayjs.extend(localizedFormat)
  }

  parse(value: any): Date | null {
    return dayjs(value, 'DD.MM.YYYY').toDate()
  }

  format(date: Date, displayFormat: any): string {
    return dayjs(date).format(displayFormat)
  }

}

shared.module.ts
/* ... */

/* Adding Providers in a Shared- or App-Module */


@NgModule({

  providers: [
    {
      provide: DateAdapter,
      useClass: AppDateAdapter,
      deps: [MAT_DATE_LOCALE, Platform]
    },
    {
      provide: MAT_DATE_FORMATS,
      useValue: AppDateFormats
    }
  ]

})
export class SharedModule { }

typescript 标记的模板

标记的模板

tagged.ts
function element(strings,name:string,lastname:string) {
    return `<p>${name} ${lastname}</p>`
}
var myname= "vladimir";
var lastname = "juarez";
console.log(element`${myname}${lastname}`)

typescript 标记的模板

标记的模板

typesript.ts
function element(strings,name:string,lastname:string) {
    return `<p>${name} ${lastname}</p>`
}
var myname= "vladimir";
var lastname = "juarez";
console.log(element`${myname}${lastname}`)

typescript Apollo websocket TRM

.md
in TRM
websocket is not being used now. 
this is for backup codes
old.ts
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloClient } from 'apollo-client';
import { split } from 'apollo-link';
import { setContext } from 'apollo-link-context';
import { createHttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
import React from 'react';
import { ApolloProvider } from 'react-apollo';
import authService from './authService';

import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import introspectionQueryResultData from './fragmentTypes.json';
import { env } from 'src/env.config';

const httpLink = createHttpLink({
  uri: env.ApolloServerURL
})

const authLink = setContext((_, { headers }) => {
  const token = authService.getUserData()
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : ''
    }
  }
})

/**
 * websocket is for subscription and the subscription functionality isn't currently in use
 */
const wsLink = new WebSocketLink({
  uri: `ws://localhost:4000`,
  options: {
    reconnect: true,
    connectionParams: {
      authToken: authService.getUserData(),
    }
  }
})

const link = split(
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query)
    return kind === 'OperationDefinition' && operation === 'subscription'
  },
  wsLink,
  authLink.concat(httpLink)
)

/**
 * to remove heuristic matching error
 */
const fragmentMatcher = new IntrospectionFragmentMatcher({
  introspectionQueryResultData
});

const client = new ApolloClient({
  link,
  cache: new InMemoryCache({ fragmentMatcher }),
  connectToDevTools: true,
})

export default function ApolloWrapper(props) {
  return (
    <ApolloProvider client={client}>
      {props.children}
    </ApolloProvider>)
}
current.ts
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloClient } from 'apollo-client';
import { split } from 'apollo-link';
import { setContext } from 'apollo-link-context';
import { createHttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
import React from 'react';
import { ApolloProvider } from 'react-apollo';
import authService from './authService';

import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import introspectionQueryResultData from './fragmentTypes.json';
import { env } from 'src/env.config';

const httpLink = createHttpLink({
  uri: env.ApolloServerURL
})

const authLink = setContext((_, { headers }) => {
  const token = authService.getUserData()
  console.log('token', token)
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : ''
    }
  }
})

/**
 * websocket is for subscription and the subscription functionality isn't currently in use
 */
// const wsLink = new WebSocketLink({
//   // uri: `ws://localhost:4000`,
//   options: {
//     reconnect: true,
//     connectionParams: {
//       authToken: authService.getUserData(),
//     }
//   }
// })

// const link = split(
//   ({ query }) => {
//     const { kind, operation } = getMainDefinition(query)
//     return kind === 'OperationDefinition' && operation === 'subscription'
//   },
//   wsLink,
//   authLink.concat(httpLink)
// )

/**
 * to remove heuristic matching error
 */
const fragmentMatcher = new IntrospectionFragmentMatcher({
  introspectionQueryResultData
});

const client = new ApolloClient({
  // link,
  link : authLink.concat(httpLink),
  cache: new InMemoryCache({ fragmentMatcher }),
  connectToDevTools: true,
})

export default function ApolloWrapper(props) {
  return (
    <ApolloProvider client={client}>
      {props.children}
    </ApolloProvider>)
}

typescript 撤消操作员

undo.ts
/**
 * Subscribes to the `undoNotifier`, and emits all values from
 * `source`. When `undoNotifier` emits, it will emit previously
 * emitted values back through time.
 *
 * If a `redoNotifier` is passed, it's subscribed to, and when
 * it emits, will "redo" anything that was "undone", unless new 
 * values have come from the source.
 * 
 * TODO: Add an upper-bounds to the undo state collected.
 */
function undo<T>(undoNotifier: Observable<any>, redoNotifier: Observable<any> = EMPTY) {
  return (source: Observable<T>) => merge(
    undoNotifier.pipe(map(() => UNDO_TOKEN)),
    redoNotifier.pipe(map(() => REDO_TOKEN)),
    source,
  ).pipe(
    scan<T, { state: T[], redos: T[]|null }>((d, x) => {
      console.log({d, x})
      let { state, redos } = d;
      if (x === UNDO_TOKEN) {
        // We were notified of an "undo". pop state.
        if (state && state.length > 1) {
          redos = redos || (d.redos = []);
          redos.push(state.pop());
        }
      } else if (x === REDO_TOKEN) {
        if (redos && redos.length > 0) {
          state.push(redos.pop());
        }
      } else {
        if (redos) {
          // clear our redos as new history is written
          redos.length = 0;
        }
        state = state || (d.state = []);
        // It's not an "undo", push state
        state.push(x);
      }
      return d;
    }, { state: null, redos: null }),
    // we only care about state past here
    map(x => x.state),
    // Don't emit if we don't have state
    filter(x => x !== null),
    // Take the last value from state
    map(state => state[state.length - 1]),
  )
}

typescript 异步ForEach

handler
 let string = '';
 let counter = 0;
 const start = async () => {
    await Promise.all(data.Contents.map(async element => {
        string += await someAsyncFunc(element);
        console.log('Counter: ' + counter);
        counter++;
    }))
    console.log('Finishing');
    doSomethingAfterThat(string);
}

start();

async function someAsyncFunc(data: string) {
  return new Promise((resolve, reject) => {
      //wait....
      resolve('asd');
  })
}

typescript 记录良好的打字稿界面

typescript_interface.ts
import AsyncData from '@/util/AsyncData';
import { AxiosError } from '../axios';
import RefreshableData from '@/util/RefreshableData';

export interface IDeploymentHistoryRecord {
  appId: number;
  created: string; // ISO 8601 Datetime String
  createdBy: string; // SSO
  current: boolean;
  envId: number;
  id: number;
  // TODO: What all can these be?
  status: 'SUCCESS' | 'FAILED' | 'WORKING' | 'QUEUED';
  // TODO: What all can these be?
  statusMessage: 'SUCCESS' | 'FAILED' | 'DEPLOYING' | 'QUEUED' | 'DELETING';
  svcId: number;
  totalEvents: number;
  totalPropertie: number;
  updated: string; // ISO 8601 Datetime String
  updatedBy: string; // SSO
  uuid: string; // UUID
  version: string; // Hopefully Semver, but it could technically be anything.
}

export interface IAvailableVersion {
  /**
   * The name of this version, hopefully in semver.
   */
  name: string;
}

export interface ICurrentDeploymentStatus {
  /**
   * ID of the service being deployed.
   */
  id: number;
  /**
   * Backend status of the deployment.
   *
   * NOTE: If there are no deploys, the backend returns 'QUEUED'?
   *
   * TODO: Get full list.
   */
  status: 'SUCCESS' | 'FAILED' | 'WORKING' | 'QUEUED';
  /**
   * Friendlier status of the deployment.
   *
   * NOTE: If there are no deploys, the backend returns 'QUEUED'?
   *
   * TODO: Get full list.
   */
  statusMessage: 'SUCCESS' | 'FAILED' | 'DEPLOYING' | 'QUEUED' | 'DELETING';
  /**
   * Version selected for this deploy.
   *
   * NOTE: If there are no deploys, the backend returns null.
   */
  versionSelected: string | null;
}

export interface ICurrentDeploymentStatusWatch {
  /**
   * ID of the service whose status is currently being watched.
   */
  serviceId: number;
  /**
   * ID of the timeout until next ping.
   *
   * This will probably change to something else if switching to
   * websockets or server-sent events or something.
   */
  timeoutId: number | null;
  /**
   * Timeout time.
   */
  timeoutTime: number | null;
  /**
   * Current status, as a RefreshableData instance.
   */
  status: RefreshableData<CurrentDeploymentStatusData>;
}

export type DeploymentHistoryData = AsyncData<IDeploymentHistoryRecord[], AxiosError>;
export type AvailableVersionsData = AsyncData<IAvailableVersion[], AxiosError>;
export type CurrentDeploymentStatusData = AsyncData<ICurrentDeploymentStatus, AxiosError>;

export default interface IDeploymentsPage {
  // TODO: Better types.
  /**
   * State specific to the Deployments Tab.
   */
  deploymentTab: {
    /**
     * What versions are available to deploy.
     * These come from the server sorted newest-first, i.e. in descending order.
     */
    availableVersions: AvailableVersionsData;
    /**
     * Past deploys of the selected service,
     * listed in descending order by date of record creation.
     */
    history: DeploymentHistoryData;
    downloadEvents: object[];
  };
  // /**
  //  * Status of the current deployment if any.
  //  */
  // currentDeploymentStatus: CurrentDeploymentStatusData;
  /**
   * Watch for the Current Deployment Status.
   */
  currentDeploymentStatusWatch: ICurrentDeploymentStatusWatch;
  events: object[];
  versions: object[];
}