#StackBounty: #typescript #vue.js #types #vuex Generic type for typing vuex store

Bounty: 50

I am trying to create a generic type which will prove typing hints for Vuex mutation. I read this article Vuex + TypeScript and I get inspired to create something more generic. I came up with something like this:

export type MutationType<S, P, K extends keyof P> = Record<K, (state: S, payload: P[K]) => void>;

// S
export type DiceGameState = {
  round: number;
  score: number;
  diceItems: DiceHistoryItem[];
};

// P
export interface DiceGameMutationPayloadMap {
  INCREMENT_SCORE: number;
  DECREMENT_ROUND: number;
  ADD_DICE_HISTORY_ITEM: DiceHistoryItem;
}

// K
export enum DiceGameMutationsKeys {
  INCREMENT_SCORE = 'INCREMENT_SCORE',
  DECREMENT_ROUND = 'DECREMENT_ROUND',
  ADD_DICE_HISTORY_ITEM = 'ADD_DICE_HISTORY_ITEM'
}

export type DiceStoreMutation = MutationType<
  DiceGameState,
  DiceGameMutationPayloadMap,
  keyof typeof DiceGameMutationsKeys
>;

export const mutations: MutationTree<DiceGameState> & DiceStoreMutation = {
  DECREMENT_ROUND: (state: DiceGameState, payload: number) => {},
  INCREMENT_SCORE: (state: DiceGameState, payload: number) => {},
  ADD_DICE_HISTORY_ITEM: (state: DiceGameState, payload: DiceHistoryItem) => {}
};

Where:

  • S → type of mutation state
  • P → map of mutation name and type of payload assigned to this mutation
  • K → mutation name

If I check details of this MutationType in my IDE I am getting this hint:

enter image description here

So the key in this object is one of K keys and the value is a method which takes state which is type of S and payload which is type of assigned value to P.

If I try to compile this code I am getting this error:

Error:(7, 3) TS2322: Type ‘(state: DiceGameState, payload: number) => void’ is not assignable to type ‘(state: DiceGameState, payload: number | DiceHistoryItem) => void’.
Types of parameters ‘payload’ and ‘payload’ are incompatible.
Type ‘number | DiceHistoryItem’ is not assignable to type ‘number’.
Type ‘DiceHistoryItem’ is not assignable to type ‘number’.

Do you know how can I make my generic to work ?


Get this bounty!!!

#StackBounty: #typescript #types #mapped-types Typescript: index signatures in mapped type

Bounty: 150

How can I take the type { 'k': number, [s: string]: any } and abstract over 'k' and number? I would like to have a type alias T such that T<'k', number> gives the said type.


Consider the following example:

function f(x: { 'k': number, [s: string]: any }) {}                           // ok
type T_no_params = { 'k': number, [s: string]: any };                         // ok
type T_key_only<k extends string> = { [a in k]: number };                     // ok
type T_value_only<V> = { 'k': V, [s: string]: any};                           // ok
type T_key_and_index<k extends string, V> = { [a in k]: V, [s: string]: any };// ?
  • Using { 'k': number, [s: string]: any} directly as type of the parameter of the function f works.
  • Using the [s: string]: any indexed part in type-alias works
  • Using k extends string in type-alias also works
  • When combining the k extends string with the [s: string]: any in same type-alias, I get a parse error (not even a semantic error, it doesn’t even seem to be valid syntax).

This here seems to work:

type HasKeyValue<K extends string, V> = { [s: string]: any } & { [S in K]: V }

but here, I can’t quite understand why it does not complain about extra properties (the type on the right side of the & should not allow objects with extra properties).


I’ve seen the questions

but those did not seem directly related, albeit having a similar name.


Get this bounty!!!

#StackBounty: #reactjs #typescript `Cannot find module: "aliasedImport/File". Make sure this package is installed.` with alia…

Bounty: 200

EDIT: To comply with Stackoverflow guidelines and makes thing easy for all of us, I have submitted a small reproducible example that reproduces my bug:

https://github.com/shackra/stackoverflow-alias-bug


For an existing React project I used CRA, squashed most bugs now however I cannot make my aliases to work after debugging the problem for several hours:

npm run build

