\( \newcommand{\N}{\mathbb{N}} \newcommand{\R}{\mathbb{R}} \newcommand{\C}{\mathbb{C}} \newcommand{\Q}{\mathbb{Q}} \newcommand{\Z}{\mathbb{Z}} \newcommand{\P}{\mathcal P} \newcommand{\B}{\mathcal B} \newcommand{\F}{\mathbb{F}} \newcommand{\E}{\mathcal E} \newcommand{\brac}[1]{\left(#1\right)} \newcommand{\abs}[1]{\left|#1\right|} \newcommand{\matrixx}[1]{\begin{bmatrix}#1\end {bmatrix}} \newcommand{\vmatrixx}[1]{\begin{vmatrix} #1\end{vmatrix}} \newcommand{\lims}{\mathop{\overline{\lim}}} \newcommand{\limi}{\mathop{\underline{\lim}}} \newcommand{\limn}{\lim_{n\to\infty}} \newcommand{\limsn}{\lims_{n\to\infty}} \newcommand{\limin}{\limi_{n\to\infty}} \newcommand{\nul}{\mathop{\mathrm{Nul}}} \newcommand{\col}{\mathop{\mathrm{Col}}} \newcommand{\rank}{\mathop{\mathrm{Rank}}} \newcommand{\dis}{\displaystyle} \newcommand{\spann}{\mathop{\mathrm{span}}} \newcommand{\range}{\mathop{\mathrm{range}}} \newcommand{\inner}[1]{\langle #1 \rangle} \newcommand{\innerr}[1]{\left\langle #1 \right \rangle} \newcommand{\ol}[1]{\overline{#1}} \newcommand{\toto}{\rightrightarrows} \newcommand{\upto}{\nearrow} \newcommand{\downto}{\searrow} \newcommand{\qed}{\quad \blacksquare} \newcommand{\tr}{\mathop{\mathrm{tr}}} \newcommand{\bm}{\boldsymbol} \newcommand{\cupp}{\bigcup} \newcommand{\capp}{\bigcap} \newcommand{\sqcupp}{\bigsqcup} \newcommand{\re}{\mathop{\mathrm{Re}}} \newcommand{\im}{\mathop{\mathrm{Im}}} \newcommand{\comma}{\text{,}} \newcommand{\foot}{\text{。}} \)

Friday, March 27, 2020

webpack config

https://github.com/Microsoft/TypeScript-Babel-Starter
const path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    path: __dirname,
    filename: "app.js"
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
            plugins: [
              [
                "@babel/plugin-transform-runtime",
                {
                  regenerator: true
                }
              ]
            ]
          }
        }
      }
    ]
  },
  target: "node",
  node: {
    __dirname: false,
    __filename: false
  },
  externals: {
    fs: "commonjs fs"
  },
  mode: "development"
};

Sunday, March 22, 2020

Data Validation using Decorator in Typescript

In index.html we have
<form>
  <input type="text" placeholder="Course Title" id="title" />
  <input type="text" placeholder="Price" id="price" />
  <button type="submit">Submit</button>
</form>
and inside our ts (transpiled into js file and link it into our index.html), we write:
enum Validation {
  required = "required",
  positive = "positive"
}

interface ValidatorConfig {
  [property: string]: {
    [validatableProp: string]: Validation[]; //e.g., [Validation.required, Validation.positive]
  };
}

const registeredValidators: ValidatorConfig = {};

function Required(target: any, propName: string) {
  //we don't have propertyDescriptor for property, it exists only for methods
  registeredValidators[target.constructor.name] = {
    ...registeredValidators[target.constructor.name],
    [propName]: [Validation.required]
  };
}

function Positive(target: any, propName: string) {
  registeredValidators[target.constructor.name] = {
    ...registeredValidators[target.constructor.name],
    [propName]: [Validation.positive]
  };
}

function validate(obj: any) {
  const objValidatorConfig = registeredValidators[obj.constructor.name];
  if (!objValidatorConfig) {
    return true;
  } else {
    let validated = true;
    for (const prop in objValidatorConfig) {
      for (const validator of objValidatorConfig[prop]) {
        if (validator === (Validation.required as string)) {
          console.log("run?");
          validated = validated && obj[prop].trim().length > 0;
        }
        if (validator === (Validation.positive as string)) {
          validated = validated && obj[prop] > 0;
        }
      }
    }
    return validated;
  }
}

class Course {
  @Required
  public title: string;

  @Positive
  public price: number;

  constructor(t: string, p: number) {
    this.title = t;
    this.price = p;
  }
}

const courseForm = document.querySelector("form")!;
courseForm.addEventListener("submit", e => {
  e.preventDefault();
  const titleEl = document.getElementById("title") as HTMLInputElement;
  const priceEl = document.getElementById("price") as HTMLInputElement;
  const title = titleEl.value;
  const price = +priceEl.value;
  const newCourse = new Course(title, price);

  if (!validate(newCourse)) {
    alert("Invalid input, please try again!");
    return;
  }

  console.log(newCourse);
});

Sunday, March 15, 2020

Wordpress Study Notes

