├── .editorconfig
├── .gitignore
├── README.md
├── e2e
├── app.e2e-spec.ts
├── app.po.ts
└── tsconfig.json
├── karma.conf.js
├── mock_data
├── form
│ ├── login.form.mock.json
│ └── login.router.mock.json
├── menubar
│ ├── menubar.admin.response.mock.json
│ ├── menubar.anon.menuitems.mock.json
│ └── menubar.anon.response.mock.json
└── table
│ ├── table.columns.response.mock.json
│ ├── table.datatable.response.mock.json
│ ├── table.records.response.mock.json
│ └── table.selectitems.mock.json
├── package-lock.json
├── package.json
├── protractor.conf.js
├── src
├── app
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── app.reducers.ts
│ ├── app.routing.ts
│ ├── auth
│ │ ├── auth.actions.ts
│ │ ├── auth.effects.ts
│ │ ├── auth.models.ts
│ │ ├── auth.module.ts
│ │ ├── auth.reducers.ts
│ │ └── auth.service.ts
│ ├── form
│ │ ├── form-element.component.ts
│ │ ├── form.actions.ts
│ │ ├── form.component.html
│ │ ├── form.component.ts
│ │ ├── form.container.spec.ts
│ │ ├── form.container.ts
│ │ ├── form.effects.ts
│ │ ├── form.models.ts
│ │ ├── form.module.ts
│ │ ├── form.reducers.ts
│ │ └── form.service.ts
│ ├── growl
│ │ ├── README.md
│ │ ├── growl.component.ts
│ │ └── growl.container.ts
│ ├── home
│ │ ├── home.container.html
│ │ ├── home.container.scss
│ │ └── home.container.ts
│ ├── menubar
│ │ ├── menubar.actions.ts
│ │ ├── menubar.component.spec.ts
│ │ ├── menubar.component.ts
│ │ ├── menubar.constants.ts
│ │ ├── menubar.container.spec.ts
│ │ ├── menubar.container.ts
│ │ ├── menubar.effects.ts
│ │ ├── menubar.models.ts
│ │ ├── menubar.module.ts
│ │ ├── menubar.reducers.ts
│ │ └── menubar.service.ts
│ ├── rest
│ │ ├── rest.actions.ts
│ │ ├── rest.effects.ts
│ │ ├── rest.models.ts
│ │ ├── rest.reducers.ts
│ │ └── rest.service.ts
│ ├── router
│ │ ├── router.actions.ts
│ │ ├── router.effects.ts
│ │ ├── router.models.ts
│ │ └── router.serializer.ts
│ ├── table
│ │ ├── table.actions.ts
│ │ ├── table.component.html
│ │ ├── table.component.scss
│ │ ├── table.component.spec.ts
│ │ ├── table.component.ts
│ │ ├── table.container.spec.ts
│ │ ├── table.container.ts
│ │ ├── table.data-mapping.component.html
│ │ ├── table.data-mapping.component.ts
│ │ ├── table.effects.ts
│ │ ├── table.models.ts
│ │ ├── table.module.ts
│ │ ├── table.reducers.ts
│ │ └── table.service.ts
│ ├── util.ts
│ └── websocket
│ │ ├── websocket.actions.ts
│ │ ├── websocket.effects.ts
│ │ └── websocket.service.ts
├── assets
│ └── .gitkeep
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
├── test.ts
└── tsconfig.json
├── tslint.json
└── uml
├── component_architecture.puml
└── store_architecture.puml
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 |
10 | # IDEs and editors
11 | /.idea
12 | .project
13 | .classpath
14 | .c9/
15 | *.launch
16 | .settings/
17 |
18 | # IDE - VSCode
19 | .vscode/*
20 | !.vscode/settings.json
21 | !.vscode/tasks.json
22 | !.vscode/launch.json
23 | !.vscode/extensions.json
24 |
25 | # misc
26 | /.sass-cache
27 | /connect.lock
28 | /coverage/*
29 | /libpeerconnection.log
30 | npm-debug.log
31 | testem.log
32 | /typings
33 |
34 | # e2e
35 | /e2e/*.js
36 | /e2e/*.map
37 |
38 | #System Files
39 | .DS_Store
40 | Thumbs.db
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # General Angular
2 |
3 | A web client for https://github.com/PierreRochard/general
4 |
5 | This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.28.3.
6 |
7 | ## Development server
8 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
9 |
10 | ## Code scaffolding
11 |
12 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.
13 |
14 | ## Build
15 |
16 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
17 |
18 | ## Running unit tests
19 |
20 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
21 |
22 | ## Running end-to-end tests
23 |
24 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
25 | Before running the tests make sure you are serving the app via `ng serve`.
26 |
27 | ## Deploying to GitHub Pages
28 |
29 | Run `ng github-pages:deploy` to deploy to GitHub Pages.
30 |
31 | ## Further help
32 |
33 | To get more help on the `angular-cli` use `ng help` or go check out the [Angular-CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
34 |
--------------------------------------------------------------------------------
/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { PrimengPostgrestPage } from './app.po';
2 |
3 | describe('primeng-postgrest App', function() {
4 | let page: PrimengPostgrestPage;
5 |
6 | beforeEach(() => {
7 | page = new PrimengPostgrestPage();
8 | });
9 |
10 | it('should display message saying app works', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('app works!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, element, by } from 'protractor';
2 |
3 | export class PrimengPostgrestPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "declaration": false,
5 | "emitDecoratorMetadata": true,
6 | "experimentalDecorators": true,
7 | "module": "commonjs",
8 | "moduleResolution": "node",
9 | "outDir": "../dist/out-tsc-e2e",
10 | "sourceMap": true,
11 | "target": "es5",
12 | "typeRoots": [
13 | "../node_modules/@types"
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/0.13/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-remap-istanbul'),
12 | require('@angular-devkit/build-angular/plugins/karma')
13 | ],
14 | files: [
15 |
16 | ],
17 | preprocessors: {
18 |
19 | },
20 | mime: {
21 | 'text/x-typescript': ['ts','tsx']
22 | },
23 | remapIstanbulReporter: {
24 | dir: require('path').join(__dirname, 'coverage'), reports: {
25 | html: 'coverage',
26 | lcovonly: './coverage/coverage.lcov'
27 | }
28 | },
29 | angularCli: {
30 | config: './.@angular-devkit/build-angular.json',
31 | environment: 'dev'
32 | },
33 | reporters: config.angularCli && config.angularCli.codeCoverage
34 | ? ['progress', 'karma-remap-istanbul']
35 | : ['progress'],
36 | port: 9876,
37 | colors: true,
38 | logLevel: config.LOG_INFO,
39 | autoWatch: true,
40 | browsers: ['ChromeHeadless'],
41 | singleRun: false,
42 | customLaunchers: {
43 | ChromeHeadless: {
44 | base: 'Chrome',
45 | flags: [
46 | '--headless',
47 | '--disable-gpu',
48 | // Without a remote debugging port, Google Chrome exits immediately.
49 | '--remote-debugging-port=9222',
50 | ],
51 | }
52 | }
53 | });
54 | };
55 |
--------------------------------------------------------------------------------
/mock_data/form/login.form.mock.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaName": "auth",
3 | "formName": "login",
4 | "formSettings": {
5 | "id": 1,
6 | "custom_name": "Login",
7 | "form_name": "login",
8 | "schema_name": "auth",
9 | "user_id": "4bbed106-90a6-4371-91c9-c074f3cdf4bb"
10 | },
11 | "fieldSettings": [
12 | {
13 | "id": 1,
14 | "custom_name": "Email",
15 | "field_name": "email",
16 | "field_type": "text",
17 | "form_name": "login",
18 | "schema_name": "auth",
19 | "user_id": "4bbed106-90a6-4371-91c9-c074f3cdf4bb"
20 | },
21 | {
22 | "id": 2,
23 | "custom_name": "Password",
24 | "field_name": "password",
25 | "field_type": "text",
26 | "form_name": "login",
27 | "schema_name": "auth",
28 | "user_id": "4bbed106-90a6-4371-91c9-c074f3cdf4bb"
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/mock_data/form/login.router.mock.json:
--------------------------------------------------------------------------------
1 | {
2 | "state": {
3 | "url": "/auth/rpc/login",
4 | "queryParams": {},
5 | "params": {
6 | "selectedObjectName": "login",
7 | "selectedSchemaName": "auth",
8 | "selectedObjectType": "form"
9 | }
10 | },
11 | "navigationId": 1
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/mock_data/menubar/menubar.admin.response.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "label": "Settings",
4 | "icon": "fa-cogs",
5 | "routerLink": null,
6 | "items": [
7 | {
8 | "id": "2a2e1722-317c-42c3-bff2-3fd6675a6770",
9 | "icon": "fa-table",
10 | "user": "kXYfMlDqdaFReje",
11 | "items": null,
12 | "label": "Forms",
13 | "routerLink": [
14 | "/",
15 | "admin",
16 | "forms"
17 | ],
18 | "submenu_id": "445c787a-6356-496f-a609-be58efc095cd",
19 | "order_index": 0
20 | },
21 | {
22 | "id": "fcc3f3cb-3d43-4c9a-a978-d606a869503e",
23 | "icon": "fa-table",
24 | "user": "kXYfMlDqdaFReje",
25 | "items": null,
26 | "label": "Form Fields",
27 | "routerLink": [
28 | "/",
29 | "admin",
30 | "form_fields"
31 | ],
32 | "submenu_id": "445c787a-6356-496f-a609-be58efc095cd",
33 | "order_index": 0
34 | },
35 | {
36 | "id": "b59bb413-ad8c-4e05-9eab-aaaef6c9e9d0",
37 | "icon": "fa-table",
38 | "user": "kXYfMlDqdaFReje",
39 | "items": null,
40 | "label": "Datatables",
41 | "routerLink": [
42 | "/",
43 | "admin",
44 | "datatables"
45 | ],
46 | "submenu_id": "445c787a-6356-496f-a609-be58efc095cd",
47 | "order_index": 0
48 | },
49 | {
50 | "id": "2b7a6dc1-e4a0-490b-b9de-29a846b40580",
51 | "icon": "fa-table",
52 | "user": "kXYfMlDqdaFReje",
53 | "items": null,
54 | "label": "Datatable Columns",
55 | "routerLink": [
56 | "/",
57 | "admin",
58 | "datatable_columns"
59 | ],
60 | "submenu_id": "445c787a-6356-496f-a609-be58efc095cd",
61 | "order_index": 0
62 | }
63 | ]
64 | }
65 | ]
66 |
--------------------------------------------------------------------------------
/mock_data/menubar/menubar.anon.menuitems.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "label": "Login",
4 | "icon": "fa-pencil-square-o",
5 | "routerLink": [
6 | "/",
7 | "auth",
8 | "rpc",
9 | "login"
10 | ]
11 | }
12 | ]
13 |
14 |
--------------------------------------------------------------------------------
/mock_data/menubar/menubar.anon.response.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "label": "Login",
4 | "icon": "fa-pencil-square-o",
5 | "routerLink": [
6 | "/",
7 | "auth",
8 | "rpc",
9 | "login"
10 | ],
11 | "items": null
12 | }
13 | ]
14 |
--------------------------------------------------------------------------------
/mock_data/table/table.columns.response.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 60,
4 | "can_update": false,
5 | "column_name": "id",
6 | "custom_name": "Id",
7 | "data_type": "uuid",
8 | "filter_match_mode": "contains",
9 | "filter_value": null,
10 | "format_pattern": null,
11 | "input_type": "text",
12 | "is_filterable": false,
13 | "is_sortable": true,
14 | "is_visible": true,
15 | "schema_name": "test",
16 | "select_item_schema_name": null,
17 | "select_item_table_name": null,
18 | "select_item_label_column_name": null,
19 | "select_item_value_column_name": null,
20 | "table_name": "clients",
21 | "user_id": "1840e030-186e-4be3-a517-79762a96427d"
22 | },
23 | {
24 | "id": 61,
25 | "can_update": true,
26 | "column_name": "household",
27 | "custom_name": "Household",
28 | "data_type": "character varying",
29 | "filter_match_mode": "contains",
30 | "filter_value": null,
31 | "format_pattern": null,
32 | "input_type": "dropdown",
33 | "is_filterable": false,
34 | "is_sortable": true,
35 | "is_visible": true,
36 | "schema_name": "test",
37 | "select_item_schema_name": "test",
38 | "select_item_table_name": "households",
39 | "select_item_label_column_name": "name",
40 | "select_item_value_column_name": "id",
41 | "table_name": "clients",
42 | "user_id": "1840e030-186e-4be3-a517-79762a96427d"
43 | },
44 | {
45 | "id": 62,
46 | "can_update": false,
47 | "column_name": "first_name",
48 | "custom_name": "First Name",
49 | "data_type": "character varying",
50 | "filter_match_mode": "contains",
51 | "filter_value": null,
52 | "format_pattern": null,
53 | "input_type": "text",
54 | "is_filterable": false,
55 | "is_sortable": true,
56 | "is_visible": true,
57 | "schema_name": "test",
58 | "select_item_schema_name": null,
59 | "select_item_table_name": null,
60 | "select_item_label_column_name": null,
61 | "select_item_value_column_name": null,
62 | "table_name": "clients",
63 | "user_id": "1840e030-186e-4be3-a517-79762a96427d"
64 | },
65 | {
66 | "id": 63,
67 | "can_update": false,
68 | "column_name": "last_name",
69 | "custom_name": "Last Name",
70 | "data_type": "character varying",
71 | "filter_match_mode": "contains",
72 | "filter_value": null,
73 | "format_pattern": null,
74 | "input_type": "text",
75 | "is_filterable": false,
76 | "is_sortable": true,
77 | "is_visible": true,
78 | "schema_name": "test",
79 | "select_item_schema_name": null,
80 | "select_item_table_name": null,
81 | "select_item_label_column_name": null,
82 | "select_item_value_column_name": null,
83 | "table_name": "clients",
84 | "user_id": "1840e030-186e-4be3-a517-79762a96427d"
85 | }
86 | ]
87 |
--------------------------------------------------------------------------------
/mock_data/table/table.datatable.response.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 8,
4 | "custom_name": "Clients",
5 | "order_index": 1,
6 | "row_limit": 10,
7 | "row_offset": 0,
8 | "schema_name": "test",
9 | "sort_column": "id",
10 | "sort_order": 1,
11 | "table_name": "clients",
12 | "user_id": "1840e030-186e-4be3-a517-79762a96427d"
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/mock_data/table/table.records.response.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "01e36eed-0509-4b6c-b1a9-d9f02d79c4ba",
4 | "household": null,
5 | "first_name": "PIERRE",
6 | "last_name": "ROCHARD"
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/mock_data/table/table.selectitems.mock.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "value": "testing-value-1",
4 | "label": "Testing Value 1"
5 | },
6 | {
7 | "value": "testing-value-2",
8 | "label": "Testing Value 2"
9 | }
10 | ]
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "postgrest-angular",
3 | "version": "0.0.0",
4 | "license": "MIT",
5 | "angular-cli": {},
6 | "scripts": {
7 | "ng": "ng",
8 | "start": "ng serve",
9 | "test": "ng test --colors=true --watch=true --progress=true --sourcemaps=false ",
10 | "pree2e": "webdriver-manager update --standalone false --gecko false",
11 | "e2e": "protractor"
12 | },
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "^6.0.3",
16 | "@angular/cdk": "^6.1.0",
17 | "@angular/common": "^6.0.3",
18 | "@angular/compiler": "^6.0.3",
19 | "@angular/core": "^6.0.3",
20 | "@angular/forms": "^6.0.3",
21 | "@angular/http": "^6.0.3",
22 | "@angular/material": "^6.1.0",
23 | "@angular/platform-browser": "^6.0.3",
24 | "@angular/platform-browser-dynamic": "^6.0.3",
25 | "@angular/platform-server": "^6.0.3",
26 | "@angular/router": "^6.0.3",
27 | "@ngrx/core": "^1.2.0",
28 | "@ngrx/effects": "^6.0.1",
29 | "@ngrx/router-store": "^6.0.1",
30 | "@ngrx/store": "^6.0.1",
31 | "@ngrx/store-devtools": "^6.0.1",
32 | "@ngrx/store-log-monitor": "^3.0.2",
33 | "angular2-websocket": "^0.9.6",
34 | "core-js": "^2.5.6",
35 | "font-awesome": "^4.7.0",
36 | "ngrx-store-localstorage": "^5.0.0",
37 | "primeng": "^6.0.0-alpha.1",
38 | "raven-js": "^3.25.2",
39 | "reselect": "^3.0.1",
40 | "rxjs": "^6.2.0",
41 | "ts-helpers": "^1.1.2",
42 | "zone.js": "^0.8.26"
43 | },
44 | "devDependencies": {
45 | "@angular-devkit/build-angular": "~0.6.5",
46 | "@angular/cli": "^6.0.5",
47 | "@angular/compiler-cli": "^6.0.3",
48 | "@types/jasmine": "2.8.7",
49 | "@types/node": "^10.1.2",
50 | "codelyzer": "^4.3.0",
51 | "jasmine-core": "3.1.0",
52 | "jasmine-spec-reporter": "4.2.1",
53 | "karma": "2.0.2",
54 | "karma-chrome-launcher": "^2.2.0",
55 | "karma-cli": "^1.0.1",
56 | "karma-jasmine": "^1.1.2",
57 | "karma-remap-istanbul": "^0.6.0",
58 | "ngrx-store-freeze": "^0.2.3",
59 | "protractor": "~5.3.2",
60 | "ts-node": "6.0.5",
61 | "tslint": "^5.10.0",
62 | "typescript": "<2.8"
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | /*global jasmine */
5 | var SpecReporter = require('jasmine-spec-reporter');
6 |
7 | exports.config = {
8 | allScriptsTimeout: 11000,
9 | specs: [
10 | './e2e/**/*.e2e-spec.ts'
11 | ],
12 | capabilities: {
13 | 'browserName': 'chrome'
14 | },
15 | directConnect: true,
16 | baseUrl: 'http://localhost:4200/',
17 | framework: 'jasmine',
18 | jasmineNodeOpts: {
19 | showColors: true,
20 | defaultTimeoutInterval: 30000,
21 | print: function() {}
22 | },
23 | useAllAngular2AppRoots: true,
24 | beforeLaunch: function() {
25 | require('ts-node').register({
26 | project: 'e2e'
27 | });
28 | },
29 | onPrepare: function() {
30 | jasmine.getEnv().addReporter(new SpecReporter());
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | template: `
6 |
13 | `,
14 | })
15 | export class AppComponent {
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
3 | import { HttpClientModule } from '@angular/common/http';
4 | import { NgModule } from '@angular/core';
5 |
6 | import { StoreModule } from '@ngrx/store';
7 | import { EffectsModule } from '@ngrx/effects';
8 | import {
9 | RouterStateSerializer,
10 | StoreRouterConnectingModule,
11 | } from '@ngrx/router-store';
12 |
13 | import { FieldsetModule } from 'primeng/components/fieldset/fieldset';
14 | import { GrowlModule } from 'primeng/components/growl/growl';
15 |
16 | import { RestEffects } from './rest/rest.effects';
17 |
18 | import { GrowlContainer } from './growl/growl.container';
19 | import { GrowlComponent } from './growl/growl.component';
20 |
21 | import { AppAuthModule } from './auth/auth.module';
22 | import { AuthEffects } from './auth/auth.effects';
23 |
24 | import { AppFormModule } from './form/form.module';
25 | import { FormEffects } from './form/form.effects';
26 |
27 | import { AppTableModule } from './table/table.module';
28 |
29 | import { HomeContainer } from './home/home.container';
30 | import { TableEffects } from './table/table.effects';
31 |
32 | import { RestClient } from './rest/rest.service';
33 |
34 | import { reducers, metaReducers } from './app.reducers';
35 | import { routing } from './app.routing';
36 | import { AppComponent } from './app.component';
37 |
38 | import { WebsocketEffects } from './websocket/websocket.effects';
39 | import { WebsocketService } from './websocket/websocket.service';
40 | import { AppMenubarModule } from './menubar/menubar.module';
41 | import { MenubarEffects } from './menubar/menubar.effects';
42 | import { RouterEffects } from './router/router.effects';
43 | import { CustomRouterStateSerializer } from './router/router.serializer';
44 |
45 | @NgModule({
46 | bootstrap: [AppComponent],
47 | declarations: [
48 | AppComponent,
49 | HomeContainer,
50 | GrowlContainer,
51 | GrowlComponent,
52 | ],
53 | imports: [
54 | AppAuthModule,
55 | AppFormModule,
56 | AppMenubarModule,
57 | AppTableModule,
58 | BrowserModule,
59 | BrowserAnimationsModule,
60 | EffectsModule.forRoot([AuthEffects, FormEffects, MenubarEffects, RestEffects,
61 | RouterEffects, TableEffects, WebsocketEffects]),
62 | FieldsetModule,
63 | GrowlModule,
64 | HttpClientModule,
65 | routing,
66 | StoreModule.forRoot(reducers, {metaReducers: metaReducers}),
67 | StoreRouterConnectingModule,
68 | ],
69 | providers: [
70 | RestClient,
71 | WebsocketService,
72 | {provide: RouterStateSerializer, useClass: CustomRouterStateSerializer},
73 | ],
74 | })
75 | export class AppModule {
76 | }
77 |
--------------------------------------------------------------------------------
/src/app/app.reducers.ts:
--------------------------------------------------------------------------------
1 | import {ActionReducer, ActionReducerMap, MetaReducer} from '@ngrx/store';
2 | // import {storeFreeze} from 'ngrx-store-freeze';
3 | import {LocalStorageConfig, localStorageSync} from 'ngrx-store-localstorage';
4 | import {createSelector} from 'reselect';
5 |
6 | import {environment} from '../environments/environment';
7 | import {AuthState, authReducer} from './auth/auth.reducers';
8 | import {FormState, formReducer} from './form/form.reducers';
9 | import {MenubarState, menubarReducer} from './menubar/menubar.reducers';
10 | import {RestState, restReducer} from './rest/rest.reducers';
11 | import {TableState, tableReducer} from './table/table.reducers';
12 | import {routerReducer, RouterReducerState} from '@ngrx/router-store';
13 | import { RouterStateUrl } from './router/router.serializer';
14 |
15 | export interface AppState {
16 | auth: AuthState;
17 | form: FormState,
18 | menubar: MenubarState;
19 | rest: RestState;
20 | routerReducer: RouterReducerState;
21 | table: TableState;
22 | }
23 |
24 | export const reducers: ActionReducerMap = {
25 | auth: authReducer,
26 | form: formReducer,
27 | menubar: menubarReducer,
28 | rest: restReducer,
29 | routerReducer: routerReducer,
30 | table: tableReducer,
31 | };
32 |
33 | const localStorageConfig: LocalStorageConfig = {
34 | keys: ['auth'],
35 | rehydrate: true,
36 | storage: localStorage,
37 | removeOnUndefined: false,
38 | };
39 |
40 | export function localStorageSyncReducer(reducer: ActionReducer): ActionReducer {
41 | return localStorageSync(localStorageConfig)(reducer);
42 | }
43 |
44 | export const metaReducers: MetaReducer[] = !environment.production
45 | ? [
46 | // storeFreeze,
47 | localStorageSyncReducer
48 | ]
49 | : [
50 | // storeFreeze,
51 | localStorageSyncReducer
52 | ];
53 |
54 |
55 | // REST
56 | export const getRestState = (state: AppState) => state.rest;
57 | export const getResponse = (state: RestState) => state.response;
58 | export const getRestResponse = createSelector(getRestState, getResponse);
59 |
60 |
61 | export const getRouterState = (state: AppState) => state.routerReducer;
62 | export const getCurrentUrl = createSelector(getRouterState, (state: RouterReducerState) => state.state && state.state.url);
63 | export const getCurrentParams = createSelector(getRouterState, (state: RouterReducerState) => state.state && state.state.params);
64 |
--------------------------------------------------------------------------------
/src/app/app.routing.ts:
--------------------------------------------------------------------------------
1 | import {RouterModule, Routes} from '@angular/router';
2 |
3 | import {FormContainer} from './form/form.container';
4 | import {HomeContainer} from './home/home.container';
5 | import {TableContainer} from './table/table.container';
6 |
7 | export const routes: Routes = [
8 | {
9 | component: HomeContainer,
10 | path: '',
11 | },
12 | {
13 | component: FormContainer,
14 | path: ':selectedSchemaName/rpc/:selectedObjectName',
15 | },
16 | {
17 | component: TableContainer,
18 | path: ':selectedSchemaName/:selectedObjectName',
19 | },
20 | ];
21 |
22 | export const routing = RouterModule.forRoot(routes, { useHash: false });
23 |
--------------------------------------------------------------------------------
/src/app/auth/auth.actions.ts:
--------------------------------------------------------------------------------
1 | import { Action } from '@ngrx/store';
2 |
3 | import { type } from '../util';
4 | import { PostLoginRequestPayload } from './auth.models';
5 |
6 | export const AuthActionTypes = {
7 | ADD_TOKEN: type('ADD_TOKEN'),
8 | REMOVE_TOKEN: type('REMOVE_TOKEN'),
9 | SEND_LOGIN_POST_REQUEST: type('SEND_LOGIN_POST_REQUEST'),
10 | };
11 |
12 | export class SendLoginPostRequestAction implements Action {
13 | type = AuthActionTypes.SEND_LOGIN_POST_REQUEST;
14 |
15 | constructor(public payload: PostLoginRequestPayload) {
16 | }
17 | }
18 |
19 | export class AddTokenAction implements Action {
20 | type = AuthActionTypes.ADD_TOKEN;
21 |
22 | constructor(public payload: string) {
23 | }
24 | }
25 |
26 | export class RemoveTokenAction implements Action {
27 | type = AuthActionTypes.REMOVE_TOKEN;
28 |
29 | constructor(public payload: string) {
30 | }
31 | }
32 |
33 | export type AuthActions = AddTokenAction | RemoveTokenAction;
34 |
--------------------------------------------------------------------------------
/src/app/auth/auth.effects.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | import { of } from 'rxjs/observable/of';
4 |
5 | import { Actions, Effect } from '@ngrx/effects';
6 |
7 | import { ReceivedResponseAction } from '../rest/rest.actions';
8 |
9 | import {
10 | AddTokenAction,
11 | AuthActionTypes,
12 | SendLoginPostRequestAction,
13 | } from './auth.actions';
14 | import { AuthService } from './auth.service';
15 | import { GetMenubarAction } from '../menubar/menubar.actions';
16 | import { Go } from '../router/router.actions';
17 | import { PostLoginRequestPayload } from './auth.models';
18 |
19 |
20 | @Injectable()
21 | export class AuthEffects {
22 |
23 | @Effect()
24 | sendPostRequest$ = this.actions$
25 | .ofType(AuthActionTypes.SEND_LOGIN_POST_REQUEST)
26 | .map((action: SendLoginPostRequestAction) => action.payload)
27 | .switchMap((payload: PostLoginRequestPayload) => {
28 | return this.authService.post_login(payload.schemaName, payload.formName, payload.data)
29 | .map((response: any) => {
30 | const token = response.body[0]['token'];
31 | return new AddTokenAction(token);
32 | })
33 | .catch(error => {
34 | return of(new ReceivedResponseAction(error));
35 | });
36 | });
37 |
38 | @Effect()
39 | addToken$ = this.actions$
40 | .ofType(AuthActionTypes.ADD_TOKEN)
41 | .switchMap(() => [
42 | new Go({path: ['/']}),
43 | new GetMenubarAction()]);
44 |
45 | @Effect()
46 | removeToken$ = this.actions$
47 | .ofType(AuthActionTypes.REMOVE_TOKEN)
48 | .switchMap(() => [
49 | new Go({path: ['/']}),
50 | new GetMenubarAction()]);
51 |
52 | constructor(private actions$: Actions,
53 | private authService: AuthService, ) {
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/app/auth/auth.models.ts:
--------------------------------------------------------------------------------
1 | export interface PostLoginRequestPayload {
2 | formName: string;
3 | schemaName: string;
4 | data: LoginData;
5 | }
6 |
7 | export interface LoginData {
8 | email: string;
9 | password: string;
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/auth/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 |
5 | import { AuthService } from './auth.service';
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | ],
11 | declarations: [
12 | ],
13 | providers: [
14 | AuthService,
15 | ],
16 | exports: [
17 | ]
18 | })
19 | export class AppAuthModule { }
20 |
--------------------------------------------------------------------------------
/src/app/auth/auth.reducers.ts:
--------------------------------------------------------------------------------
1 | import {AuthActions, AuthActionTypes} from './auth.actions';
2 |
3 | export interface AuthState {
4 | token: string | null;
5 | }
6 |
7 | const initialState: AuthState = {
8 | token: null,
9 | };
10 |
11 | export function authReducer (state = initialState, action: AuthActions): AuthState {
12 | switch (action.type) {
13 | case AuthActionTypes.ADD_TOKEN:
14 | return Object.assign({}, state, { token: action.payload });
15 | case AuthActionTypes.REMOVE_TOKEN:
16 | return Object.assign({}, state, { token: null});
17 | default:
18 | return state;
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/app/auth/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | import { Observable } from 'rxjs/Observable';
4 |
5 | import { RestClient } from 'app/rest/rest.service';
6 |
7 | import { LoginData } from './auth.models';
8 |
9 | @Injectable()
10 | export class AuthService {
11 | post_login(schemaName: string, formName: string, loginData: LoginData): Observable