> frontend@0.1.0 prebuild /home/jorge/code/kue/fero/dev/frontend
> nps generate-build-version

nps is executing `generate-build-version` : nps genver
nps is executing `genver` : deno run --allow-read --allow-write generate-build-version.ts

> frontend@0.1.0 build /home/jorge/code/kue/fero/dev/frontend
> nps build

nps is executing `build` : craco build
craco:  *** Cannot find ESLint loader (eslint-loader). ***
Creating an optimized production build...

● Webpack █████████████████████████ building (11%) 12/16 modules 4 active
 css-loader › postcss-loader › src/App.css

Failed to compile.

./src/App.tsx
Cannot find module: 'pages/AdminLand'. Make sure this package is installed.

You can install this package by running: npm install pages/AdminLand.


The script called "build" which runs "craco build" failed with exit code 1 https://github.com/sezna/nps/blob/master/other/ERRORS_AND_WARNINGS.md#failed-with-exit-code
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! frontend@0.1.0 build: `nps build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the frontend@0.1.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/jorge/.npm/_logs/2020-11-29T02_52_51_308Z-debug.log

my package.json:

{
    "name": "frontend",
    "version": "0.1.0",
    "private": true,
    "dependencies": {
        "@casl/ability": "^4.1.6",
        "@casl/react": "^2.1.1",
        "@craco/craco": "^5.8.0",
        "@sentry/browser": "^5.27.6",
        "@testing-library/jest-dom": "^5.11.4",
        "@testing-library/react": "^11.1.0",
        "@testing-library/user-event": "^12.1.10",
        "@types/jest": "^26.0.15",
        "@types/node": "^12.0.0",
        "@types/react": "^16.14.2",
        "@types/react-dom": "^16.9.8",
        "antd": "^4.8.6",
        "axios": "^0.21.0",
        "classnames": "^2.2.6",
        "craco-antd": "^1.19.0",
        "currency.js": "^2.0.3",
        "file-saver": "^2.0.5",
        "jwt-decode": "^3.1.2",
        "lodash": "^4.17.20",
        "moment": "^2.29.1",
        "nps": "^5.10.0",
        "nps-utils": "^1.7.0",
        "print-js": "^1.5.0",
        "query-string": "^6.13.7",
        "react": "^17.0.1",
        "react-context-devtool": "^2.0.0",
        "react-cosmos": "^5.5.1",
        "react-dom": "^17.0.1",
        "react-router-dom": "^5.2.0",
        "react-scripts": "4.0.1",
        "typescript": "^4.0.3",
        "ulid": "^2.3.0",
        "url-regex": "npm:url-regex-safe@^1.0.2",
        "web-vitals": "^0.2.4"
    },
    "scripts": {
        "nps": "nps",
        "clean": "rm -rf build",
        "prebuild": "nps generate-build-version",
        "start": "nps start",
        "build": "nps build",
        "test": "nps test",
        "cosmos": "nps cosmos",
        "lint": "nps lint",
        "lint-fix": "nps lint.fix",
        "tsc": "nps tsc",
        "bump-patch": "nps bump-patch",
        "bump-minor": "nps bump-minor",
        "bump-major": "nps bump-major",
        "eject": "react-scripts eject"
    },
    "eslintConfig": {
        "extends": [
            "react-app",
            "react-app/jest"
        ]
    },
    "browserslist": {
        "production": [
            ">0.2%",
            "not dead",
            "not op_mini all"
        ],
        "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
        ]
    },
    "devDependencies": {
        "@types/classnames": "^2.2.11",
        "@types/file-saver": "^2.0.1",
        "@types/lodash": "^4.14.165",
        "@types/react-router-dom": "^5.1.6",
        "craco-alias": "^2.1.1",
        "eslint-plugin-simple-import-sort": "^6.0.1",
        "favicons-webpack-plugin": "^4.2.0",
        "webpack-bundle-analyzer": "^4.1.0",
        "webpackbar": "^5.0.0-3"
    }
}

and finally my craco.config.js:

const path = require('path')
// ...

process.env.BROWSER = 'none'

module.exports = {
  plugins: [
   // ...
  ],
  webpack: {
    // ...  
    resolve: {
      alias: {
        components: path.resolve(__dirname, './src/components/'),
        modules: path.resolve(__dirname, './src/modules/'),
        pages: path.resolve(__dirname, './src/pages/'),
        types: path.resolve(__dirname, './src/types/'),
        utils: path.resolve(__dirname, './src/utils/'),
      },
      extensions: ['.js', '.jsx', '.ts', '.tsx'],
    },
  },
  jest: {
    transformIgnorePatterns: [
      '/node_modules/(?!antd|@ant-design|rc-.+?|@babel/runtime).+(js|jsx)$',
    ],
    configure: {
      moduleNameMapper: {
        '^components(.*)$': '<rootDir>/src/components$1',
        '^modules(.*)$': '<rootDir>/src/modules$1',
        '^pages(.*)$': '<rootDir>/src/pages$1',
        '^types(.*)$': '<rootDir>/src/types$1',
        '^utils(.*)$': '<rootDir>/src/utils$1',
      },
    },
  },
}

This is how I extend my tsconfig.json:

{
    "compilerOptions": {
        "pretty": false,
        "jsx": "react",
        "baseUrl": "src"
    }
}

I provide the following for guidance, this is my project’s directory layout.

.
├── build
│   ├── icono.svg
│   ├── manifest.json
│   ├── meta.json
│   └── robots.txt
├── CHANGELOG.rst
├── CONTRIBUTING.md
├── cosmos.config.json
├── craco.config.js
├── default.conf
├── docker-compose.yml
├── Dockerfile
├── generate-build-version.ts
├── index.js
├── LICENSE
├── Makefile
├── package.json
├── package-lock.json
├── package-scripts.js
├── public
│   ├── icono.svg
│   ├── index.html
│   ├── manifest.json
│   ├── meta.json
│   └── robots.txt
├── README.md
├── replace-interface-with-decimal-type.el
├── src
│   ├── App.css
│   ├── App.tsx
│   ├── CacheBuster.tsx
│   ├── components
│   ├── cosmos.decorator.tsx
│   ├── index.tsx
│   ├── modules
│   │   ├── ability
│   │   ├── authorization
│   │   ├── invoice
│   │   ├── notification
│   │   └── resource
│   ├── pages
│   │   ├── AdminLand.tsx
│   ├── react-app-env.d.ts
│   ├── react-context-devtool.d.ts
│   ├── sentry.jsx
│   ├── serviceWorker.js
│   ├── styles
│   │   └── antd
│   ├── types
│   ├── utils
│   └── vendor.d.ts
├── tsconfig.custom.json
└── tsconfig.json

I tried using the babel resolver plugin without success. Any help dealing with this?


Get this bounty!!!

#StackBounty: #typescript #yarnpkg #netlify #lerna #yarn-workspaces Using UI Library as a Dependency for Web App on Netlify Monorepo (Y…

Bounty: 500

I have two apps, glowystuff-web, and glowy-ui. Glowy-UI is a shared UI lib, that I plan to use on other projects, kind of my own React Bootstrap.

Here’s the challenge. I have glowy-ui defined as a dependency in packages/glowystuff-web/package.json as follows:

{
 "dependencies": {
   "glowy-ui": "*"
 },
 "scripts": {
  "build": "gatsby build"
 }
}

Unless I run yarn build (which compiles using tsc to glowy-ui/lib) and commit the JS lib/ files to git (yuck!) I get errors like this build:

3:47:15 PM: failed Building production JavaScript and CSS bundles - 24.131s
3:47:15 PM: error Generating JavaScript bundles failed
3:47:15 PM: Can't resolve 'glowy-ui' in '/opt/build/repo/packages/glowystuff-web/src/components'
3:47:15 PM: If you're trying to use a package make sure that 'glowy-ui' is installed. If you're trying to use a local file make sure that the path is correct.

For context, these are the Best instructions I’ve found for Monorepos (with Yarn Workspaces) on Netlify:

https://community.netlify.com/t/difficulty-with-new-monorepo-deployment-options/4381/9

What’s unclear to me is how I get Netlify to know that building needs to happen. If I did this on packages/glowystuff-web/package.json:

"scripts": {
  "build": "yarn workspace glowy-ui build && gatsby build"
}

… then it seems like it would build the UI lib on every build of the main web app, glowystuff-web, even when there were no updates to the UI lib code.

A private, published NPM package for glowy-ui could be a workable option here, but my idea was to have a single GitHub repo with Yarn Workspaces, where I don’t need to publish. After all, why publish if all the files are available for reading?

So what’s the best approach, on Netlify/Yarn Workspaces, to make things build, but also take advantage of caching when appropriate?

Additional context on current builds – netlify.tomls:

We are using the code-as-config approach to Netlify builds. Here is current packages/glowystuff-web/netlify.toml:

[build]
  publish = "public/"
  command = "yarn build"

Glowy-UI is both the UI lib, and the accompanying storybook app, so here is current packages/glowy-ui/netlify.toml:

[build]
  publish = "storybook-static"
  command = "yarn build-storybook"


Get this bounty!!!

#StackBounty: #reactjs #typescript HTMLElement definition in typescript.lib/lib.dom.d.ts was overridden by @types/react/global.d.ts

Bounty: 150

enter image description here

The compiler find the definition of HTMLElement, but the definition from react/global.d.ts is taken instead of typescript/lib/lib.dom.d.ts.

Here’s the compiler error:

Property 'value' does not exist on type 'EventTarget'.  TS2339

Here are the differences:

In react/global.d.ts

interface Element { }

interface HTMLElement extends Element { }

In typescript/lib/lib.dom.d.ts

interface HTMLElement extends Element, GlobalEventHandlers, DocumentAndElementEventHandlers, ElementContentEditable, HTMLOrSVGElement, ElementCSSInlineStyle {
    accessKey: string;
    readonly accessKeyLabel: string;
    autocapitalize: string;
    dir: string;
    draggable: boolean;
    hidden: boolean;
    innerText: string;
    lang: string;
    readonly offsetHeight: number;
    readonly offsetLeft: number;
    readonly offsetParent: Element | null;
    readonly offsetTop: number;
    readonly offsetWidth: number;
    spellcheck: boolean;
    title: string;
    translate: boolean;
    click(): void;
    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
    removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
    removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}

So my question is: how to make the compiler choose typescript/lib/lib.dom.d.ts before the one from React? Any help would be greatly appreciated!

Edit: here’s the tsconfig.json, correctly referencing the TS lib:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "incremental": true, // Enable incremental compilation by reading/writing information from prior compilations to a file on disk
    "sourceMap": true, // Generate corrresponding .map file
    "declaration": true, // Generate corresponding .d.ts file
    "noUnusedLocals": true, // Report errors on unused locals
    "noUnusedParameters": true, // Report errors on unused parameters
    "jsx": "react"
  },
  "include": [
    "src"
  ]
}


Get this bounty!!!

#StackBounty: #javascript #typescript #visual-studio-code #console.log #vscode-debugger vscode debugger with typescript: what determine…

Bounty: 50

I’m using vscode to write some typescript, and I have set a breakpoint. When I open the Debug pane and ask it to evaluate an object, what is it doing to produce the string representation?

The reason I am asking is because I am using this solution to control the way that console.log renders an instance of a class, and it works great — but it doesn’t seem to impact the way the object is rendered in the debugger.

To be more specific, the below code (also available in the typescript sandbox here) results in the desired output from console.log. However, when I set a breakpoint just before the console.log line and evaluate myObj in the debugger, what’s displayed is

cls {property: 'property', hello: 'override', newProperty: 'new property'}

rather than

Greeter3Generated {property: 'property', hello: 'override', newProperty: 'new property'}

Code in question:

function classDecorator3<T extends { new (...args: any[]): {} }>(
  constructor: T
) {
  const cls = class extends constructor {
    newProperty = "new property";
    hello = "override";
  };
  Object.defineProperty(cls, 'name', {
    get: () => `${constructor.name}Generated`
  });
  return cls
}

@classDecorator3
class Greeter3 {
  property = "property";
  hello: string;
  constructor(m: string) {
    this.hello = m;
  }
}

const myObj = new Greeter3("world")
console.log(myObj);
//=>  Greeter3Generated: { "property": "property", "hello": "override", "newProperty": "new property" } 


Get this bounty!!!

#StackBounty: #php #node.js #angular #typescript Not able to pass JWT authorization using Angular8

Bounty: 250

Below php api script given by client when I run into local then Static data storing in api server successfully.

<?php
    //creating payload parameters:
    $classTitle = 'Demo Class on 3rd April, 2020';
    $classInfo = 'This is a demo class scheduled to understand API';
    $classDateTime = '2020-11-12 11:30 AM';
    $timezone = 'Asia/Kolkata';
    $classDuration = 15;
    $classRecording = 'yes';
    $classAutoStart = false;
    $recordingAutoStart = false;
    $classVideoRes = 720;


    /*xyz.com*/
    $apiKey = '12345';
    $secretKey = '12345';

    // Create token header as a JSON string
    $header = json_encode(['alg' => 'HS256','typ' => 'JWT']); // ensure to place first alg part and next typ part

    // Create token payload as a JSON string
    $payload = json_encode(['classTitle' => $classTitle ,'classInfo' => $classInfo ,'classDateTime' => $classDateTime ,'timezone' => $timezone ,'classDuration' => $classDuration ,'classRecording' => $classRecording ,'classAutoStart' => $classAutoStart ,'recordingAutoStart' => $recordingAutoStart ,'classVideoRes' => $classVideoRes ,'apiKey' => $apiKey]);

    // Encode Header to Base64Url String
    $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));

    // Encode Payload to Base64Url String
    $base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));

    // Create Signature Hash
    $signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secretKey , true);

    // Encode Signature to Base64Url String
    $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

    // creating JWT token variable
    $jwt_token = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;

    // creating authorization varibale
    $authorization = 'Bearer '.$jwt_token;

    ?>

    https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
    <script type="text/javascript">
        $.ajax
        ({
        type: "POST",
         url: 'https://xyz/client/schedule',
        contentType: 'application/json',
        data: JSON.stringify({
            "apiKey": "12345"
        }),
        dataType : 'json',
        headers: {
        'authorization': '<?php echo $authorization; ?>'
        },
        success: function(retval)
        {
        // alert(retval);
        console.log(retval);
        // var success = retval.success;
        }
        });
    </script>

Directly i pass parameters to above php api then also its not working, my senior told me you have to call above code from angular I wrote code but i am not able to store successfully below is my angular code.

Below is my model class

export class Schedule1 {

classTitle: string;
classInfo: string;
classDateTime: string;
timezone: string;
classDuration: number;
classRecording:string;
classAutoStart: boolean;
recordingAutoStart: boolean;
classVideoRes: number;
    
   constructor() {
    
      
   }

  }

Below is component.ts on button click passing static values

import { Schedule1 } from '../Models/Schedule1.model'


   Schedule1: Schedule1 = new Schedule1();

    addSchedule(scheduleForm: NgForm): void {

    //static data parameter passing
    this.Schedule1.classTitle='hi Class on 3rd April, 2020';
    this.Schedule1.classInfo= 'This is a demo class scheduled to understand API';
    this.Schedule1.classDateTime= '2020-11-12 11:30 AM';
    this.Schedule1.timezone= 'Asia/Kolkata';
    this.Schedule1.classDuration= 15;
    this.Schedule1.classRecording= 'yes';
    this.Schedule1.classAutoStart= false;
    this.Schedule1.recordingAutoStart= false;
    this.Schedule1.classVideoRes= 720;


    //const data = JSON.stringify(this.Schedule1);
    const data = { 
    apiKey: "dcbf187d-bdfe-431b-8f60-fa19bf51cd85", 
    data:  JSON.stringify(this.Schedule1)
    } 

    this.subscription = this.userSvc
    .fetchData("https: //xyz.com/client/schedule", data)
    .subscribe(
    data => {
    // Data on Success
    console.log("data", data);
    },
    error => {
    console.log("error", error);
    }
    );

    }

Below is service.ts

  fetchData(url: string, data: any): Observable<any> {
    const headers = {
    
    Authorization: "Bearer "+"1234",
     "My-Custom-Header": "foobar",
    contentType: "application/json"
    };

   return this.http.post(url, data, {
    headers
    });
   }

in console getting this error.

enter image description here


Get this bounty!!!

#StackBounty: #angular #typescript #visual-studio-code #tsconfig #tsconfig-paths VSCode / tslint does not resolve paths in tsconfig.json

Bounty: 100

vscode is somehow not honoring my tsconfig.json (for a couple of weeks now, it has been different. eiter my bad or vscode update…)

{
"compileOnSave": false,
"compilerOptions": {
    "baseUrl": "./",
    "paths": {
        "@foo-animation/*": [
            "src/app/animation/*"
        ],
        ...

enter image description here

Respectively in the Problems tab:

Cannot find module ‘@foo-animation/animation-micro’ or its corresponding type declarations. ts(2307)

Regular base paths (like @angular/core) are properly resolved, just my ‘custom’ ones are the problem…

Compiling, Building, Running… all works like a charm. So I believe from an angular/typescript-perspective everything is fine. (Also, my fellow developers using IntelliJ have no issues…) So it seems to boild down to „telling vscode (or tslint within) about it“…. :-/

My tsconfig.json sits in the root-folder of the project. the only thing is, that I use another tsconfig.app.json, which includes above tsconfig.json.

enter image description here

So is there a way to tell vscode (resp. tslint) where to look for it’s tsconfig.json (to encourage parsing those paths) ?

This SO question and this VSCode github issue might be related, but I still don’t know what to do.


Get this bounty!!!

#StackBounty: #javascript #typescript #lit-element @composi/gestures swipe with lit element

Bounty: 50

i am trying to implement gestures with my lit-element using the library: https://github.com/composi/gestures

at the top of my file i have the following:

import { gestures } from '@composi/gestures'
gestures();

Then in my render function i have:

render() {
 return html`
  <div class="tablet-menu " id="tablet-menu-T">
  <div class="tablet-menu-body" on-swipe="${this._swipe}">
