exports.up = function(knex, Promise) { return knex.schema .createTable('customers', function(table) { table.increments('id').primary().unique() table.string('name') table.string('phone1') table.string('phone2') table.string('city') table.string('agreement') table.timestamp('created_at').defaultTo(knex.fn.now()) table.timestamp('updated_at').defaultTo(knex.fn.now()) }) .createTable('users', function(table) { table.increments('id').primary().unique() table.string('name') table.string('password') table.boolean('superuser') table.string('gecos') table.timestamp('created_at').defaultTo(knex.fn.now()) table.timestamp('updated_at').defaultTo(knex.fn.now()) }) } exports.down = function(knex, Promise) { return knex.schema .dropTable('users') .dropTable('customers') }
'use strict' module.exports = function(knex) { var find = function(params) { return knex .select([ 'customers.*', ]) .from('customers') .where( 'customers.phone1', '~', params.phone1 ) .orWhere( 'customers.phone2', '~', params.phone2 ) .orWhere( 'customers.name', '~', params.name ) .limit(50) } var get = function(params) { return knex .select([ 'customers.*', ]) .from('customers') .where({ 'customers.id': params.id, }) } var create = function(params) { return knex .insert({ name: params.name, phone1: params.phone1, phone2: params.phone2, city: params.city, agreement: params.agreement, }) .into('customers') } return { modelName: "customers", find: find, get: get, create: create } }
'use strict' module.exports = function(knex) { var login = function(params) { return knex .select([ 'users.name', 'users.gecos', 'users.id', 'users.superuser' ]) .from('users') .where({ 'users.name': params.name, 'users.password': params.password, }) } var check = function(params) { return knex .select([ 'users.id', ]) .from('users') .where({ 'users.id': params.id }) } return { modelName: "login", login: login, check: check } }
'use strict' module.exports = function(knex) { var list = function(params) { return knex .select([ 'users.*', ]) .from('users') .orderBy('users.name') } var find = function(params) { return knex .select([ 'users.*', ]) .from('users') .where({ 'users.name': params.name, }) .orderBy('users.name') } var get = function(params) { return knex .select([ 'users.*', ]) .from('users') .where({ 'users.id': params.id, }) .orderBy('users.name') } var create = function(params) { return knex .insert({ gecos: params.gecos, name: params.name, password: params.password, superuser: params.superuser, }) .into('users') } var update = function(params) { return knex .update({ gecos: params.gecos, name: params.name, password: params.password, superuser: params.superuser, }) .from('users') .where({ id: params.id }) } var drop = function(params) { return knex .del() .from('users') .where({ id: params.id }) } return { modelName: "users", list: list, find: find, create: create, update: update, drop: drop } }
module.exports = function nocors() { return function _nocors(req, res, next) { res.header('Access-Control-Allow-Origin', '*') res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') next() } }
'use strict' module.exports = function(knex) { const model = require('models/customers')(knex) const router = require('routers/exrouter')(model) return router }
'use strict' const lodash = require('lodash') const error = { invalidRequest: { jsonrpc: "2.0", error: { code: -32600, message: "Invalid Request" }, id: null }, parseError: { jsonrpc: "2.0", error: { code: -32700, message: "Parse error" }, id: null }, methodNotFound: { jsonrpc: "2.0", error: { code: -32601, message: "Method not found" }, id: 1 }, internalError: { jsonrpc: "2.0", error: { code: -32603, message: "Internal error" }, id: 0 } } module.exports = function(model) { const express = require('express') const router = express.Router() function responder(req, res) { console.log({ body: req.body }) if(!lodash.has(req, 'body.method')) { res.send(error.invalidRequest) return } if(!lodash.has(req, 'body.id')) { res.send(error.invalidRequest) return } if(!lodash.has(req, 'body.params')) { res.send(error.invalidRequest) return } if (!lodash.isString(req.body.method)) { res.send(error.invalidRequest) return } if (!lodash.isString(req.body.id) && !lodash.isNumber(req.body.id)) { res.send(error.invalidRequest) return } if (typeof(req.body.params) === 'undefined') { res.send(error.invalidRequest) return } if (typeof(model[req.body.method]) !== 'function') { res.send(error.methodNotFound) return } const method = req.body.method var params = req.body.params const id = req.body.id if (method === 'check') { if (lodash.has(req, 'session.userId')) { params = { id: req.session.userId } } else { params = { id: -1 } } } var modelPromise = model[method](params) modelPromise .then(function(result) { if (method === 'login' && lodash.has(result, '[0].id')) { req.session.userId = result[0].id req.session.userProfile = result[0] } if (method === 'check') { console.log({ checkResult: result }) if (lodash.has(req, "session.userId") && lodash.has(result, "[0].id")) { result = true } else { result = false } } res.send({ jsonrpc: "2.0", result: result, id: id }) }) .catch(function(err) { console.log(err) res.send({ jsonrpc: "2.0", error: { code: -32603, message: "Internal error" }, id: id }) }) } router.post('/', responder) return router }
'use strict' module.exports = function(knex) { const model = require('models/login')(knex) const router = require('routers/exrouter')(model) return router }
'use strict' module.exports = function(knex) { const model = require('models/users')(knex) const router = require('routers/exrouter')(model) return router }
exports.seed = function(knex, Promise) { var rows = [] rows.push({"id":0,"name":"Borodin Oleg","phone1":"79520587264","phone2":"79520587232","city":"Kenigsberg","agreement":"SPN1645","created_at":"2018-12-13T23:36:20.925Z","updated_at":"2018-12-13T23:36:20.925Z"}) console.log(rows.length) var chunkSize = 50 return knex('customers').del() .then(function() { return knex.batchInsert('customers', rows, chunkSize) }) }
exports.seed = function(knex, Promise) { var rows = [] rows.push({"id":5,"name":"qwerty","password":"12345","superuser":true,"gecos":"Zurb Gnorb","created_at":"2018-11-25T08:36:32.344Z","updated_at":"2018-11-25T08:36:32.344Z"}) rows.push({"id":2,"name":"kokkolo","password":"12345","superuser":false,"gecos":"Kokkolo Lokkalo","created_at":"2018-12-14T01:36:38.706Z","updated_at":"2018-12-14T01:36:38.706Z"}) rows.push({"id":1,"name":"user","password":"12345","superuser":false,"gecos":"Anre Brown","created_at":"2018-12-15T08:55:23.180Z","updated_at":"2018-12-15T08:55:23.180Z"}) console.log(rows.length) var chunkSize = 50 return knex('users').del() .then(function() { return knex.batchInsert('users', rows, chunkSize) }) }
const child_process = require('child_process') module.exports = function(nodeBin) { function child(exe, args, env) { const child = child_process.spawn(exe, args, { detached: true, stdio: ['ignore', 'ignore', 'ignore'], env: env }) child.unref() return child } if (process.env.__daemon) { return process.pid } process.env.__daemon = true var args = [].concat(process.argv) var node = args.shift() var env = process.env child(node, args, env) return process.exit() }
const path = require('path') const fs = require('fs') const util = require('util') const exmkdir = require('exmkdir') module.exports = function(logDir) { exmkdir(logDir) if (!exmkdir(logDir)) { console.log('Cannot write to log directory ' + logDir + '. Exit process.') process.exit(1) } var consoleLog = function(data) { var date = new Date().toISOString() const logFile = fs.createWriteStream(logDir + '/debug.log', {flags : 'a'}) const logStdout = process.stdout logFile.write(date + ' ' + util.format(data) + '\n') logStdout.write(date + ' ' + util.format(data) + '\n') } return consoleLog }
var fs = require('fs') module.exports = function(dir) { var dummyFile = dir + '/.dummy' if (fs.existsSync(dir)) { try { var fd = fs.openSync(dummyFile, 'w') fs.writeSync(fd, process.pid) fs.closeSync(fd) fs.unlinkSync(dummyFile) return true } catch (err) { return false } } if (!fs.existsSync(dir)) { try { fs.mkdirSync(dir) return true } catch { return false } } }
'use strict' var fs = require('fs') var path = require('path') var exmkdir = require('exmkdir') var create = function(pidFile) { var pidDir = path.basename(path.dirname(pidFile)) var _write = function(path) { try { var fd = fs.openSync(path, 'w') } catch (err) { return false; } fs.writeSync(fd, process.pid) fs.closeSync(fd) return true } if (!exmkdir(pidDir)) { console.log('Cannot write to directory ' + pidDir + '. Exit process.') process.exit(1) } if (!_write(pidFile)) { console.log('Cannot write pid file ' + pidFile) process.exit(1) } } var drop = function(path) { try { fs.unlinkSync(path); return true; } catch (err) { return false; } } module.exports = { create: create, drop: drop }
const expid = require('expid') module.exports = function(pidFile) { function _exit() { expid.drop(pidFile) setTimeout(function() { process.exit(0) }, 100) } process.on('SIGINT', _exit) process.on('SIGTERM', _exit) process.on('uncaughtException', function (err) { if (err) { console.log("caughtException but no error msg" + err.stack) setTimeout(function() { process.exit(1) }, 500) } }) }
module.exports = { nodeBin: '/usr/local/bin/node', appDir: '/home/user/expresso/backend', publicDir: '/home/user/expresso/backend/public', uploadDir: '/home/user/expresso/backend/uploads', port: 3100, address: '127.0.0.1', runUser: 'ziggi', runGroup: 'wheel', logDir: '/home/user/expresso/backend/logs', pidFile: '/home/user/expresso/backend/run/pid', runDir: '/home/user/expresso/backend/run' }
#!/usr/bin/env node 'use strict' const fs = require('fs') const readline = require('readline') const knexfile = require('./knexfile') const knex = require('knex')( knexfile.development ) const customers = require('./models/customers')(knex) var rd = readline.createInterface({ input: fs.createReadStream('customers.csv'), console: false }) function phoneNormalize(phone) { //if (phone.length === 10) { // phone = '7' + phone //} phone = phone.replace(/[\-.()]/g, '') phone = phone.split(' ')[0] return phone } var rows = [] //City,Full Name,Phone2,Phone1,Id // 0 1 2 3 4 rd.on('line', (line) => { var arr = line.split(',') var customer = { agreement: arr[4].trim(), name: arr[1].trim(), phone1: arr[2].trim(),//.replace(/[()\-.+]/g, ''), phone2: arr[3].trim(),//.replace(/[()\-.+]/g, ''), city: arr[0].trim() + '', //email: arr[6].trim() + '' } customer.phone1 = phoneNormalize(customer.phone1) customer.phone2 = phoneNormalize(customer.phone2) //console.log(customer) rows.push(customer) }) rd.on('close', () => { console.log({ len: rows.length }) var chunkSize = 50 knex.batchInsert('customers', rows, chunkSize) .returning('id') .then(function(ids) { }) .catch(function(err) { console.log(err) }) .finally(function() { knex.destroy(); }) })
'use strict' const exconfig = require('exconfig') const path = require('path') const fs = require('fs') const util = require('util') const lodash = require('lodash') const minimist = require('minimist') var argv = minimist(process.argv.slice(2)) if (argv.help) { console.log('Expresso sample web application') console.log('Usage: expresso [options]') console.log(' --daemon daemonize process') process.exit() } //*** make log ***= var exlog = require('exlog')(exconfig.logDir) console.log = exlog console.error = exlog // *** throw *** //throw new Error('Boum!') // *** attach express plugins *** const express = require('express') const helmet = require('helmet') const cookieParser = require('cookie-parser') const bodyParser = require('body-parser') const compression = require('compression') const responseTime = require('response-time') const morgan = require('morgan') const lowercasePaths = require('express-lowercase-paths') const excors = require('excors') const app = express() var formatStr = ':date[iso] :remote-addr :method :url :status :res[content-length] :res[content-type] :response-time ms' var accessLog = fs.createWriteStream(exconfig.logDir + '/access.log', { flags: 'a' }) app.use(morgan(formatStr, { stream: accessLog })) app.use(morgan(formatStr)) app.use(excors()) app.use(compression()) app.use(lowercasePaths()) app.use(helmet()) app.use(express.static(exconfig.publicDir)) app.use(cookieParser()) app.use(bodyParser.json()) app.use(responseTime()) // *** create session *** const session = require('express-session') const FileStore = require('session-file-store')(session) app.use(session({ store: new FileStore({ path: exconfig.runDir }), name: 'session', secret: 'efwe987ysdf9fsd69f9ds', resave: false, rolling: true, saveUninitialized: true, cookie: { secure: false, maxAge: 3600 * 60 * 1000, httpOnly: false } })) // *** create knex shared object *** const knexfile = require('knexfile') const knex = require('knex')(knexfile.development) // *** set routes *** var login = require('./routers/login')(knex) app.use('/api/login', login) app.use(function(req, res, next) { if (typeof(req.session.userId) != 'undefined') { req.session.touch() next() } else { res.sendFile(path.join(exconfig.appDir, '/public/index.html')) } }) var users = require('./routers/users')(knex) app.use('/api/users', users) var customers = require('./routers/customers')(knex) app.use('/api/customers', customers) app.get('/*', function(req, res) { res.sendFile(path.join(exconfig.appDir, '/public/index.html')) }) // *** daemonize process *** const exdaemon = require('exdaemon') if(argv.daemon) { exdaemon() } // *** write pid file *** const expid = require('expid') expid.create(exconfig.pidFile) // *** signal ans exeption handling *** const exsig = require('exsig') exsig(exconfig.pidFile) // *** listen socket *** const cluster = require('cluster') if (cluster.isMaster) { var cpuCount = require('os').cpus().length + 1 for (var i = 0; i < cpuCount; i += 1) { cluster.fork(); } } else { app.listen(exconfig.port, exconfig.address, null, function() { try { process.setgid(exconfig.runGroup) process.setuid(exconfig.runUser) } catch (err) { console.log('Cannot change process user and group') process.exit(1) } }) }
var path = require('path') module.exports = { development: { //debug: true, client: 'pg', connection:'postgres://pgsql@localhost/expresso', useNullAsDefault: true, migrations: { directory: __dirname + '/migrations' }, seeds: { directory: __dirname + '/seeds' }, //pool: { // min: 0, // max: 10 //}, //acquireConnectionTimeout: 10000 }, staging: { client: 'pg', connection:'postgres://localhost/expresso', useNullAsDefault: true, migrations: { directory: __dirname + '/migrations' }, seeds: { directory: __dirname + '/seeds' } }, production: { client: 'pg', connection:'postgres://localhost/expresso', useNullAsDefault: true, migrations: { directory: __dirname + '/migrations' }, seeds: { directory: __dirname + '/seeds' } } }
#!/usr/bin/env node 'use strict' Object.defineProperty(Date.prototype, 'timestamp', { value: function() { function pad2(n) { return (n < 10 ? '0' : '') + n; } return this.getFullYear() + pad2(this.getMonth() + 1) + pad2(this.getDate()) + pad2(this.getHours()) + pad2(this.getMinutes()) + pad2(this.getSeconds()); } }); const timestamp = new Date().timestamp() const exconfig = require('./exconfig') const knexfile = require(exconfig.appDir + '/knexfile') const knex = require('knex')(knexfile.development) const fs = require('fs') //var tableName = 'domains' var header = function(tableName) { return ` exports.seed = function(knex, Promise) { var rows = [] ` } var footer = function(tableName) { return ` console.log(rows.length) var chunkSize = 50 return knex('${tableName}').del() .then(function() { return knex.batchInsert('${tableName}', rows, chunkSize) }) } ` } var tables = [ 'users', 'customers' ] tables.forEach(function(item) { console.log('export table ' + item) knex .select() .from(item) .then(function(result) { var out = fs.createWriteStream('./seeds/' + timestamp + '_' + item + '.js', {flags : 'w'}) out.write(header(item) + '\n') result.forEach(function(item) { out.write(' rows.push(' + JSON.stringify(item) + ')\n') }) out.write(footer(item) + '\n') out.close() }) .finally(function() { knex.destroy(); }) })
<div id="app-footer"> <div class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-8"> <hr /> <p class="text-center"> <small>Made by <a href="http://wiki.unix7.org">Borodin Oleg</a></small> </p> </div> </div> </div> </div>
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-footer', templateUrl: './app-footer.component.html', styleUrls: ['./app-footer.component.scss'] }) export class AppFooterComponent implements OnInit { constructor() { } ngOnInit() { } }
<div id="app-header" class="margin-bottom-2"> <div class="top-bar" id="top-bar"> <div class="top-bar-left" *ngIf="loginService.isSuperuser()"> <ul class="dropdown menu" data-dropdown-menu> <li><a href="#"><i class="my-menu-icon"></i></a></li> <li class="menu-text">NgII <i class="fi-sheriff-badge" style="font-size: 1.2em;"></i></li> <li> <a href="#">Units</a> <ul class="menu hover"> <li><a routerLink="/customers">Customers</a></li> <li><a routerLink="/users">Users</a></li> <li><a routerLink="/">Home</a></li> </ul> </li> <li> <a (click)="loginService.logout()"> <i class="fi-power" style="font-size: 1.3em;"></i> </a> </li> </ul> </div> <div class="top-bar-left" *ngIf="loginService.isUser() && !loginService.isSuperuser()"> <ul class="dropdown menu" data-dropdown-menu> <li><a href="#"><i class="my-menu-icon"></i></a></li> <li class="menu-text">NgII</li> <li> <a href="#">Units</a> <ul class="menu hover"> <li><a routerLink="/customers">Customers</a></li> <li><a routerLink="/">Home</a></li> </ul> </li> <li> <a (click)="loginService.logout()"> <i class="fi-power" style="font-size: 1.3em;"></i> </a> </li> </ul> </div> <div class="top-bar-left" *ngIf="!loginService.isLogin()"> <ul class="dropdown menu" data-dropdown-menu> <li><a href="#"><i class="my-menu-icon"></i></a></li> <li class="menu-text">NgII</li> <li> <a href="#">Units</a> <ul class="menu hover"> <li><a routerLink="/">Home</a></li> </ul> </li> <li><a routerLink="/login">Login</a></li> </ul> </div> </div> </div>
import { Component, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { LoginService } from '../login.service' declare var $ : any @Component({ selector: 'app-header', templateUrl: './app-header.component.html', styleUrls: ['./app-header.component.scss'] }) export class AppHeaderComponent implements OnInit, OnChanges { constructor( public loginService: LoginService ) {} ngOnInit() { $('#app-header').foundation() } ngAfterViewInit() { $('#app-header').foundation() } ngOnChanges(changes: SimpleChanges) { $('#app-header').foundation() } ngAfterContentChecked() { $('#app-header').foundation() } }
<div> <app-header></app-header> <div class="margin-left-2 margin-right-2"> <div class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-6"> <div> <form accept-charset="UTF-8" [formGroup]="phoneForm" (ngSubmit)="searchByPhone(phoneForm)"> <div class="input-group"> <span class="input-group-label">Search</span> <input class="input-group-field" type="text" formControlName="phone"> <div class="input-group-button"> <input type="submit" class="button" value="Submit"> </div> </div> </form> </div> <div *ngIf="phone && !(customerList.length > 0) "> <p>Yet not found.</p> </div> <div *ngIf="customerList.length > 0"> <h6>{{ timestamp() }}, total <b>{{ customerList.length }}</b></h6> <div *ngFor="let item of customerList; let i = index"> <hr /> <h6>{{ i + 1 }}. <b>{{ item.name }}</b></h6> <table> <tbody> <tr> <td width="14em">Location</td> <td><b>{{ item.city }}</b></td> </tr> <tr> <td>Order</td> <td>{{ item.agreement }}</td> </tr> <tr> <td>Phone 1</td> <td><a (click)="search(item.phone1)">{{ item.phone1 }}</a></td> </tr> <tr> <td>Phone 2</td> <td><a (click)="search(item.phone2)">{{ item.phone2 }}</a></td> </tr> </tbody> </table> </div> <p> <a (click)="router.navigate([ '/' ])"> <i class="fi-arrow-left"></i> Back to home </a> </p> </div> </div> </div> </div> </div> <app-footer></app-footer> </div>
import { Component, OnInit, OnDestroy, OnChanges, SimpleChanges, Input, Output, EventEmitter } from '@angular/core' import { Router, ActivatedRoute } from '@angular/router' import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms' import { AppHeaderComponent } from '../app-header/app-header.component' import { AppFooterComponent } from '../app-footer/app-footer.component' import { RPCService, RPCResponce, RPCError } from '../rpc.service' import { CustomersService } from '../customers.service' import { Customer } from '../models/customer.model' import * as moment from 'moment-mini' @Component({ selector: 'domain', templateUrl: './customers.component.html', styleUrls: ['./customers.component.scss'] }) export class CustomersComponent implements OnInit { phoneForm: FormGroup phone: string = '' customer: Customer = { id: -1, name: '', phone1: '', phone2: '', city: '', agreement: '' } customerList: Customer[] = [] constructor( private formBuilder: FormBuilder, private router: Router, private route: ActivatedRoute, private customersService: CustomersService ) {} timestamp() { return moment().format('hh:mm:ss a') } searchByPhone(form) { let phone = form.value.phone this.router.navigate([ '/customers/' + phone ]) } search(some) { this.router.navigate([ '/customers/' + some ]) } ngOnChanges(changes: SimpleChanges) { } ngOnInit() { this.phoneForm = this.formBuilder.group({ phone: [ this.phone ], }) this.route.paramMap.subscribe(params => { this.phone = params.get('phone') this.phone = this.phone.replace(/[\-.()+]/g, '') this.phoneForm = this.formBuilder.group({ phone: [ this.phone ], }) if (this.phone) { let customer : Customer = { phone1: this.phone, phone2: this.phone, name: this.phone } this.customersService .find(customer) .subscribe((res: RPCResponce<Customer[]>) => { if (res.result.length > 0) { this.customerList = res.result } }) } }) } }
import { Injectable } from '@angular/core' import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router" import { Observable } from "rxjs" import * as Cookies from 'es-cookie' import { LoginService } from '../login.service' @Injectable() export class SuperloginGuard implements CanActivate { cookieName: string = 'session' constructor( private loginService: LoginService, private router: Router ) {} canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ) : Observable<boolean> | boolean { if (this.loginService.isSuperuser()) { return true } this.loginService.returnUrl = state.url this.router.navigate(['/login']) return false } }
import { Injectable } from '@angular/core' import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router" import { Observable } from "rxjs" import * as Cookies from 'es-cookie' import { LoginService } from '../login.service' @Injectable() export class LoginGuard implements CanActivate { constructor( private loginService: LoginService, private router: Router ) {} canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ) : Observable<boolean> | boolean { if (this.loginService.isUser()) { return true } this.loginService.returnUrl = state.url this.router.navigate(['/login']) return false } }
<div> <app-header></app-header> <div class="margin-left-2 margin-right-2"> <div id="lorem" class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-8"> <h5>Sample call from:</h5> <ul class="list-square"> <li *ngFor="let item of samplePhoneList; let i = index"> <a target="_blank" rel="noopener noreferrer" href='#/customers/{{ item }}'>{{ item }}</a> </li> </ul> <h5>Sample search from parial string:</h5> <ul class="list-square"> <li *ngFor="let item of partialSamples; let i = index"> <a target="_blank" rel="noopener noreferrer" href='#/customers/{{ item }}'>{{ item }}</a> </li> </ul> </div> </div> </div> </div> <app-footer></app-footer> </div>
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'] }) export class HomeComponent implements OnInit { samplePhoneList: string[] = [ '16192188689', '1141855692', '7118221699', '6315369258', '18549937810', '16192', ] partialSamples: string[] = [ '16192', '7911', 'Anre', 'Princess', ] ngOnInit() { } }
<div> <div class="top-bar"> <div class="top-bar-left padding-left-2"> <ul class="menu"> <li class="menu-text"><i class="fi-shield" style="font-size: 1.3em;"></i></li> <li class="menu-text">Login</li> </ul> </div> </div> <div class="grid-container"> <div class="grid-x grid-padding-x align-center"> <div class="cell small-8 medium-4 large-3"> <div class="card padding-2 margin-top-3"> <form accept-charset="UTF-8" [formGroup]="loginForm" (ngSubmit)="login(loginForm)"> <label>Login name (demo: user) <input type="text" formControlName="name"> </label> <label>Password (demo: 12345) <input type="password" formControlName="password"> </label> <div class="text-center"> <button class="button small" type="submit">Submit</button> </div> </form> <div class="margin-2"> <div class="text-center"> {{ message }} </div> </div> </div> </div> </div> </div> </div>
import { Component, OnInit, OnDestroy } from '@angular/core' import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms' import { HttpClient } from '@angular/common/http' import { LoginService } from '../login.service' @Component({ selector: 'login', templateUrl: './login.component.html', styleUrls: [ './login.component.scss' ] }) export class LoginComponent implements OnInit { loginForm: FormGroup message: string = '' attemptCount: number = 0 constructor( private formBuilder: FormBuilder, private loginService: LoginService ) {} login(event) { if (this.loginService.login(event.value.name, event.value.password)) { this.message = `Wow! Login successful` return } setTimeout(() => { this.attemptCount++ this.message = `Login incorrect. Attempt ${this.attemptCount}` }, 1000 ) } ngOnInit() { this.loginForm = this.formBuilder.group({ name: [ '' ], password: [ '' ] }) } }
export interface Customer { id?: number name?: string password?: string phone1?: string phone2?: string agreement?: string city?: string }
export interface User { id?: number name?: string password?: string superuser?: boolean gecos?: string }
<div> <app-header></app-header> <div class="margin-left-2 margin-right-2"> <div id="lorem" class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-8"> <h5>Page not found</h5> </div> </div> </div> </div> <app-footer></app-footer> </div>
import { Component, OnInit } from '@angular/core'; import { AppHeaderComponent } from '../app-header/app-header.component' import { AppFooterComponent } from '../app-footer/app-footer.component' @Component({ selector: 'not-found', templateUrl: './not-found.component.html', styleUrls: ['./not-found.component.scss'] }) export class NotFoundComponent implements OnInit { ngOnInit() { } }
<div *ngIf="show"> <form accept-charset="UTF-8" class="callout" [formGroup]="userForm" (ngSubmit)="create(userForm)" > <h5 class="text-center">Do create user?</h5> <label>Login <input type="text" formControlName="name" /> </label> <label>Password <input type="text" formControlName="password" /> </label> <label>Name <input type="text" formControlName="gecos" /> </label> <fieldset class="cell margin-bottom-1 text-center"> <input id="checkbox-user-as" type="checkbox" formControlName="superuser"> <label for="checkbox-user-as">as Superuser</label> </fieldset> <div class="text-center"> <button class="button small margin-left-1 margin-right-1" type="submit">Accept</button> <div class="button small margin-left-1 margin-right-1" (click)="escape()">Escape</div> </div> </form> </div>
import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core' import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms' import { state, query, useAnimation, transition, style, trigger, animate, animateChild } from '@angular/animations'; import { RPCService, RPCResponce, RPCError } from '../rpc.service' import { UsersService } from '../users.service' import { User } from '../models/user.model' @Component({ selector: 'user-create', templateUrl: './user-create.component.html', styleUrls: ['./user-create.component.scss'], animations: [ ] }) export class UserCreateComponent implements OnInit { userForm: FormGroup user: User alertMessage: string = '' message: string = '' @Input() show: boolean = false @Output() escapeEvent = new EventEmitter<boolean>(); @Output() successEvent = new EventEmitter<boolean>(); constructor( private formBuilder: FormBuilder, private usersService: UsersService ) {} create(item) { this.user = item.value this.usersService .create(this.user) .subscribe((res: RPCResponce<any>) => { if (res.result.rowCount > 0) { this.show = false this.successEvent.emit(true) } else { this.show = false this.successEvent.emit(false) } }) } escape() { this.show = false this.escapeEvent.emit(true) } ngOnInit() { this.userForm = this.formBuilder.group({ name: [ '' ], password: [ '' ], gecos: [ '' ], superuser: [ false ] }) } }
<div *ngIf="show"> <form accept-charset="UTF-8" class="callout" [formGroup]="userForm" (ngSubmit)="update(userForm)" > <h5 class="text-center">Do drop user {{ user.name }}?</h5> <div class="text-center"> <button class="button small margin-left-1 margin-right-1" type="submit">Accept</button> <div class="button small margin-left-1 margin-right-1" (click)="escape()">Escape</div> </div> </form> </div>
import { Component, OnInit, OnDestroy, OnChanges, SimpleChanges, Input, Output, EventEmitter } from '@angular/core' import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms' import { RPCService, RPCResponce, RPCError } from '../rpc.service' import { UsersService } from '../users.service' import { User } from '../models/user.model' @Component({ selector: 'user-drop', templateUrl: './user-drop.component.html', styleUrls: ['./user-drop.component.scss'] }) export class UserDropComponent implements OnInit { userForm: FormGroup alertMessage: string = '' message: string = '' @Input() show: boolean = false @Input() user: User = { id: -1, name: '', password: '', gecos: '' } @Output() escapeEvent = new EventEmitter<boolean>(); @Output() successEvent = new EventEmitter<boolean>(); constructor( private formBuilder: FormBuilder, private usersService: UsersService ) {} create(item) { this.user = item.value } escape() { this.show = false this.escapeEvent.emit(true) } update(item) { this.user = item.value this.usersService .drop(this.user) .subscribe((res: RPCResponce<any>) => { if (res.result.rowCount > 0) { this.show = false this.successEvent.emit(true) } else { this.show = false this.successEvent.emit(false) } }) } ngOnChanges(changes: SimpleChanges) { if (changes['user']) { this.userForm = this.formBuilder.group({ id: [ this.user.id ], }) } } ngOnInit() { } }
<div *ngIf="show"> <form accept-charset="UTF-8" class="callout" [formGroup]="userForm" (ngSubmit)="update(userForm)" > <h5 class="text-center">Do update user?</h5> <label>Login <input type="text" formControlName="name" /> </label> <label>Password <input type="text" formControlName="password" /> </label> <label>Name <input type="text" formControlName="gecos" /> </label> <fieldset class="cell margin-bottom-1 text-center"> <input id="checkbox-user-as" type="checkbox" formControlName="superuser"> <label for="checkbox-user-as">as Superuser</label> </fieldset> <div class="text-center"> <button class="button small margin-left-1 margin-right-1" type="submit">Accept</button> <div class="button small margin-left-1 margin-right-1" (click)="escape()">Escape</div> </div> </form> </div>
import { Component, OnInit, OnDestroy, OnChanges, SimpleChanges, Input, Output, EventEmitter } from '@angular/core' import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms' import { RPCService, RPCResponce, RPCError } from '../rpc.service' import { UsersService } from '../users.service' import { User } from '../models/user.model' @Component({ selector: 'user-update', templateUrl: './user-update.component.html', styleUrls: ['./user-update.component.scss'] }) export class UserUpdateComponent implements OnInit { userForm: FormGroup alertMessage: string = '' message: string = '' @Input() show: boolean = false @Input() user: User = { id: -1, name: '', password: '', gecos: '' } @Output() escapeEvent = new EventEmitter<boolean>(); @Output() successEvent = new EventEmitter<boolean>(); constructor( private formBuilder: FormBuilder, private usersService: UsersService ) {} create(item) { this.user = item.value } escape() { this.show = false this.escapeEvent.emit(true) } update(item) { this.user = item.value this.usersService .update(this.user) .subscribe((res: RPCResponce<any>) => { if (res.result.rowCount > 0) { this.show = false this.successEvent.emit(true) } else { this.show = false this.successEvent.emit(false) } }) } ngOnChanges(changes: SimpleChanges) { if (changes['user']) { this.userForm = this.formBuilder.group({ id: [ this.user.id ], name: [ this.user.name ], password: [ this.user.password ], gecos: [ this.user.gecos ], superuser: [ this.user.superuser ] }) } } ngOnInit() { } }
<div id="users"> <app-header></app-header> <div class="margin-left-2 margin-right-2"> <div id="lorem" class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-4"> <user-create [show]="showCreateForm" (escapeEvent)="escapeForm()" (successEvent)="successForm($event)"></user-create> </div> </div> </div> <div class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-4"> <user-update [user]="currentUser" [show]="showUpdateForm" (escapeEvent)="escapeForm()" (successEvent)="successForm($event)"></user-update> </div> </div> </div> <div class="grid-container"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-4"> <user-drop [user]="currentUser" [show]="showDropForm" (escapeEvent)="escapeForm()" (successEvent)="successForm($event)"></user-drop> </div> </div> </div> <div class="grid-container" *ngIf="showListRecords"> <div class="grid-x grid-margin-x align-center"> <div class="cell medium-8"> <h5>Users <a (click)="getList()"><i class="fi-refresh" style="font-size: 1.3em;"></i></a> <button class="float-right small button" (click)="showCreate()"><i class="fi-plus" style="font-size: 1.3em;"></i></button> </h5> <table> <thead> <tr> <th>#</th> <th>name</th> <th>login</th> <th>right</th> <th><i class="fi-pencil"></i></th> <th><i class="fi-trash"></i></th> </tr> </thead> <tbody> <tr *ngFor="let item of list; let i = index"> <td>{{ i + 1 }}</td> <td>{{ item.gecos }}</td> <td>{{ item.name }}</td> <td><span *ngIf="item.superuser"><i class="fi-sheriff-badge" style="font-size: 1.2em;"></i></span></td> <td><a (click)="updateItem(item)"><i class="fi-pencil"></i></a></td> <td><a (click)="dropItem(item)"><i class="fi-trash"></i></a></td> </tr> </tbody> </table> </div> </div> </div> </div> <app-footer></app-footer> </div>
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router } from '@angular/router' import { AppHeaderComponent } from '../app-header/app-header.component' import { AppFooterComponent } from '../app-footer/app-footer.component' import { UserCreateComponent } from '../user-create/user-create.component' import { UserUpdateComponent } from '../user-update/user-update.component' import { UserDropComponent } from '../user-drop/user-drop.component' import { RPCService, RPCResponce, RPCError } from '../rpc.service' import { UsersService } from '../users.service' import { User } from '../models/user.model' @Component({ selector: 'users', templateUrl: './users.component.html', styleUrls: ['./users.component.scss'], }) export class UsersComponent implements OnInit { showCreateForm: boolean = false showUpdateForm: boolean = false showDropForm: boolean = false showListRecords: boolean = true list: User[] = [] currentUser : User = { id: -1, name: '', password: '', gecos: '' } constructor( private usersService: UsersService, ) {} dropItem(item: User) { this.currentUser = item this.showDrop() } updateItem(item: User) { this.currentUser = item this.showUpdate() } getList() { this.usersService .list() .subscribe((res: RPCResponce<User[]>) => { this.list = res.result }) } ngOnInit() { this.getList() } escapeForm() { this.showList() } successForm($event) { this.getList() this.showList() } showCreate() { this.showCreateForm = true this.showUpdateForm = false this.showDropForm = false this.showListRecords = false } showUpdate() { this.showCreateForm = false this.showUpdateForm = true this.showDropForm = false this.showListRecords = false } showDrop() { this.showCreateForm = false this.showUpdateForm = false this.showDropForm = true this.showListRecords = false } showList() { this.showCreateForm = false this.showUpdateForm = false this.showDropForm = false this.showListRecords = true } }
import { Injectable } from '@angular/core' import { Observable } from 'rxjs' import { RPCService, RPCResponce, RPCError } from './rpc.service' import { Customer } from './models/customer.model' @Injectable({ providedIn: 'root' }) export class CustomersService { constructor( private rpcService: RPCService ) {} find(customer: Customer) { return this.rpcService .request<Customer, Customer[]>('/api/customers', 'find', customer) } }
<div id="app"> <router-outlet></router-outlet> </div>
import { Component, OnInit, OnDestroy } from '@angular/core' declare var $ : any @Component({ selector: 'app', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { ngOnInit() { $(document).foundation() } }
import { NgModule } from '@angular/core' import { LocationStrategy, HashLocationStrategy } from '@angular/common' import { FormsModule } from '@angular/forms' import { ReactiveFormsModule } from '@angular/forms' import { BrowserModule } from '@angular/platform-browser' import { BrowserAnimationsModule } from '@angular/platform-browser/animations' import { HttpClientModule } from '@angular/common/http' import { RoutingModule } from './routing.module' import { AppComponent } from './app.component' import { AppHeaderComponent } from './app-header/app-header.component' import { AppFooterComponent } from './app-footer/app-footer.component' import { HomeComponent } from './home/home.component' import { CustomersComponent } from './customers/customers.component' import { LoginComponent } from './login/login.component' import { NotFoundComponent } from './not-found/not-found.component' import { RPCService } from './rpc.service' import { LoginService } from './login.service' import { UsersService } from './users.service' import { CustomersService } from './customers.service' import { LoginGuard } from './guards/login.guard' import { SuperloginGuard } from './guards/superlogin.guard' import { UsersComponent } from './users/users.component' import { UserCreateComponent } from './user-create/user-create.component' import { UserUpdateComponent } from './user-update/user-update.component' import { UserDropComponent } from './user-drop/user-drop.component' @NgModule({ declarations: [ AppHeaderComponent, AppFooterComponent, AppComponent, HomeComponent, CustomersComponent, UsersComponent, LoginComponent, NotFoundComponent, UserCreateComponent, UserUpdateComponent, UserDropComponent ], imports: [ ReactiveFormsModule, FormsModule, BrowserModule, BrowserAnimationsModule, RoutingModule, HttpClientModule ], providers: [ {provide: LocationStrategy, useClass: HashLocationStrategy}, LoginService, RPCService, UsersService, CustomersService, LoginGuard, SuperloginGuard ], bootstrap: [ AppComponent ] }) export class AppModule { }
import { Injectable, OnInit } from '@angular/core' import { Router, ActivatedRoute } from '@angular/router' import * as Cookies from 'es-cookie' import { RPCService } from './rpc.service' import { User } from './models/user.model' export interface UserLogin { name: string password: string } //export enum AccessLevel { Superuser = 'superuser', User = 'user' } @Injectable({ providedIn: 'root' }) export class LoginService { cookieName = 'session' returnUrl: string = '/' loginState: boolean = false user: User = { id: -1, name: '', superuser: false, gecos: '' } constructor( private route: ActivatedRoute, private router: Router, private rpc: RPCService ) {} isLogin() : boolean { if (Cookies.get(this.cookieName)) { return true } return false } isUser() : boolean { return this.isLogin() } isSuperuser() : boolean { if (this.isLogin() && this.user.superuser) { return true } return false } login(name: string, password: string) : boolean { let params : User = { name: name, password: password, id: -1 } this.rpc.request<User, User[]>('/api/login', 'login', params) .subscribe((res) => { if (res.result[0].id >= 0) { this.user.id = res.result[0].id this.user.superuser = res.result[0].superuser this.user.gecos = res.result[0].gecos this.router.navigate([ this.returnUrl ]) } }) if (this.user.id >= 0) return true return false } logout() { Cookies.remove(this.cookieName) this.router.navigate(['/']) } ngOnInit() { } }
import { NgModule } from '@angular/core' import { Routes, RouterModule } from '@angular/router' import { HomeComponent } from './home/home.component' import { LoginComponent } from './login/login.component' import { CustomersComponent } from './customers/customers.component' import { UsersComponent } from './users/users.component' import { NotFoundComponent } from './not-found/not-found.component' import { LoginGuard } from './guards/login.guard' import { SuperloginGuard } from './guards/superlogin.guard' const routes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'customers', component: CustomersComponent, canActivate: [ LoginGuard ] }, { path: 'customers/:phone', component: CustomersComponent, canActivate: [ LoginGuard ] }, { path: 'users', component: UsersComponent, canActivate: [ SuperloginGuard ] }, { path: '', //redirectTo: 'customers', //pathMatch: 'full' component: HomeComponent, //canActivate: [ LoginGuard ] }, { path: '**', component: NotFoundComponent, //canActivate: [ LoginGuard ] } ] @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class RoutingModule {}
import { Injectable } from '@angular/core' import { HttpClient } from '@angular/common/http' import { Observable } from 'rxjs' import { v4 as uuid } from 'uuid' export interface RPCRequest<TParam> { jsonrpc: string method: string params: TParam id: string } export interface RPCError { code?: number message?: string } export interface RPCResponce<TResult> { jsonrpc: string error?: RPCError result?: TResult id: string } @Injectable({ providedIn: 'root' }) export class RPCService { constructor( private httpClient: HttpClient ) {} request<TParam, TResult>(url: string, method: string, params: TParam) : Observable<RPCResponce<TResult>> { let rpcRequest : RPCRequest<TParam> = { jsonrpc: '2.0', method: method, params: params, id: uuid() } return this.httpClient.post<RPCResponce<TResult>>(url, rpcRequest) } }
import { Injectable } from '@angular/core' import { Observable } from 'rxjs' import { RPCService, RPCResponce, RPCError } from './rpc.service' import { User } from './models/user.model' @Injectable({ providedIn: 'root' }) export class UsersService { constructor( private rpcService: RPCService ) {} list() { return this.rpcService .request<null, User[]>('/api/users', 'list', null) } create(user: User) { return this.rpcService .request<User, number>('/api/users', 'create', user) } update(user: User) { return this.rpcService .request<User, number>('/api/users', 'update', user) } drop(user: User) { return this.rpcService .request<User, number>('/api/users', 'drop', user) } }
export const environment = { production: true };
export const environment = { production: false };
import 'zone.js/dist/zone';
<!doctype html> <html class="no-js" lang="en" dir="ltr"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="/foundation-icons.css"> <title>NgII</title> <base href="/"> <link rel="shortcut icon" href="/favicon.ico"> </head> <body id="body"> <app></app> </body> </html>
import { enableProdMode } from '@angular/core' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { AppModule } from './app/app.module' import { environment } from './environments/environment' if (environment.production) { enableProdMode() } platformBrowserDynamic() .bootstrapModule(AppModule) .catch(err => console.error(err))
declare var module: NodeModule; interface NodeModule { id: string; }