Extension in VSCode

  • I install beautify for cleaning up the indentations of both php and html code at the same time.
  • I also install PHP Intelephense to give auto completion on html tag.

Prelude

Hierarchy of wordpress php files: Assume that we have a post type called "program", as registered by using
 
<?php 
function university_post_types()
{
  //Program Post Type
  register_post_type("program", array(
  'supports' => array('title', 'editor'),
  'rewrite'=>array('slug'=>'programs'),
  'has_archive' => true,
  'public' => true,
  'labels' => array(
  'name' => 'Programs',
  'add_new_item'=>'Add New Program',
  'edit_item'=>'Edit Program',
  'all_items'=> 'All Programs',
  'singular_name' => 'Program'
  ),
  'menu_icon' => 'dashicons-awards'
  ));
}

add_action("init", "university_post_types");
?>
inside \wp-content\mu-plugins\*.php  (mu stands for "must-use") , then we get:


in our dashboard. This is a kind of customized post type, therefore we will create a php file that is dedicated to customizing post of type "program".

Wednesday, March 4, 2020

php installation

  1. Follow the link to install php
    https://www.youtube.com/watch?v=4_-12QSaaFg
  2. Following this to install xampp:
    https://www.youtube.com/watch?v=TjFRTkw6GDQ
  3. visual studio plug-in that I have used:
    1. phpfmt - PHP formatter
    2. Format HTML in PHP
    refer to my config file sent in gmail

Tuesday, March 3, 2020

Factory Design Pattern in Typescript

Javascript is not enough to implement ordinary factory design patternt that I want to mimic from C#, therefore I try to do it on Typescript, though nested class declaration is still not that straight forward in typescript:
class Point {
  x: number;
  y: number;

  private constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }

  static Factory = class {
    static pointXY(x: number, y: number) {
      return new Point(x, y);
    }
    static pointPolar(r: number, theta: number) {
      return new Point(
        r * Math.cos((theta * Math.PI) / 180),
        r * Math.sin((theta * Math.PI) / 180)
      );
    }
  };
}
now we can create our point by calling
const pt = Point.Factory.pointXY(10, 20);

Monday, February 17, 2020

Certbot

SSH into our ubuntu device and do the following. The commands are subject to changes, we should use all latest relevant commands from certbot's website.
$ sudo apt update
$ clear
$ sudo apt install apache2
$ cd /etc/apache2/sites-available/
$ clear
$ ls
$ sudo vi ridiculous-inc.com.conf
$ cd /var/www
$ sudo git clone https://github.com/ridiculous-ijquery-todo.git ridic
$ sudo a2ensite ridiculous-inc.com.conf 
$ sudo service apache2 restart
$ sudo apt-get update
$ clear
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ clear
$ sudo apt-get update
$ sudo apt-get install python-certbot-apache 
$ clear
$ sudo certbot --apache
$ history
and
<VirtualHost *:80>
    DocumentRoot /var/www/ridic
    ServerName ridiculous-inc.com
    <Directory "/var/www/ridic">
        allow from all
        AllowOverride All
        Order allow,deny
        Options +Indexes
    </Directory>
</VirtualHost>
To redirect request to port 80 to other internal port we use the following setting of virtualhost:
<VirtualHost *:80>
    ServerName api.screencapdictionary.com
    <Location "/">
        ProxyPreserveHost On
        ProxyPass http://localhost:5000/
        ProxyPassReverse http://localhost:5000/
    </Location>
</VirtualHost>

Saturday, February 8, 2020

Git command that I should know

Configuration

git config --global --edit
This will open the .gitconfig file by our default editor. Make changes, save, and close the editor, changes will take place. To view the changes:
git config --global --list

Branches

List out all branches:
git branch -a
Create new branch:
git branch mynewbranch
switch to new branch:
git checkout mynewbranch
Rename a branch (-m for move, as in mv in bash command):
 git branch -m mynewbranch newbranch
Delete a branch:
 git branch -d newbranch

Specific branch

git clone a specific branch instead of all the branches and checkout specific one. For example, in my private repo I want to clone the "forth-branch" only, then write:
git clone --single-branch --branch forth-branch https://github.com/machingclee/2020-English-Learning-Website.git
without --single-branch the above will fetch all branches and checkout the forth-branch.

P4Merge Configuration

git config --global merge.tool p4merge
git config --global mergetool.p4merge.path "C:/Program Files/Perforce/p4merge.exe"
git config --global mergetool.prompt false
git config --global diff.tool p4merge
git config --global difftool.p4merge.path "C:/Program Files/Perforce/p4merge.exe"
git config --global difftool.prompt false
and git config --global --list to double check the configuration:
core.editor="C:\Users\Ching-Cheong Lee\AppData\Local\Programs\Microsoft VS Code\Code.exe" --wait
user.name=James Lee
user.email=machingclee@gmail.com
color.ui=true
merge.tool=p4merge
mergetool.p4merge.path=C:/Program Files/Perforce/p4merge.exe
mergetool.prompt=false
diff.tool=p4merge
difftool.p4merge.path=C:/Program Files/Perforce/p4merge.exe
difftool.prompt=false