....

However the _swipe function is never called. so it doesnt seem that it registers the swipe command.

Can anyone tell me what ive done wrong?


Get this bounty!!!

#StackBounty: #javascript #security #authentication #typescript #angular-2+ Angular Frontend login logic

Bounty: 50

This is a follow-up to this question Node.js backend login logic. I wrote the following login Angular frontend logic for my Node.js Backend (see the previous question above). Is it any good in terms of security, efficiency, building, async/sync, logging? SECURITY is my main concern.
On in a prettier format the question would be:

  • SECURITY: Is my website secure in any way, shape, or form? I’m wondering if I could implement any security measures other than the ones that are built in to the methods provided by Angular. Isn’t the transmission of the password in plaintext a security issue? What about XSS and similar troubles? Can’t my login just simply be circumvented? That would be a critical mistake.
  • EFFICIENCY: Is how I’m checking usernames and password efficient? Is there any better way to do this?
  • BUILDING: Is how I loaded my website acceptable?
  • ASYNC/SYNC: I know I preform async and sync calls at the same time. Is there any problem to this?
  • LOGGING: I log all connections to the server, and all login attempts. Is this a good practice, or am I overdoing what logging is supposed to accomplish?
  • MISC: Are there any mistakes in the play between the backend and frontend? If I forgot some other important points about the code I would be glad if you mentioned them as well
    (Source: Login Server with Node.js)

My code:

authentication.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { environment } from '../../environments/environment';
import { User } from '../models/user.model';
import { Router } from '@angular/router';
import { GlobalDataService } from './global-data.service';

@Injectable({ providedIn: 'root' })
export class AuthenticationService {
    constructor(private http: HttpClient,
                private router: Router, public DataService: GlobalDataService) {
        this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
        this.currentUser = this.currentUserSubject.asObservable();
        this.LoggedIn = true;
    }
    public LoggedIn = true;
    public get currentUserValue(): User {
        return this.currentUserSubject.value;
    }
    private currentUserSubject: BehaviorSubject<User>;
    public currentUser: Observable<User>;
  getRedirectUrl() {
    throw new Error('Method not implemented.');
  }
  isUserLoggedIn() {
    throw new Error('Method not implemented.');
  }

  login(email: string, password: string) {
    return this.http.post<any>(`${environment.apiUrl}/api/login`, { email, password }, {withCredentials: true})
        .pipe(map(user => {
            // login successful if there's a jwt token in the response
            if (user && user.token) {

                // store user details and jwt token in local storage to keep user logged in between page refreshes
                // https://dev.to/rdegges/please-stop-using-local-storage-1i04
                localStorage.setItem('currentUserToken', JSON.stringify(user));
                this.currentUserSubject.next(user);
            }
            // set firstname & email of loggedin user
            this.DataService.loggedinfirstname = user['firstname'];
            this.DataService.loggedinemail = user['eMail'];
            this.redirtoDashboard();
            this.Toolbar();
            this.DataService.prefillSenderData();
            return user;
        }));
  }

  redirtoDashboard() {
      this.router.navigate(['order']);
  }

  Toolbar() {
      this.LoggedIn = !this.LoggedIn;
  }
}

login.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { first } from 'rxjs/operators';

import { AuthenticationService } from '../services/authentication.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  returnUrl: string;
  loginForm: FormGroup;
  submitted = false;
  error = '';
  loading = false;
  public errorMsg = 'Please login to continue.';
  public redirected: boolean;
  public utm_source: string;

  constructor(private router: Router, private formBuilder: FormBuilder,
              private authenticationService: AuthenticationService, private activatedRoute: ActivatedRoute) {
      if (this.authenticationService.currentUserValue) {
        this.router.navigate(['order']);
    }
      this.activatedRoute.queryParams.subscribe(params => {
      const param = params['utm_source'];

      if (param === 'order' || param === 'work-document' || param === 'profile') {
        this.redirected = true;
        this.utm_source = param;
      } else {
        this.redirected = false;
      }
  });
  }

  ngOnInit(): void {
    this.loginForm = this.formBuilder.group({
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(6)]]
  });
  }

// convenience getter for easy access to form fields
get f() { return this.loginForm.controls; }

  onSubmit(loginsubmit) {
    this.submitted = true;
    // stop here if form is invalid
    if (this.loginForm.invalid) {
        return console.log('LoginForm Invalid');
    }
    this.loading = true;
    this.authenticationService.login(this.f.email.value, this.f.password.value)
        .pipe(first())
        .subscribe(
            data => {
                if (this.redirected) {
                  this.router.navigate([this.utm_source]);
                } else {
                  this.router.navigate(['order']);
                }

            },
            error => {
                console.log('Login->authservice->err: ', error);
                this.error = error;
                this.loading = false;
            });
}

}

login.component.html:

<div class="container">
  <div class="row">
    <div class="col-sm-9 col-md-7 col-lg-5 mx-auto">
      <div class="card card-signin my-5">
        <div class="card-body">
          <h5 class="card-title text-center">Login</h5>
          <br>
            <form [formGroup]="loginForm" class="form-signin" (ngSubmit)="onSubmit(this.loginForm.value)">
              <div class="form-label-group">
                <input #userName formControlName="email" type="text" id="inputUser" class="form-control" placeholder="E-Mail" required autofocus [ngClass]="{ 'is-invalid': submitted && f.email.errors }">
                  <div *ngIf="submitted && f['email'].errors" class="invalid-feedback">
                    <div *ngIf="f['email'].errors.required">E-Mail is required</div>
                  </div>
                </div>
                <br>
                  <div class="form-label-group">
                    <input #password type="password" formControlName="password" id="inputPassword" class="form-control" placeholder="Password" required [ngClass]="{ 'is-invalid': submitted && f.password.errors }">
                      <div *ngIf="submitted && f['password'].errors" class="invalid-feedback">
                        <div *ngIf="f['password'].errors.required">Password is required</div>
                      </div>
                    </div>
                    <br>
                      <div *ngIf="redirected">
                        <mat-error>
                          <p class="alert alert-danger">
                            {{errorMsg}}
                          </p>
                        </mat-error>
                      </div>
                      <button [disabled]="!loginForm.valid" class="btn btn-dark btn-block" id="loginSubmit" type="submit">Login</button>
                      <div class="forgot-password-link">
                        <a routerLink="/forgot-password">Forgot password</a>
                      </div>
                    </form>
                  </div>
                </div>
              </div>
            </div>
          </div>

```


Get this bounty!!!