├── src
├── assets
│ ├── .gitkeep
│ ├── logo.png
│ ├── logos.png
│ └── logo.svg
├── styles.scss
├── sass
│ ├── partials
│ │ ├── index.scss
│ │ ├── _login.scss
│ │ └── _home.scss
│ ├── base
│ │ ├── index.scss
│ │ ├── _variables.scss
│ │ ├── _reset.scss
│ │ ├── _typography.scss
│ │ └── _layout.scss
│ ├── components
│ │ ├── index.scss
│ │ ├── _tabs.scss
│ │ ├── _buttons.scss
│ │ ├── _lists.scss
│ │ ├── _table.scss
│ │ ├── _nav.scss
│ │ └── _alerts.scss
│ ├── themes
│ │ ├── index.scss
│ │ ├── _theme.scss
│ │ ├── _light-theme.scss
│ │ ├── _dark-theme.scss
│ │ ├── _mixed-theme.scss
│ │ ├── _black-theme.scss
│ │ └── _snow-white-theme.scss
│ ├── main.scss
│ └── utils
│ │ ├── _spinners.scss
│ │ ├── _margins.scss
│ │ └── _flex.scss
├── app
│ ├── components
│ │ ├── users
│ │ │ ├── models
│ │ │ │ ├── index.ts
│ │ │ │ └── user.model.ts
│ │ │ ├── services
│ │ │ │ ├── index.ts
│ │ │ │ └── user.service.ts
│ │ │ ├── list
│ │ │ │ ├── user-list.component.spec.ts
│ │ │ │ ├── user-list.component.ts
│ │ │ │ └── user-list.component.html
│ │ │ ├── details
│ │ │ │ ├── user-details.component.spec.ts
│ │ │ │ ├── user-details.component.ts
│ │ │ │ └── user-details.component.html
│ │ │ └── shared
│ │ │ │ └── create-edit-user
│ │ │ │ ├── create-edit-user.component.spec.ts
│ │ │ │ ├── create-edit-user.component.html
│ │ │ │ └── create-edit-user.component.ts
│ │ ├── login
│ │ │ ├── login.component.ts
│ │ │ ├── login.component.spec.ts
│ │ │ └── login.component.html
│ │ ├── shared
│ │ │ ├── navbar
│ │ │ │ ├── navbar.component.ts
│ │ │ │ └── navbar.component.html
│ │ │ └── toolbar
│ │ │ │ ├── toolbar.component.html
│ │ │ │ └── toolbar.component.ts
│ │ ├── layout
│ │ │ ├── typography
│ │ │ │ ├── typography.component.ts
│ │ │ │ ├── typography.component.spec.ts
│ │ │ │ └── typography.component.html
│ │ │ ├── alerts-layout
│ │ │ │ ├── alerts-layout.component.ts
│ │ │ │ ├── alerts-layout.component.spec.ts
│ │ │ │ └── alerts-layout.component.html
│ │ │ ├── base
│ │ │ │ ├── layout.component.ts
│ │ │ │ ├── layout.component.spec.ts
│ │ │ │ └── layout.component.html
│ │ │ └── buttons-layout
│ │ │ │ ├── buttons-layout.component.ts
│ │ │ │ ├── buttons-layout.component.spec.ts
│ │ │ │ └── buttons-layout.component.html
│ │ ├── profile
│ │ │ ├── profile.component.ts
│ │ │ ├── profile.component.html
│ │ │ └── profile.component.spec.ts
│ │ ├── dialogs
│ │ │ └── confirm-dialog
│ │ │ │ ├── confirm-dialog.component.html
│ │ │ │ ├── confirm-dialog.component.ts
│ │ │ │ └── confirm-dialog.component.spec.ts
│ │ ├── app
│ │ │ ├── app.component.ts
│ │ │ └── app.component.spec.ts
│ │ ├── home
│ │ │ ├── home.component.spec.ts
│ │ │ ├── home.component.ts
│ │ │ └── home.component.html
│ │ └── settings
│ │ │ ├── settings.component.spec.ts
│ │ │ ├── settings.component.html
│ │ │ └── settings.component.ts
│ ├── services
│ │ ├── index.ts
│ │ ├── http.service.ts
│ │ └── theme.service.ts
│ ├── layouts
│ │ ├── login-layout
│ │ │ ├── login-layout.component.ts
│ │ │ └── login-layout.component.spec.ts
│ │ └── main-layout
│ │ │ ├── main-layout.component.html
│ │ │ ├── main-layout.component.spec.ts
│ │ │ └── main-layout.component.ts
│ ├── directives
│ │ └── ng-init.directive.ts
│ └── app.module.ts
├── favicon.ico
├── typings.d.ts
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── tsconfig.app.json
├── tsconfig.spec.json
├── main.ts
├── test.ts
├── index.html
└── polyfills.ts
├── compilerconfig.json
├── e2e
├── app.po.ts
├── tsconfig.e2e.json
└── app.e2e-spec.ts
├── .editorconfig
├── tsconfig.json
├── .gitignore
├── protractor.conf.js
├── karma.conf.js
├── compilerconfig.json.defaults
├── README.md
├── .angular-cli.json
├── package.json
└── tslint.json
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | @import 'sass/main';
2 |
--------------------------------------------------------------------------------
/src/sass/partials/index.scss:
--------------------------------------------------------------------------------
1 | @import '_home';
2 | @import '_login';
3 |
--------------------------------------------------------------------------------
/src/app/components/users/models/index.ts:
--------------------------------------------------------------------------------
1 | export { User } from './user.model';
2 |
--------------------------------------------------------------------------------
/src/app/components/users/services/index.ts:
--------------------------------------------------------------------------------
1 | export { UserService } from './user.service';
2 |
--------------------------------------------------------------------------------
/src/sass/base/index.scss:
--------------------------------------------------------------------------------
1 | @import '_reset';
2 | @import '_layout';
3 | @import '_typography';
4 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aronium/angular-material-boilerplate/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aronium/angular-material-boilerplate/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/logos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aronium/angular-material-boilerplate/HEAD/src/assets/logos.png
--------------------------------------------------------------------------------
/src/app/services/index.ts:
--------------------------------------------------------------------------------
1 | export { HttpService } from './http.service';
2 | export { ThemeService } from './theme.service';
3 |
--------------------------------------------------------------------------------
/compilerconfig.json:
--------------------------------------------------------------------------------
1 | [
2 | //{
3 | // "outputFile": "src/sass/main.css",
4 | // "inputFile": "src/sass/main.scss"
5 | //}
6 | ]
7 |
--------------------------------------------------------------------------------
/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | /* SystemJS module definition */
2 | declare var module: NodeModule;
3 | interface NodeModule {
4 | id: string;
5 | }
6 |
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 | baseUrl: "https://jsonplaceholder.typicode.com"
4 | };
5 |
--------------------------------------------------------------------------------
/src/sass/base/_variables.scss:
--------------------------------------------------------------------------------
1 | $heading-font-family: 'Roboto Condensed',sans-serif;
2 |
3 | $sidenav-width: 200px;
4 | $light-border-color: rgba(0,0,0,0.12);
5 |
--------------------------------------------------------------------------------
/src/sass/components/index.scss:
--------------------------------------------------------------------------------
1 | @import "_alerts";
2 | @import "_buttons";
3 | @import "_lists";
4 | @import "_table";
5 | @import "_tabs";
6 | @import "_nav";
7 |
--------------------------------------------------------------------------------
/src/app/components/users/models/user.model.ts:
--------------------------------------------------------------------------------
1 | export class User {
2 | name: string = "";
3 | email: string = "";
4 | username: string = "";
5 | phone: string = "";
6 | }
7 |
--------------------------------------------------------------------------------
/src/sass/themes/index.scss:
--------------------------------------------------------------------------------
1 | @import '_theme';
2 | @import '_light-theme';
3 | @import '_mixed-theme';
4 | @import '_snow-white-theme';
5 | @import '_dark-theme';
6 | @import '_black-theme';
7 |
--------------------------------------------------------------------------------
/src/app/components/login/login.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-login',
5 | templateUrl: './login.component.html'
6 | })
7 | export class LoginComponent{ }
8 |
--------------------------------------------------------------------------------
/src/app/components/shared/navbar/navbar.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-navbar',
5 | templateUrl: './navbar.component.html'
6 | })
7 | export class NavBarComponent { }
8 |
--------------------------------------------------------------------------------
/src/app/components/layout/typography/typography.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-typography',
5 | templateUrl: './typography.component.html'
6 | })
7 | export class TypographyComponent{ }
8 |
--------------------------------------------------------------------------------
/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/components/layout/alerts-layout/alerts-layout.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-alerts-layout',
5 | templateUrl: './alerts-layout.component.html'
6 | })
7 | export class AlertsLayoutComponent { }
8 |
--------------------------------------------------------------------------------
/src/app/components/layout/base/layout.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-layout',
5 | templateUrl: './layout.component.html'
6 | })
7 | export class LayoutComponent {
8 | constructor() { }
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/layouts/login-layout/login-layout.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-login-layout',
5 | template: ' ',
6 | styles: []
7 | })
8 | export class LoginLayoutComponent { }
9 |
--------------------------------------------------------------------------------
/src/app/components/layout/buttons-layout/buttons-layout.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-buttons-layout',
5 | templateUrl: './buttons-layout.component.html'
6 | })
7 | export class ButtonsLayoutComponent { }
8 |
--------------------------------------------------------------------------------
/src/sass/base/_reset.scss:
--------------------------------------------------------------------------------
1 | html, body{
2 | margin: 0;
3 | padding: 0;
4 | }
5 | body {
6 | font-family: Roboto, "Helvetica Neue", sans-serif;
7 | font-size: 14px;
8 | -webkit-font-smoothing: antialiased;
9 | }
10 |
11 | main {
12 | padding: 16px;
13 | }
14 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "baseUrl": "./",
6 | "module": "es2015",
7 | "types": []
8 | },
9 | "exclude": [
10 | "test.ts",
11 | "**/*.spec.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/src/sass/main.scss:
--------------------------------------------------------------------------------
1 | // Utils
2 | @import 'utils/_margins';
3 | @import 'utils/_spinners';
4 |
5 | // Themes
6 | @import 'themes/index';
7 |
8 | // Base styles
9 | @import 'base/index';
10 |
11 | // Components
12 | @import 'components/index';
13 |
14 | // Partials / pages
15 | @import 'partials/index';
16 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/e2e",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": [
9 | "jasmine",
10 | "jasminewd2",
11 | "node"
12 | ]
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/components/profile/profile.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-profile',
5 | templateUrl: './profile.component.html'
6 | })
7 | export class ProfileComponent implements OnInit {
8 |
9 | constructor() { }
10 |
11 | ngOnInit() {
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/components/dialogs/confirm-dialog/confirm-dialog.component.html:
--------------------------------------------------------------------------------
1 |
{{ data.title }}
2 |
3 | {{ data.message }}
4 |
5 |
6 | Yes
7 | No
8 |
--------------------------------------------------------------------------------
/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('aronium-inside App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to app!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/app/directives/ng-init.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, Input } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[ngInit]',
5 | exportAs: 'ngInit'
6 | })
7 | export class NgInitDirective {
8 |
9 | @Input() value: any = {};
10 |
11 | @Input() ngInit;
12 | ngOnInit() {
13 | if(this.ngInit) {
14 | this.ngInit();
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/sass/components/_tabs.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | // Tabs
3 | //////////////////////////////////////////////////////////////////////////////
4 |
5 | .tabs-centered{
6 | .mat-tab-labels{
7 | justify-content: center;
8 | }
9 |
10 | &.no-border{
11 | .mat-tab-header{
12 | margin: 0 auto;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": [
9 | "jasmine",
10 | "node"
11 | ]
12 | },
13 | "files": [
14 | "test.ts"
15 | ],
16 | "include": [
17 | "**/*.spec.ts",
18 | "**/*.d.ts"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/src/sass/components/_buttons.scss:
--------------------------------------------------------------------------------
1 | .theme-selector-button{
2 | .mat-button-toggle-label-content{
3 | line-height: 32px;
4 | padding: 0 8px;
5 | .theme-indicator{
6 | color: currentColor;
7 | border: 2px solid currentColor;
8 | border-radius: 50%;
9 |
10 | width: 16px!important;
11 | height: 16px!important;
12 | font-size: 16px!important;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/components/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Inject } from '@angular/core';
2 | import { ThemeService } from '../../services';
3 |
4 | @Component({
5 | selector: 'app-root',
6 | template: ' ',
7 | providers: [ ThemeService ]
8 | })
9 | export class AppComponent {
10 |
11 | constructor(private themeService: ThemeService){
12 | themeService.loadSavedTheme();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/components/users/services/user.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { HttpService } from '../../../services';
3 |
4 | @Injectable()
5 | export class UserService {
6 |
7 | constructor(private http: HttpService) {
8 | }
9 |
10 | getUsers() {
11 | return this.http.get('/users');
12 | }
13 |
14 | getUser(id: any){
15 | return this.http.get(`/users/${id}`);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | import 'hammerjs';
8 |
9 | if (environment.production) {
10 | enableProdMode();
11 | }
12 |
13 | platformBrowserDynamic().bootstrapModule(AppModule)
14 | .catch(err => console.log(err));
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "outDir": "./dist/out-tsc",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "moduleResolution": "node",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "target": "es5",
11 | "typeRoots": [
12 | "node_modules/@types"
13 | ],
14 | "lib": [
15 | "es2017",
16 | "dom"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/components/dialogs/confirm-dialog/confirm-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material'
3 |
4 | @Component({
5 | selector: 'app-confirm-dialog',
6 | templateUrl: './confirm-dialog.component.html'
7 | })
8 | export class ConfirmDialogComponent {
9 | constructor(public dialogRef: MatDialogRef,
10 | @Inject(MAT_DIALOG_DATA) public data: any) { }
11 | }
12 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 |
6 | export const environment = {
7 | production: false,
8 | baseUrl: "https://jsonplaceholder.typicode.com"
9 | };
10 |
--------------------------------------------------------------------------------
/src/app/layouts/main-layout/main-layout.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/sass/utils/_spinners.scss:
--------------------------------------------------------------------------------
1 | @-webkit-keyframes spin-reverse {
2 | 0% {
3 | -webkit-transform: rotate(0deg);
4 | transform: rotate(0deg);
5 | }
6 | 100% {
7 | -webkit-transform: rotate(-360deg);
8 | transform: rotate(-360deg);
9 | }
10 | }
11 |
12 | @keyframes spin-reverse {
13 | 0% {
14 | -webkit-transform: rotate(0deg);
15 | transform: rotate(0deg);
16 | }
17 | 100% {
18 | -webkit-transform: rotate(-360deg);
19 | transform: rotate(-360deg);
20 | }
21 | }
22 |
23 | .spin-reverse{
24 | -webkit-animation: spin-reverse 2s infinite linear;
25 | animation: spin-reverse 2s infinite linear;
26 | }
--------------------------------------------------------------------------------
/src/app/components/profile/profile.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | testem.log
34 | /typings
35 |
36 | # e2e
37 | /e2e/*.js
38 | /e2e/*.map
39 |
40 | # System Files
41 | .DS_Store
42 | Thumbs.db
43 | /.vs
44 |
--------------------------------------------------------------------------------
/src/sass/themes/_theme.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | @include mat-core();
3 |
4 | // Define theme defaults
5 | $app-default: mat-palette($mat-blue, 500);
6 | $app-default-accent: mat-palette($mat-blue-grey, 900);
7 | $app-default-warn: mat-palette($mat-red, 800);
8 |
9 | // Build theme
10 | $theme: mat-light-theme($app-default, $app-default-accent, $app-default-warn);
11 |
12 | // Include custom theme
13 | @include angular-material-theme($theme);
14 |
15 | // Get colors from theme
16 | $accent: map-get($theme, accent);
17 | $primary: map-get($theme, primary);
18 |
19 | $accent-color: mat-color($accent);
20 | $primary-color: mat-color($primary);
--------------------------------------------------------------------------------
/src/app/components/home/home.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { HomeComponent } from './home.component';
4 |
5 | describe('HomeComponent', () => {
6 | let component: HomeComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ HomeComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(HomeComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/login/login.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { LoginComponent } from './login.component';
4 |
5 | describe('LoginComponent', () => {
6 | let component: LoginComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ LoginComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(LoginComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/sass/partials/_login.scss:
--------------------------------------------------------------------------------
1 | .login-container {
2 | display: flex;
3 | justify-content: center;
4 |
5 | .mat-form-field {
6 | width: 300px;
7 | }
8 |
9 | .center {
10 | padding-top: 40px;
11 | text-align: center;
12 | }
13 |
14 | button{
15 | float: right;
16 | min-width: 120px;
17 | }
18 |
19 | input:-webkit-autofill,
20 | input:-webkit-autofill:hover,
21 | input:-webkit-autofill:focus,
22 | input:-webkit-autofill:active {
23 | -webkit-transition: "color 9999s ease-out, background-color 9999s ease-out";
24 | transition: "color 9999s ease-out, background-color 9999s ease-out";
25 | -webkit-transition-delay: 9999s;
26 | transition-delay: 9999s
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/components/layout/base/layout.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { LayoutComponent } from './layout.component';
4 |
5 | describe('LayoutComponent', () => {
6 | let component: LayoutComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ LayoutComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(LayoutComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/profile/profile.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ProfileComponent } from './profile.component';
4 |
5 | describe('ProfileComponent', () => {
6 | let component: ProfileComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ ProfileComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(ProfileComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/login/login.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | email
9 |
10 |
11 |
12 |
13 |
14 | lock
15 |
16 |
17 |
Login
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/app/components/settings/settings.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { SettingsComponent } from './settings.component';
4 |
5 | describe('SettingsComponent', () => {
6 | let component: SettingsComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ SettingsComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(SettingsComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/users/list/user-list.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { UserListComponent } from './user-list.component';
4 |
5 | describe('UserListComponent', () => {
6 | let component: UserListComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ UserListComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(UserListComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/layouts/main-layout/main-layout.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { MainLayoutComponent } from './main-layout.component';
4 |
5 | describe('MainLayoutComponent', () => {
6 | let component: MainLayoutComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ MainLayoutComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(MainLayoutComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/layout/typography/typography.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { TypographyComponent } from './typography.component';
4 |
5 | describe('TypographyComponent', () => {
6 | let component: TypographyComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ TypographyComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(TypographyComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/users/details/user-details.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { UserDetailsComponent } from './user-details.component';
4 |
5 | describe('UserDetailsComponent', () => {
6 | let component: UserDetailsComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ UserDetailsComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(UserDetailsComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/layouts/login-layout/login-layout.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { LoginLayoutComponent } from './login-layout.component';
4 |
5 | describe('LoginLayoutComponent', () => {
6 | let component: LoginLayoutComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ LoginLayoutComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(LoginLayoutComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/layout/alerts-layout/alerts-layout.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { AlertsLayoutComponent } from './alerts-layout.component';
4 |
5 | describe('AlertsLayoutComponent', () => {
6 | let component: AlertsLayoutComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ AlertsLayoutComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(AlertsLayoutComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/dialogs/confirm-dialog/confirm-dialog.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ConfirmDialogComponent } from './confirm-dialog.component';
4 |
5 | describe('ConfirmDialogComponent', () => {
6 | let component: ConfirmDialogComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ ConfirmDialogComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(ConfirmDialogComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/layout/buttons-layout/buttons-layout.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ButtonsLayoutComponent } from './buttons-layout.component';
4 |
5 | describe('ButtonsLayoutComponent', () => {
6 | let component: ButtonsLayoutComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ ButtonsLayoutComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(ButtonsLayoutComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/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 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './e2e/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: 'e2e/tsconfig.e2e.json'
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/sass/components/_lists.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | // Lists
3 | //////////////////////////////////////////////////////////////////////////////
4 |
5 | dl {
6 | &.dl-horizontal {
7 | width: 100%;
8 | overflow: hidden;
9 | padding: 0;
10 | margin: 0;
11 | line-height: 1.5;
12 | font-size: 1em;
13 |
14 | dt {
15 | @media (min-width: 768px) {
16 | float: left;
17 | width: 140px;
18 | clear: left;
19 | }
20 |
21 | overflow: hidden;
22 | text-overflow: ellipsis;
23 | white-space: nowrap;
24 | font-weight: 700;
25 | }
26 |
27 | dd {
28 | margin-left: 0;
29 | margin-bottom: .5rem;
30 |
31 | @media (min-width: 768px) {
32 | margin-left: 160px;
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/app/components/users/shared/create-edit-user/create-edit-user.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { CreateEditUserComponent } from './create-edit-user.component';
4 |
5 | describe('CreateEditUserComponent', () => {
6 | let component: CreateEditUserComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ CreateEditUserComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(CreateEditUserComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/components/layout/typography/typography.component.html:
--------------------------------------------------------------------------------
1 | Typography
2 | Heading 1
3 | Heading 2
4 | Heading 3
5 | Heading 4
6 |
7 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent gravida ut odio id sollicitudin. Aenean suscipit cursus tortor, non tempor magna molestie vehicula. Fusce efficitur ipsum a aliquam condimentum. In auctor dolor vel condimentum ultricies. Proin porta elementum dui at suscipit. Donec convallis euismod lectus, non venenatis ligula. Morbi at enim risus. Etiam id diam mi. Sed bibendum fermentum velit, sed congue massa. Integer sagittis maximus magna ut maximus. Nullam commodo fermentum augue, id commodo odio commodo in. Praesent viverra eros a tempus luctus. Proin blandit blandit mollis. Cras sed eros magna. Fusce mollis enim nulla, vel efficitur urna varius et. Ut in tincidunt sem.
8 |
--------------------------------------------------------------------------------
/src/sass/base/_typography.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | // Headings
3 | //////////////////////////////////////////////////////////////////////////////
4 |
5 | h1, h2{
6 | font-family: $heading-font-family;
7 | font-weight: 300;
8 | }
9 |
10 | .title{
11 | margin-top: 0;
12 | }
13 |
14 |
15 | //////////////////////////////////////////////////////////////////////////////
16 | // Links
17 | //////////////////////////////////////////////////////////////////////////////
18 |
19 | a {
20 | color: $primary-color;
21 | text-decoration: none;
22 | transition: color 0.2s;
23 |
24 | &:hover {
25 | color: $accent-color;
26 | text-decoration: none;
27 | }
28 | }
29 |
30 | .mat-menu-content {
31 | .mat-card {
32 | padding: 10px 24px;
33 |
34 | .mat-card-title {
35 | font-size: 18px;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/app/components/users/shared/create-edit-user/create-edit-user.component.html:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 | done Save
22 |
23 |
24 | Cancel
25 |
26 |
27 | Cancel
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/sass/utils/_margins.scss:
--------------------------------------------------------------------------------
1 | $spaceamounts: (0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 100);
2 |
3 | @mixin generate-margin-bottom() {
4 | @each $space in $spaceamounts {
5 | @if $space == 0 {
6 | .margin-bottom-#{$space} {
7 | margin-bottom: #{$space} !important;
8 | }
9 | }
10 | @else {
11 | .margin-bottom-#{$space} {
12 | margin-bottom: #{$space}px !important;
13 | }
14 | }
15 | }
16 | }
17 |
18 | @mixin generate-margin-top() {
19 | @each $space in $spaceamounts {
20 | @if $space == 0 {
21 | .margin-top-#{$space} {
22 | margin-top: #{$space} !important;
23 | }
24 | }
25 | @else {
26 | .margin-top-#{$space} {
27 | margin-top: #{$space}px !important;
28 | }
29 | }
30 | }
31 | }
32 |
33 | @include generate-margin-bottom();
34 | @include generate-margin-top();
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular/cli'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular/cli/plugins/karma')
14 | ],
15 | client:{
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | reports: [ 'html', 'lcovonly' ],
20 | fixWebpackSourcePaths: true
21 | },
22 | angularCli: {
23 | environment: 'dev'
24 | },
25 | reporters: ['progress', 'kjhtml'],
26 | port: 9876,
27 | colors: true,
28 | logLevel: config.LOG_INFO,
29 | autoWatch: true,
30 | browsers: ['Chrome'],
31 | singleRun: false
32 | });
33 | };
34 |
--------------------------------------------------------------------------------
/src/app/components/settings/settings.component.html:
--------------------------------------------------------------------------------
1 |
2 | Toolbar layout
3 | Full width
4 |
5 |
6 |
7 | Theme ({{ selectedTheme.name }})
8 |
15 |
16 |
17 |
18 | fiber_manual_record
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/app/components/settings/settings.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { MatSnackBar } from '@angular/material';
3 | import 'rxjs/add/operator/filter';
4 |
5 | import { ThemeService } from '../../services';
6 |
7 | @Component({
8 | selector: 'app-settings',
9 | templateUrl: './settings.component.html',
10 | providers: [ ThemeService ]
11 | })
12 | export class SettingsComponent {
13 |
14 | themes: Array = [];
15 |
16 | selectedTheme: any;
17 | isFullWidth: boolean = true;
18 |
19 | constructor(private themeService: ThemeService, private snackBar: MatSnackBar) {
20 | this.themes = themeService.themes;
21 | this.selectedTheme = themeService.currentTheme();
22 |
23 | this.isFullWidth = themeService.isFullWidth();
24 | }
25 |
26 | onThemeSelected(theme: any){
27 | this.themeService.setTheme(theme);
28 |
29 | this.snackBar.open(`Theme changed to "${theme.name}"`, null, {
30 | duration: 3000
31 | });
32 | }
33 |
34 | setFullWidth(isFullWidth: boolean){
35 | this.themeService.setFullWidth(isFullWidth);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/app/components/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 | describe('AppComponent', () => {
4 | beforeEach(async(() => {
5 | TestBed.configureTestingModule({
6 | declarations: [
7 | AppComponent
8 | ],
9 | }).compileComponents();
10 | }));
11 | it('should create the app', async(() => {
12 | const fixture = TestBed.createComponent(AppComponent);
13 | const app = fixture.debugElement.componentInstance;
14 | expect(app).toBeTruthy();
15 | }));
16 | it(`should have as title 'app'`, async(() => {
17 | const fixture = TestBed.createComponent(AppComponent);
18 | const app = fixture.debugElement.componentInstance;
19 | expect(app.title).toEqual('app');
20 | }));
21 | it('should render title in a h1 tag', async(() => {
22 | const fixture = TestBed.createComponent(AppComponent);
23 | fixture.detectChanges();
24 | const compiled = fixture.debugElement.nativeElement;
25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
26 | }));
27 | });
28 |
--------------------------------------------------------------------------------
/src/app/components/layout/alerts-layout/alerts-layout.component.html:
--------------------------------------------------------------------------------
1 | Alerts
2 |
3 |
4 | Error! This is danger alert!
5 |
6 |
7 |
8 | Info! This is info alert!
9 |
10 |
11 |
12 | Success! This is success alert!
13 |
14 |
15 |
16 | Warning! This is warning alert!
17 |
18 |
19 |
20 | Callouts
21 |
22 |
23 |
Error! This is danger callout!
24 |
25 |
26 |
27 |
Info! This is info callout!
28 |
29 |
30 |
31 |
Warning! This is warning callout!
32 |
33 |
34 |
35 |
Success! This is success callout!
36 |
37 |
38 |
--------------------------------------------------------------------------------
/compilerconfig.json.defaults:
--------------------------------------------------------------------------------
1 | {
2 | "compilers": {
3 | "less": {
4 | "autoPrefix": "",
5 | "cssComb": "none",
6 | "ieCompat": true,
7 | "strictMath": false,
8 | "strictUnits": false,
9 | "relativeUrls": true,
10 | "rootPath": "",
11 | "sourceMapRoot": "",
12 | "sourceMapBasePath": "",
13 | "sourceMap": false
14 | },
15 | "sass": {
16 | "includePath": "",
17 | "indentType": "space",
18 | "indentWidth": 2,
19 | "outputStyle": "nested",
20 | "Precision": 5,
21 | "relativeUrls": true,
22 | "sourceMapRoot": "",
23 | "sourceMap": false
24 | },
25 | "stylus": {
26 | "sourceMap": false
27 | },
28 | "babel": {
29 | "sourceMap": false
30 | },
31 | "coffeescript": {
32 | "bare": false,
33 | "runtimeMode": "node",
34 | "sourceMap": false
35 | }
36 | },
37 | "minifiers": {
38 | "css": {
39 | "enabled": true,
40 | "termSemicolons": true,
41 | "gzip": false
42 | },
43 | "javascript": {
44 | "enabled": true,
45 | "termSemicolons": true,
46 | "gzip": false
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/long-stack-trace-zone';
4 | import 'zone.js/dist/proxy.js';
5 | import 'zone.js/dist/sync-test';
6 | import 'zone.js/dist/jasmine-patch';
7 | import 'zone.js/dist/async-test';
8 | import 'zone.js/dist/fake-async-test';
9 | import { getTestBed } from '@angular/core/testing';
10 | import {
11 | BrowserDynamicTestingModule,
12 | platformBrowserDynamicTesting
13 | } from '@angular/platform-browser-dynamic/testing';
14 |
15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
16 | declare const __karma__: any;
17 | declare const require: any;
18 |
19 | // Prevent Karma from running prematurely.
20 | __karma__.loaded = function () {};
21 |
22 | // First, initialize the Angular testing environment.
23 | getTestBed().initTestEnvironment(
24 | BrowserDynamicTestingModule,
25 | platformBrowserDynamicTesting()
26 | );
27 | // Then we find all the tests.
28 | const context = require.context('./', true, /\.spec\.ts$/);
29 | // And load the modules.
30 | context.keys().map(context);
31 | // Finally, start Karma to run the tests.
32 | __karma__.start();
33 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Material Boilerplate
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/sass/components/_table.scss:
--------------------------------------------------------------------------------
1 | @import '../themes/_theme.scss';
2 |
3 | .table {
4 | width: 100%;
5 | max-width: 100%;
6 | border-spacing: 0;
7 | border-collapse: collapse;
8 |
9 | &>caption+thead>tr:first-child>td,
10 | &>caption+thead>tr:first-child>th,
11 | &>colgroup+thead>tr:first-child>td,
12 | &>colgroup+thead>tr:first-child>th,
13 | &>thead:first-child>tr:first-child>td,
14 | &>thead:first-child>tr:first-child>th {
15 | border-top: 0;
16 | text-align: left;
17 | }
18 |
19 | &>tbody>tr>td,
20 | &>tbody>tr>th,
21 | &>tfoot>tr>td,
22 | &>tfoot>tr>th,
23 | &>thead>tr>td,
24 | &>thead>tr>th {
25 | padding: 12px 8px;
26 | line-height: 1.4em;
27 | vertical-align: top;
28 | }
29 |
30 | tr{
31 | border-bottom: 1px solid $light-border-color;
32 | }
33 |
34 | &.table-bordered{
35 | border: 1px solid $light-border-color;
36 | }
37 | }
38 |
39 | @media (max-width: 991px){
40 | .table-responsive {
41 | display: block;
42 | width: 100%;
43 | overflow-x: auto;
44 | overflow-y: hidden;
45 |
46 | tr{
47 | td{
48 | white-space: nowrap;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/components/users/details/user-details.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { ActivatedRoute } from '@angular/router';
3 | import { MatDialog } from '@angular/material';
4 | import { UserService } from '../services';
5 | import { ConfirmDialogComponent } from '../../dialogs/confirm-dialog/confirm-dialog.component';
6 |
7 | @Component({
8 | selector: 'app-user-details',
9 | templateUrl: './user-details.component.html',
10 | providers: [ UserService ]
11 | })
12 | export class UserDetailsComponent implements OnInit {
13 | user: any;
14 |
15 | constructor(private route: ActivatedRoute, private service: UserService, private dialog: MatDialog) { }
16 |
17 | ngOnInit() {
18 | this.route.params.subscribe(params => {
19 | let id = params['id'];
20 | this.getUser(id);
21 | });
22 | }
23 |
24 | private getUser(id: any){
25 | this.service.getUser(id).subscribe(data => this.user = data);
26 | }
27 |
28 | onDelete(): void {
29 | let dialogRef = this.dialog.open(ConfirmDialogComponent, {
30 | data: { title: 'Delete user', message: 'Are you sure you want to delete selected user?' }
31 | });
32 |
33 | dialogRef.afterClosed().subscribe(result => {
34 | console.log('The dialog was closed', result);
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/app/components/shared/toolbar/toolbar.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | menu
5 |
6 |
7 |
8 |
9 |
10 | {{ header }}
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 | Profile & Settings
22 | john.doe@example.com
23 |
24 | person Profile
25 | settings Settings
26 | lock Change password
27 | power_settings_new Logout
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/app/components/users/shared/create-edit-user/create-edit-user.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { ActivatedRoute } from '@angular/router';
3 |
4 | import { UserService } from '../../services';
5 | import { User } from '../../models';
6 |
7 | export enum EditMode {
8 | Create = 0,
9 | Edit = 1
10 | }
11 |
12 | @Component({
13 | selector: 'app-create-edit-user',
14 | templateUrl: './create-edit-user.component.html',
15 | providers: [ UserService ]
16 | })
17 | export class CreateEditUserComponent implements OnInit {
18 | user: User;
19 | editMode: EditMode = EditMode.Create;
20 |
21 | constructor(private route: ActivatedRoute, private service: UserService) { }
22 |
23 | ngOnInit() {
24 | this.route.params.subscribe(params => {
25 | let id = params['id'];
26 | if(id){
27 | this.editMode = EditMode.Edit;
28 | this.getUser(id);
29 | }
30 | else{
31 | this.editMode = EditMode.Create;
32 | this.user = new User();
33 | }
34 | });
35 |
36 | console.log('EditMode', EditMode[this.editMode], this.editMode);
37 | }
38 |
39 | private getUser(id: any){
40 | this.service.getUser(id).subscribe(data => this.user = data);
41 | }
42 |
43 | onSave(){
44 | console.log(this.user);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/sass/themes/_light-theme.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | @include mat-core();
3 |
4 | @import '../base/_variables.scss';
5 |
6 | $primary-light: mat-palette($mat-blue);
7 | $accent-light: mat-palette($mat-light-blue);
8 | $warn-light: mat-palette($mat-red);
9 |
10 | .light-theme{
11 |
12 | $light-theme: mat-light-theme($primary-light, $accent-light, $warn-light);
13 | @include angular-material-theme($light-theme);
14 |
15 | &.theme-indicator{
16 | color: #cccccc!important;
17 | }
18 |
19 | .mat-toolbar{
20 | background: #03A9F4!important;
21 | color: #ffffff!important;
22 | }
23 |
24 | .mat-sidenav{
25 |
26 | background-color: #fafafa!important;
27 |
28 | .sidenav {
29 | a{
30 | color: currentColor!important;
31 |
32 | &.active,
33 | &.active:hover,
34 | &.active:focus,
35 | &.active:active{
36 | background-color: #c5c5c59f!important;
37 | }
38 | }
39 | }
40 | }
41 |
42 | ///////////////////////////////////////////////
43 | // Tables
44 | //////////////////////////////////////////////
45 | .table{
46 | tr{
47 | border-bottom: 1px solid $light-border-color;
48 | }
49 |
50 | &.table-bordered{
51 | border: 1px solid $light-border-color;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular Material Boilerplate
2 |
3 | Boilerplate Angular 4 project with initial setup for angular application with [Material UI](https://material.angular.io/)
4 |
5 | ## Demo
6 | [**VIEW LIVE DEMO**](https://aronium.github.io/angular-material-boilerplate/)
7 |
8 | ## Dev Notes
9 |
10 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.4.5.
11 |
12 | ## Development server
13 |
14 | 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.
15 |
16 | ## Code scaffolding
17 |
18 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
19 |
20 | ## Build
21 |
22 | 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.
23 |
24 | ## Running unit tests
25 |
26 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
27 |
28 | ## Running end-to-end tests
29 |
30 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
31 |
32 | ## Further help
33 |
34 | 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).
35 |
--------------------------------------------------------------------------------
/src/app/components/shared/navbar/navbar.component.html:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/src/sass/themes/_dark-theme.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | @include mat-core();
3 |
4 | $table-border-color: #2F3030;
5 |
6 | $primary-dark: mat-palette($mat-blue, 700);
7 | $accent-dark: mat-palette($mat-light-blue, 600);
8 | $warn-dark: mat-palette($mat-red);
9 |
10 | .dark-theme {
11 |
12 | $dark-theme: mat-dark-theme($primary-dark, $accent-dark, $warn-dark);
13 | @include angular-material-theme($dark-theme);
14 |
15 | &.theme-indicator {
16 | color: #777777 !important;
17 | }
18 |
19 | a {
20 | color: #ffffff;
21 | text-decoration: none;
22 | transition: color 0.2s;
23 |
24 | &:hover {
25 | color: #dadada;
26 | text-decoration: none;
27 | }
28 | }
29 |
30 | .mat-sidenav-container {
31 | .mat-sidenav {
32 | background: #434443 !important;
33 |
34 | .sidenav {
35 |
36 | a {
37 | &.active,
38 | &.active:hover,
39 | &.active:focus,
40 | &.active:active {
41 | background-color: #009CE4!important;
42 | color: #ffffff;
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | ///////////////////////////////////////////////
50 | // Tables
51 | //////////////////////////////////////////////
52 | .table {
53 | tr {
54 | border-bottom: 1px solid $table-border-color;
55 | }
56 |
57 | &.table-bordered {
58 | border-bottom: 1px solid $table-border-color;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/.angular-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "project": {
4 | "name": "aronium-inside"
5 | },
6 | "apps": [
7 | {
8 | "root": "src",
9 | "outDir": "dist",
10 | "assets": [
11 | "assets",
12 | "favicon.ico"
13 | ],
14 | "index": "index.html",
15 | "main": "main.ts",
16 | "polyfills": "polyfills.ts",
17 | "test": "test.ts",
18 | "tsconfig": "tsconfig.app.json",
19 | "testTsconfig": "tsconfig.spec.json",
20 | "prefix": "app",
21 | "styles": [
22 | "styles.scss"
23 | ],
24 | "scripts": [
25 | "../node_modules/chart.js/dist/Chart.bundle.min.js"
26 | ],
27 | "environmentSource": "environments/environment.ts",
28 | "environments": {
29 | "dev": "environments/environment.ts",
30 | "prod": "environments/environment.prod.ts"
31 | }
32 | }
33 | ],
34 | "e2e": {
35 | "protractor": {
36 | "config": "./protractor.conf.js"
37 | }
38 | },
39 | "lint": [
40 | {
41 | "project": "src/tsconfig.app.json",
42 | "exclude": "**/node_modules/**"
43 | },
44 | {
45 | "project": "src/tsconfig.spec.json",
46 | "exclude": "**/node_modules/**"
47 | },
48 | {
49 | "project": "e2e/tsconfig.e2e.json",
50 | "exclude": "**/node_modules/**"
51 | }
52 | ],
53 | "test": {
54 | "karma": {
55 | "config": "./karma.conf.js"
56 | }
57 | },
58 | "defaults": {
59 | "styleExt": "css",
60 | "component": {}
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/sass/themes/_mixed-theme.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | @include mat-core();
3 |
4 | @import '../base/_variables.scss';
5 |
6 | $mixed-primary: mat-palette($mat-blue, 700);
7 | $mixed-accent: mat-palette($mat-light-blue, 700);
8 | $app-light-warn: mat-palette($mat-red, A700);
9 |
10 | .mixed-theme{
11 |
12 | $mixed-theme: mat-light-theme($mixed-primary, $mixed-accent, $app-light-warn);
13 | @include angular-material-theme($mixed-theme);
14 |
15 | &.theme-indicator{
16 | color: rgb(3, 151, 236)!important;
17 | }
18 |
19 | .mat-sidenav-container{
20 | .mat-toolbar{
21 | background: white!important;
22 | color: #444444!important;
23 | border-bottom: 1px solid $light-border-color;
24 |
25 | .logo{
26 | background-position-y: 0!important;
27 | }
28 | }
29 |
30 | .mat-sidenav{
31 | background-color: #0288D1!important;
32 |
33 | .sidenav {
34 | a{
35 | color: #ffffff!important;
36 |
37 | &.active,
38 | &.active:hover,
39 | &.active:focus,
40 | &.active:active{
41 | background-color: #0277BD!important;
42 | color: #ffffff!important;
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | &.theme-indicator{
50 | color: #0288D1!important;
51 | }
52 |
53 | ///////////////////////////////////////////////
54 | // Tables
55 | //////////////////////////////////////////////
56 | .table{
57 | tr{
58 | border-bottom: 1px solid $light-border-color;
59 | }
60 |
61 | &.table-bordered{
62 | border: 1px solid $light-border-color;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng-test",
3 | "version": "0.0.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "ng": "ng",
7 | "start": "ng serve",
8 | "build": "ng build",
9 | "test": "ng test",
10 | "lint": "ng lint",
11 | "e2e": "ng e2e"
12 | },
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "^5.0.3",
16 | "@angular/cdk": "^5.0.0-rc.1",
17 | "@angular/common": "^5.0.0",
18 | "@angular/compiler": "^5.0.0",
19 | "@angular/core": "^5.0.0",
20 | "@angular/forms": "^5.0.0",
21 | "@angular/http": "^5.0.0",
22 | "@angular/material": "^5.0.0-rc.1",
23 | "@angular/platform-browser": "^5.0.0",
24 | "@angular/platform-browser-dynamic": "^5.0.0",
25 | "@angular/router": "^5.0.0",
26 | "angular-svg-round-progressbar": "^1.1.1",
27 | "chart.js": "^2.7.0",
28 | "core-js": "^2.4.1",
29 | "hammerjs": "^2.0.8",
30 | "ng2-charts": "^1.6.0",
31 | "ngx-progressbar": "^2.1.1",
32 | "rxjs": "^5.5.2",
33 | "zone.js": "^0.8.14"
34 | },
35 | "devDependencies": {
36 | "@angular/cli": "^1.6.4",
37 | "@angular/compiler-cli": "^5.0.0",
38 | "@angular/language-service": "^5.0.0",
39 | "@types/jasmine": "~2.5.53",
40 | "@types/jasminewd2": "~2.0.2",
41 | "@types/node": "~6.0.60",
42 | "codelyzer": "^4.0.1",
43 | "jasmine-core": "~2.6.2",
44 | "jasmine-spec-reporter": "~4.1.0",
45 | "karma": "~1.7.0",
46 | "karma-chrome-launcher": "~2.1.1",
47 | "karma-cli": "~1.0.1",
48 | "karma-coverage-istanbul-reporter": "^1.2.1",
49 | "karma-jasmine": "~1.1.0",
50 | "karma-jasmine-html-reporter": "^0.2.2",
51 | "protractor": "~5.1.2",
52 | "ts-node": "~3.2.0",
53 | "tslint": "~5.7.0",
54 | "typescript": "~2.4.2"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/app/components/users/list/user-list.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | import { UserService } from '../services';
4 |
5 | @Component({
6 | selector: 'app-user-list',
7 | templateUrl: './user-list.component.html',
8 | providers: [UserService]
9 | })
10 | export class UserListComponent implements OnInit {
11 |
12 | private allUsersChecked: boolean = false;
13 |
14 | users: Array;
15 | isAdvancedSearchEnabled: boolean = false;
16 | email:string;
17 | startDate: Date = null;
18 | endDate:Date = null;
19 | state:string;
20 | states = [
21 | 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware',
22 | 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky',
23 | 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi',
24 | 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico',
25 | 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania',
26 | 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
27 | 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'
28 | ];
29 |
30 | constructor(private service: UserService) { }
31 |
32 | ngOnInit() {
33 | this.loadUsers();
34 | }
35 |
36 | private loadUsers(): void{
37 | this.service.getUsers().subscribe(data => {
38 | this.users = data
39 | });
40 | }
41 |
42 | onRefresh(){
43 | this.users = null;
44 |
45 | this.loadUsers();
46 | }
47 |
48 | checkAll() {
49 | this.allUsersChecked = !this.allUsersChecked;
50 | for (let i in this.users) {
51 | this.users[i].selected = this.allUsersChecked;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/app/components/users/details/user-details.component.html:
--------------------------------------------------------------------------------
1 |
2 | arrow_back Back to list
3 |
4 |
5 | edit
6 |
7 |
8 | delete
9 |
10 |
11 |
12 |
13 | {{ user.name }}
14 | Username: {{ user.username }}
15 |
16 |
17 | Name
18 | {{ user.name }}
19 | Username
20 | {{ user.username }}
21 | Email
22 | {{ user.email }}
23 | Phone
24 | {{ user.phone }}
25 | Web
26 | {{ user.website }}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Company
35 |
36 |
37 | Company name
38 | {{ user.company.name }}
39 |
40 | Additional data
41 | {{ user.company.catchPhrase }}
42 |
43 | Product search type
44 |
45 | {{ user.company.bs }}
46 |
47 |
48 |
49 |
50 |
51 |
52 | edit
53 |
54 |
--------------------------------------------------------------------------------
/src/app/components/layout/buttons-layout/buttons-layout.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Flat Buttons
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Raised Buttons
20 |
21 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | Fab Buttons
36 |
37 |
38 | done
39 |
40 |
41 | add
42 |
43 |
44 | close
45 |
46 |
47 | remove
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/services/http.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { HttpClient, HttpHeaders } from '@angular/common/http';
3 | import { Observable } from 'rxjs/Rx';
4 | import { Router } from '@angular/router';
5 | import { environment } from '../../environments/environment';
6 |
7 | import 'rxjs/Rx';
8 |
9 | @Injectable()
10 | export class HttpService {
11 |
12 | private baseUrl: string;
13 |
14 | constructor(private http: HttpClient, private router: Router) {
15 | this.baseUrl = environment.baseUrl;
16 | }
17 |
18 | private getHeaders(): HttpHeaders {
19 | let headers = new HttpHeaders().set('Content-Type', 'application/json');
20 |
21 | let user = localStorage.getItem('user');
22 |
23 | if (user) {
24 | // HttpHeaders are immutable, set() method returns new instance of HttpHeaders
25 | headers = headers.set('Authorization', `Bearer ${JSON.parse(user).token}`);
26 | }
27 |
28 | return headers;
29 | }
30 |
31 | private onError(error: any): Promise {
32 | if (error.status === 401 || error.status === 403) {
33 | this.router.navigate(['/login']);
34 | }
35 | return Promise.reject(error);
36 | }
37 |
38 | /**
39 | * Executes GET request for specified url.
40 | * @param url Url to execute.
41 | */
42 | get(url: string): Observable {
43 | return this.http.get(`${this.baseUrl}${url}`, {
44 | headers: this.getHeaders()
45 | }).catch(error => this.onError(error));
46 | }
47 |
48 | /**
49 | * Executes POST request with specified url and data
50 | * @param url Request Url.
51 | * @param data Post data.
52 | */
53 | post(url: string, data: any): Observable {
54 | return this.http.post(`${this.baseUrl}${url}`, data, {
55 | headers: this.getHeaders()
56 | }).catch(error => this.onError(error));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/sass/themes/_black-theme.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | @include mat-core();
3 |
4 | $toolbar-border-color: #424242;
5 |
6 | $primary-black: mat-palette($mat-blue-grey, 600);
7 | $accent-black: mat-palette($mat-blue-grey, 800);
8 | $warn-black: mat-palette($mat-red, 900);
9 |
10 | .black-theme {
11 |
12 | $black-theme: mat-dark-theme($primary-black, $accent-black, $warn-black);
13 | @include angular-material-theme($black-theme);
14 |
15 | &.theme-indicator {
16 | color: #111111 !important;
17 | }
18 |
19 | .mat-sidenav-container {
20 | background: #252525 !important;
21 |
22 | .mat-toolbar {
23 | background: #222222 !important;
24 | border-bottom: 1px solid $toolbar-border-color;
25 | }
26 |
27 | .mat-sidenav-content {
28 |
29 | a {
30 | color: #ffffff;
31 | text-decoration: none;
32 | transition: color 0.2s;
33 |
34 | &:hover {
35 | color: #dadada;
36 | text-decoration: none;
37 | }
38 | }
39 |
40 | .mat-card {
41 | background: #313131 !important;
42 |
43 | .info-card-icon{
44 | background-color: inherit !important;
45 | }
46 | }
47 | }
48 |
49 | .mat-sidenav {
50 | background: #222222 !important;
51 | border-right: 1px solid $toolbar-border-color;
52 |
53 | .sidenav {
54 | a {
55 | color: #ffffff !important;
56 |
57 | &.active,
58 | &.active:hover,
59 | &.active:focus,
60 | &.active:active {
61 | background: #1d1c1c !important;
62 | color: #ffffff !important;
63 | }
64 | }
65 | }
66 | }
67 | }
68 |
69 | ///////////////////////////////////////////////
70 | // Tables
71 | //////////////////////////////////////////////
72 | .table{
73 | tr{
74 | border-bottom: 1px solid #262827;
75 | }
76 |
77 | &.table-bordered{
78 | border: 1px solid #262827;
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/src/sass/themes/_snow-white-theme.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | @include mat-core();
3 |
4 | @import '../base/_variables.scss';
5 |
6 | $primary-white: mat-palette($mat-blue, 700);
7 | $accent-white: mat-palette($mat-light-blue, 600);
8 | $warn-white: mat-palette($mat-red);
9 |
10 | $foreground: #444444;
11 |
12 | .snow-white-theme{
13 |
14 | $snow-theme: mat-light-theme($primary-white, $accent-white, $warn-white);
15 | @include angular-material-theme($snow-theme);
16 |
17 | &.theme-indicator{
18 | color: #ffffff!important;
19 | border-color: #efefef!important;
20 | }
21 |
22 | .mat-sidenav-container{
23 | background: white!important;
24 |
25 | .mat-toolbar{
26 | background: white!important;
27 | color: $foreground!important;
28 | border-bottom: 1px solid $light-border-color;
29 |
30 | .logo{
31 | background-position-y: 0!important;
32 | }
33 | }
34 |
35 | .mat-sidenav-content{
36 | .mat-card{
37 | &.info-card{
38 | background-color: inherit !important;
39 | color: inherit !important;
40 |
41 | .info-card-icon{
42 | background-color: inherit !important;
43 | }
44 | }
45 | }
46 | }
47 |
48 | .mat-sidenav{
49 | border-right: 1px solid $light-border-color;
50 | background: white!important;
51 |
52 | .sidenav {
53 | a{
54 | color: #444444!important;
55 |
56 | &.active,
57 | &.active:hover,
58 | &.active:focus,
59 | &.active:active{
60 | background-color: rgba(0,0,0,0.1)!important;
61 | color: #111111!important;
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 | ///////////////////////////////////////////////
69 | // Tables
70 | //////////////////////////////////////////////
71 | .table{
72 | tr{
73 | border-bottom: 1px solid $light-border-color;
74 | }
75 |
76 | &.table-bordered{
77 | border: 1px solid $light-border-color;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/app/components/shared/toolbar/toolbar.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2 | import { NavigationEnd, Router, ActivatedRoute } from '@angular/router';
3 | import { forEach } from '@angular/router/src/utils/collection';
4 | import { Title } from '@angular/platform-browser';
5 |
6 | @Component({
7 | selector: 'app-toolbar',
8 | templateUrl: './toolbar.component.html'
9 | })
10 | export class ToolbarComponent implements OnInit {
11 |
12 | private sub: any;
13 | private defaultTitle: string;
14 |
15 | @Input()
16 | header: string;
17 |
18 | @Output()
19 | toggleMenu = new EventEmitter();
20 |
21 | constructor(private router: Router,
22 | private route: ActivatedRoute,
23 | private titleService: Title) { }
24 |
25 | /**
26 | * Dispatch toggleMenu event.
27 | */
28 | onToggleMenu() {
29 | this.toggleMenu.emit();
30 | }
31 |
32 | ngOnInit() {
33 | // Use default header as the document title or a fallback for toolbar title
34 | this.defaultTitle = this.header;
35 |
36 | // Get initial title on page load
37 | this.getPageTitle();
38 |
39 | this.sub = this.router.events
40 | .filter(event => event instanceof NavigationEnd)
41 | .subscribe((event: NavigationEnd) => {
42 | this.getPageTitle();
43 | });
44 | }
45 |
46 | private getPageTitle(): void {
47 | let parentRouteTitle;
48 | let snapshot = this.route.snapshot;
49 | let activated = this.route.firstChild;
50 | if (activated != null) {
51 | while (activated != null) {
52 | // Get title for the current route, if case child is missing rote data, use parent title.
53 | parentRouteTitle = snapshot.data['title'] || parentRouteTitle;
54 |
55 | snapshot = activated.snapshot;
56 | activated = activated.firstChild;
57 | }
58 | }
59 |
60 | // Set header, fallback to default title if data not set on route
61 | let title = snapshot.data['title'] || parentRouteTitle;
62 |
63 | // If any custom title is set, use it
64 | this.header = title || this.defaultTitle;
65 |
66 | // Set document title
67 | this.titleService.setTitle(title ? `${this.defaultTitle} - ${title}` : this.defaultTitle)
68 | }
69 |
70 | ngOnDestroy() {
71 | this.sub.unsubscribe();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/sass/components/_nav.scss:
--------------------------------------------------------------------------------
1 | @import '../themes/_theme.scss';
2 |
3 | $expand-icon-size: 16px;
4 |
5 | body{
6 | // If .full-width is not set on main container, add logo to sidenav
7 | :not(.full-width){
8 | .sidenav{
9 | .logo{
10 | margin: 0 auto;
11 | margin-top: 20px;
12 | width: 100px;
13 | height: 100px;
14 |
15 | background-image: url('/assets/logos.png');
16 | background-repeat: no-repeat;
17 | background-position-y: -90px;
18 | }
19 | }
20 | }
21 | }
22 |
23 | .mat-sidenav-container{
24 | .mat-sidenav{
25 | background-color: #37474C;
26 |
27 | .sidenav {
28 | width: $sidenav-width !important;
29 |
30 | .mat-icon{
31 | height: 22px;
32 | width: 22px;
33 | font-size: 22px;
34 | }
35 |
36 | a{
37 | font-size: 14px!important;
38 | color: #ffffff;
39 |
40 | span{
41 | margin-left: 10px;
42 | }
43 |
44 | &.active,
45 | &.active:hover,
46 | &.active:focus,
47 | &.active:active{
48 | background-color: $accent-color;
49 | color: #ffffff;
50 | }
51 | }
52 |
53 | ul, li{
54 | list-style: none;
55 | padding: 0;
56 | margin: 0;
57 |
58 | .expand-icon{
59 | transition: all 500ms ease;
60 | height: $expand-icon-size;
61 | width: $expand-icon-size;
62 | font-size: $expand-icon-size;
63 |
64 | &::after{
65 | content: 'add';
66 | }
67 |
68 | &.collapse{
69 | // Using expand_more icon with rotation
70 | // -webkit-transform: rotate(-180deg);
71 | // -moz-transform: rotate(-180deg);
72 | // transform: rotate(-180deg);
73 |
74 | &::after{
75 | content: 'remove';
76 | }
77 | }
78 | }
79 |
80 | ul{
81 | text-indent: 22px;
82 |
83 | &.collapsed{
84 | display: none;
85 |
86 | // transition: max-height 0.1s;
87 | // max-height: 0;
88 | // overflow: hidden;
89 | }
90 | &.expanded{
91 | display: block;
92 |
93 | // transition: max-height 0.5s;
94 | // max-height: 100vh;
95 | }
96 | }
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/app/components/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-home',
5 | templateUrl: './home.component.html'
6 | })
7 | export class HomeComponent {
8 |
9 | loading: boolean = false;
10 |
11 | barChartData: Array = [[27, 33, 32, 34, 48, 42, 30, 37, 23, 33, 6, 7, 9, 17, 7, 10, 10, 10, 16, 6, 9, 18, 24, 8, 11, 10, 23, 31, 22, 26]];
12 | barChartLabels: Array = ["Fri 01", "Sat 02", "Sun 03", "Mon 04", "Tue 05", "Wed 06", "Thu 07", "Fri 08", "Sat 09", "Sun 10", "Mon 11", "Tue 12", "Wed 13", "Thu 14", "Fri 15", "Sat 16", "Sun 17", "Mon 18", "Tue 19", "Wed 20", "Thu 21", "Fri 22", "Sat 23", "Sun 24", "Mon 25", "Tue 26", "Wed 27", "Thu 28", "Fri 29", "Sat 30"];
13 | barChartColors = [{ backgroundColor: 'rgba(0, 156, 228, 0.80)' }]
14 |
15 | lineChartData: Array = [[10, 30, 33, 80, 87, 101, 112]];
16 | lineChartLabels: Array = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
17 | lineChartColors = [{ backgroundColor: 'rgba(0,0,0,0.0)', borderColor: 'rgba(92, 184, 92, 0.8)' }]
18 |
19 | versionsData: Array = [[2, 1, 2, 1, 1, 8, 2, 2, 1, 1, 1, 12, 26, 8, 17, 6, 4, 54, 34]];
20 | versionsLabels: Array = ['0.9.5.0', '1.2.0.0', '1.3.1.0', '1.4.0.0', '1.6.0.0', '1.7.0.0', '1.7.1.0', '1.8.0.0', '1.9.0.0', '1.10.0.0', '1.10.1.1', '1.11.0.0', '1.12.0.0', '1.13.0.0', '1.13.1.0', '1.13.2.0', '1.13.3.0', '1.14.0.0', '1.14.1.0'];
21 |
22 | pieChartData: Array = [[10, 100, 154, 184, 476, 95, 133, 408, 619, 363]];
23 | pieChartLabels: Array = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct'];
24 | pieChart2Data: Array = [[112,55]];
25 | pieChart2Labels: Array = ['Active', 'Inactive'];
26 | pieChart2Colors: any[] = [{ backgroundColor: ['rgba(21,101,192,.8)', 'rgba(96,125,139,.7)'] }];
27 | pieChart3Data: Array = [[95, 78]];
28 | pieChart3Labels: Array = ['Dark', 'Light'];
29 |
30 | chartOptions = {
31 | bezierCurve: false,
32 | responsive: true,
33 | maintainAspectRatio: false,
34 | elements: {
35 | line: {
36 | tension: 0
37 | }
38 | },
39 | legend: {
40 | display: false
41 | }
42 | };
43 |
44 | pieChartOptions: any = {
45 | cutoutPercentage: 0,
46 | responsive: true,
47 | maintainAspectRatio: false,
48 | legend: {
49 | display: false,
50 | }
51 | };
52 |
53 | constructor() { }
54 |
55 | onRefresh(){
56 | this.loading = true;
57 |
58 | setTimeout(() => {
59 | this.loading = false;
60 | }, 2000);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/app/components/layout/base/layout.component.html:
--------------------------------------------------------------------------------
1 | Flex layout
2 |
7 |
8 |
9 | .col
10 |
11 |
12 | .col
13 |
14 |
15 |
16 |
17 | .col
18 |
19 |
20 | .col
21 |
22 |
23 | .col
24 |
25 |
26 |
27 |
28 | .col
29 |
30 |
31 | .col
32 |
33 |
34 | .col
35 |
36 |
37 | .col
38 |
39 |
40 |
41 |
42 | .col
43 |
44 |
45 | .col
46 |
47 |
48 | .col
49 |
50 |
51 | .col
52 |
53 |
54 | .col
55 |
56 |
57 | .col
58 |
59 |
60 |
61 | Nested flex containers
62 | Using nesting so columns keeps the same width as flex items put directly in container, aligned to above examples.
63 |
64 |
65 |
66 | .col
67 |
68 |
69 |
70 |
71 | .col
72 |
73 |
74 | .col
75 |
76 |
77 |
78 |
79 |
80 | Using ".col-x" classes to grow content in container
81 |
82 |
83 | .col .col-x2
84 |
85 |
86 | .col
87 |
88 |
89 |
90 |
91 | .col .col-x3
92 |
93 |
94 | .col
95 |
96 |
97 |
98 |
99 | .col .col-x4
100 |
101 |
102 | .col
103 |
104 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/weak-map';
35 | // import 'core-js/es6/set';
36 |
37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
38 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
39 |
40 | /** Evergreen browsers require these. **/
41 | import 'core-js/es6/reflect';
42 | import 'core-js/es7/reflect';
43 |
44 |
45 | /**
46 | * Required to support Web Animations `@angular/platform-browser/animations`.
47 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
48 | **/
49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
50 |
51 |
52 |
53 | /***************************************************************************************************
54 | * Zone JS is required by Angular itself.
55 | */
56 | import 'zone.js/dist/zone'; // Included with Angular CLI.
57 |
58 |
59 |
60 | /***************************************************************************************************
61 | * APPLICATION IMPORTS
62 | */
63 |
64 | /**
65 | * Date, currency, decimal and percent pipes.
66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
67 | */
68 | // import 'intl'; // Run `npm install --save intl`.
69 | /**
70 | * Need to import at least one locale-data with intl.
71 | */
72 | // import 'intl/locale-data/jsonp/en';
73 |
--------------------------------------------------------------------------------
/src/app/services/theme.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | @Injectable()
4 | export class ThemeService {
5 |
6 | themes: Array = [
7 | { value: 'default', name: 'Default', cssClass: null },
8 | { value: 'light', name: 'Light', cssClass: 'light-theme' },
9 | { value: 'snow-white', name: 'Snow white', cssClass: 'snow-white-theme' },
10 | { value: 'mixed', name: 'Mixed', cssClass: 'mixed-theme' },
11 | { value: 'Dark', name: 'Dark', cssClass: 'dark-theme' },
12 | { value: 'black', name: 'Black', cssClass: 'black-theme' }
13 | ];
14 |
15 | /**
16 | * Loads saved theme and sets required classes to body element.
17 | */
18 | loadSavedTheme(){
19 | let theme = localStorage.getItem('theme');
20 | if(theme !== undefined){
21 | let selectedTheme = JSON.parse(theme);
22 | if(selectedTheme != null && selectedTheme.cssClass){
23 | let body = document.getElementsByTagName('body')[0];
24 | body.classList.add(selectedTheme.cssClass);
25 | }
26 | }
27 |
28 | // Set toolbar width
29 | let fullWidthSaved = localStorage.getItem('fullWidth');
30 | if(fullWidthSaved){
31 | this.setFullWidth(JSON.parse(fullWidthSaved));
32 | }
33 | }
34 |
35 | /**
36 | * Gets current theme.
37 | */
38 | currentTheme(){
39 | let storedTheme = localStorage.getItem('theme');
40 |
41 | if(storedTheme != null){
42 | let tempTheme = JSON.parse(storedTheme);
43 | let theme = this.themes.filter(theme => theme.value && theme.value === tempTheme.value);
44 |
45 | if(theme != null)
46 | return theme[0];
47 | }
48 |
49 | return this.themes[0];
50 | }
51 |
52 | /**
53 | * Sets theme.
54 | *
55 | * @param theme Theme to use.
56 | */
57 | setTheme(theme: any){
58 | let body = document.getElementsByTagName('body')[0];
59 | this.themes.forEach(theme => body.classList.remove(theme.cssClass));
60 | localStorage.removeItem('theme');
61 |
62 | if(theme.cssClass){
63 | localStorage.setItem('theme', JSON.stringify(theme));
64 | body.classList.add(theme.cssClass);
65 | }
66 | }
67 |
68 | isFullWidth(): boolean{
69 | let fullWidthSaved = localStorage.getItem('fullWidth');
70 | if(fullWidthSaved){
71 | return JSON.parse(fullWidthSaved) as boolean;
72 | }
73 | else{
74 | let body = document.getElementsByTagName('body')[0];
75 | return body.classList.contains('full-width');
76 | }
77 | }
78 |
79 | /**
80 | * Sets toolbar full width options.
81 | *
82 | * @param fullWidth Indicates whether toolbar is displayed in full width.
83 | */
84 | setFullWidth(fullWidth: boolean){
85 | let body = document.getElementsByTagName('body')[0];
86 | localStorage.setItem('fullWidth', JSON.stringify(fullWidth));
87 |
88 | if(fullWidth){
89 | body.classList.add('full-width');
90 | }
91 | else{
92 | body.classList.remove('full-width');
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/app/layouts/main-layout/main-layout.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, OnDestroy, ViewChild, ElementRef, HostListener } from '@angular/core';
2 | import { Router, NavigationStart } from '@angular/router';
3 | import { MatSidenav } from '@angular/material';
4 | import { ISubscription } from 'rxjs/Subscription'
5 | import 'rxjs/add/operator/filter';
6 |
7 | @Component({
8 | selector: 'app-main-layout',
9 | templateUrl: './main-layout.component.html'
10 | })
11 | export class MainLayoutComponent implements OnInit, OnDestroy {
12 | @ViewChild('sidenav') sidenav: MatSidenav;
13 |
14 | sidenavMode: string;
15 | isSidenavOpen: boolean = true;
16 | navigationSubscription: ISubscription;
17 |
18 | constructor(private router: Router) { }
19 |
20 | /**
21 | * Gets current side nav mode for page refresh, if any.
22 | * Sidenav mode is stored in localStorage for later use.
23 | */
24 | private wasSidenavOpen(): boolean {
25 | let savedState = localStorage.getItem("sidenavOpen");
26 |
27 | if (savedState) {
28 | return JSON.parse(savedState);
29 | }
30 |
31 | return true;
32 | }
33 |
34 | /**
35 | * Sets correct sidenav mode based on window size.
36 | */
37 | private setSidenavMode() {
38 | if (window.innerWidth < 768) {
39 | this.sidenavMode = 'over';
40 | this.isSidenavOpen = false;
41 |
42 | this.sidenav.close();
43 | }
44 | else {
45 | this.sidenavMode = 'side';
46 | this.isSidenavOpen = this.wasSidenavOpen();
47 | if (this.isSidenavOpen)
48 | this.sidenav.open();
49 | }
50 | }
51 |
52 | /**
53 | * Creates subscription to navigation change event.
54 | * Used to toggle side menu if one is in "over" mode.
55 | */
56 | private subscribeToRouteChangeEvent() {
57 | // Hide sidenav on route change if using 'over' mode
58 | this.navigationSubscription = this.router.events
59 | .filter(event => event instanceof NavigationStart)
60 | .subscribe((event: NavigationStart) => {
61 | if (this.sidenav.mode === 'over')
62 | this.sidenav.close();
63 | });
64 | }
65 |
66 | /**
67 | * Handes window resilze.
68 | *
69 | * @param event Event args.
70 | */
71 | @HostListener('window:resize', ['$event'])
72 | onResize(event) {
73 | this.setSidenavMode();
74 | }
75 |
76 | /**
77 | * Method executed on component initialization.
78 | */
79 | ngOnInit() {
80 | this.subscribeToRouteChangeEvent();
81 | this.setSidenavMode();
82 | }
83 |
84 | /**
85 | * Method executed on component destroy.
86 | */
87 | ngOnDestroy(): void {
88 | if (this.navigationSubscription) {
89 | this.navigationSubscription.unsubscribe();
90 | }
91 | }
92 |
93 | /**
94 | * Toggles sidenav based on current sidenav settings.
95 | */
96 | toggleSidenav() {
97 | if (this.sidenavMode === 'side') {
98 | this.sidenav.toggle();
99 | this.isSidenavOpen = !this.isSidenavOpen;
100 |
101 | // Keep open state for desktops only
102 | localStorage.setItem("sidenavOpen", JSON.stringify(this.isSidenavOpen));
103 | }
104 | else {
105 | this.sidenav.open();
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/sass/components/_alerts.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | // Alerts
3 | //////////////////////////////////////////////////////////////////////////////
4 | .alert{
5 | padding: 15px 10px;
6 | border-width: 1px;
7 | border-style: solid;
8 | font-size: 16px;
9 | border-radius: 2px;
10 |
11 | margin-bottom: 10px;
12 | clear: both;
13 |
14 | box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);
15 |
16 | .mat-icon{
17 | float: left;
18 | margin-right: 10px;
19 | margin-top: -2px;
20 | }
21 |
22 | &.alert-danger{
23 | background-color: #D32F2F;
24 | border-color: #D32F2F;
25 | color: #ffffff;
26 |
27 | .mat-icon{
28 | &::after{
29 | content: 'error_outline';
30 | }
31 | }
32 | }
33 |
34 | &.alert-warning{
35 | background-color: #f6c342;
36 | border-color: #f6c342;
37 | color: #E65100;
38 |
39 | .mat-icon{
40 | &::after{
41 | content: 'warning';
42 | }
43 | }
44 | }
45 |
46 | &.alert-info{
47 | background-color: #03A9F4;
48 | border-color: #03A9F4;
49 | color: #ffffff;
50 |
51 | .mat-icon{
52 | &::after{
53 | content: 'info';
54 | }
55 | }
56 | }
57 |
58 | &.alert-success{
59 | background-color: #4CAF50;
60 | border-color: #4CAF50;
61 | color: #ffffff;
62 |
63 | .mat-icon{
64 | &::after{
65 | content: 'done';
66 | }
67 | }
68 | }
69 | }
70 |
71 |
72 | .callout {
73 | border-top: 1px solid #3572b0;
74 | border-right: 1px solid #3572b0;
75 | border-bottom: 1px solid #3572b0;
76 | border-left: 1px solid #3572b0;
77 | border-radius: 3px;
78 | color: currentColor;
79 | line-height: 20px;
80 | margin: 20px 0 20px 0;
81 | overflow-wrap: break-word;
82 | padding-bottom: 20px;
83 | padding-left: 60px;
84 | padding-right: 40px;
85 | padding-top: 20px;
86 | position: relative;
87 | word-wrap: break-word;
88 | word-break: break-word;
89 |
90 | h4{
91 | margin: 0 0 10px;
92 | font-size: 18px;
93 | font-weight: normal;
94 | }
95 |
96 | &:before {
97 | background-color: #3572b0;
98 | bottom: 0;
99 | left: 0;
100 | position: absolute;
101 | top: 0;
102 | width: 40px;
103 | line-height: 24px;
104 | width: 32px;
105 | padding-left: 8px;
106 | display: flex;
107 | align-items: center;
108 |
109 | direction: ltr;
110 | font-family: 'Material Icons';
111 | font-size: 24px;
112 | font-style: normal;
113 | font-weight: normal;
114 | letter-spacing: normal;
115 | line-height: 1;
116 | text-transform: none;
117 | white-space: nowrap;
118 | word-wrap: normal;
119 | -webkit-font-feature-settings: 'liga';
120 | -webkit-font-smoothing: antialiased;
121 | content: 'info';
122 | color: #ffffff;
123 | }
124 |
125 | &.callout-danger {
126 | border-color: #d04437;
127 |
128 | &:before {
129 | content: 'error_outline';
130 | background-color: #d04437;
131 | }
132 | }
133 |
134 | &.callout-warning {
135 | border-color: #f6c342;
136 |
137 | &:before {
138 | content: 'warning';
139 | background-color: #f6c342;
140 | }
141 | }
142 |
143 | &.callout-success {
144 | border-color: #4CAF50;
145 |
146 | &:before {
147 | content: 'done_all';
148 | background-color: #4CAF50;
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "eofline": true,
15 | "forin": true,
16 | "import-blacklist": [
17 | true,
18 | "rxjs"
19 | ],
20 | "import-spacing": true,
21 | "indent": [
22 | true,
23 | "spaces"
24 | ],
25 | "interface-over-type-literal": true,
26 | "label-position": true,
27 | "max-line-length": [
28 | true,
29 | 140
30 | ],
31 | "member-access": false,
32 | "member-ordering": [
33 | true,
34 | {
35 | "order": [
36 | "static-field",
37 | "instance-field",
38 | "static-method",
39 | "instance-method"
40 | ]
41 | }
42 | ],
43 | "no-arg": true,
44 | "no-bitwise": true,
45 | "no-console": [
46 | true,
47 | "debug",
48 | "info",
49 | "time",
50 | "timeEnd",
51 | "trace"
52 | ],
53 | "no-construct": true,
54 | "no-debugger": true,
55 | "no-duplicate-super": true,
56 | "no-empty": false,
57 | "no-empty-interface": true,
58 | "no-eval": true,
59 | "no-inferrable-types": [
60 | true,
61 | "ignore-params"
62 | ],
63 | "no-misused-new": true,
64 | "no-non-null-assertion": true,
65 | "no-shadowed-variable": true,
66 | "no-string-literal": false,
67 | "no-string-throw": true,
68 | "no-switch-case-fall-through": true,
69 | "no-trailing-whitespace": true,
70 | "no-unnecessary-initializer": true,
71 | "no-unused-expression": true,
72 | "no-use-before-declare": true,
73 | "no-var-keyword": true,
74 | "object-literal-sort-keys": false,
75 | "one-line": [
76 | true,
77 | "check-open-brace",
78 | "check-catch",
79 | "check-else",
80 | "check-whitespace"
81 | ],
82 | "prefer-const": true,
83 | "quotemark": [
84 | true,
85 | "single"
86 | ],
87 | "radix": true,
88 | "semicolon": [
89 | true,
90 | "always"
91 | ],
92 | "triple-equals": [
93 | true,
94 | "allow-null-check"
95 | ],
96 | "typedef-whitespace": [
97 | true,
98 | {
99 | "call-signature": "nospace",
100 | "index-signature": "nospace",
101 | "parameter": "nospace",
102 | "property-declaration": "nospace",
103 | "variable-declaration": "nospace"
104 | }
105 | ],
106 | "typeof-compare": true,
107 | "unified-signatures": true,
108 | "variable-name": false,
109 | "whitespace": [
110 | true,
111 | "check-branch",
112 | "check-decl",
113 | "check-operator",
114 | "check-separator",
115 | "check-type"
116 | ],
117 | "directive-selector": [
118 | true,
119 | "attribute",
120 | "app",
121 | "camelCase"
122 | ],
123 | "component-selector": [
124 | true,
125 | "element",
126 | "app",
127 | "kebab-case"
128 | ],
129 | "use-input-property-decorator": true,
130 | "use-output-property-decorator": true,
131 | "use-host-property-decorator": true,
132 | "no-input-rename": true,
133 | "no-output-rename": true,
134 | "use-life-cycle-interface": true,
135 | "use-pipe-transform-interface": true,
136 | "component-class-suffix": true,
137 | "directive-class-suffix": true,
138 | "invoke-injectable": true
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/sass/utils/_flex.scss:
--------------------------------------------------------------------------------
1 | // Flexbox display
2 | @mixin flexbox() {
3 | display: -webkit-box;
4 | display: -moz-box;
5 | display: -ms-flexbox;
6 | display: -webkit-flex;
7 | display: flex;
8 | }
9 |
10 | // The 'flex' shorthand
11 | // - applies to: flex items
12 | // , initial, auto, or none
13 | @mixin flex($values) {
14 | -webkit-box-flex: $values;
15 | -moz-box-flex: $values;
16 | -webkit-flex: $values;
17 | -ms-flex: $values;
18 | flex: $values;
19 | }
20 |
21 | // Flex Flow Direction
22 | // - applies to: flex containers
23 | // row | row-reverse | column | column-reverse
24 | @mixin flex-direction($direction) {
25 | -webkit-flex-direction: $direction;
26 | -moz-flex-direction: $direction;
27 | -ms-flex-direction: $direction;
28 | flex-direction: $direction;
29 | }
30 |
31 | // Flex Line Wrapping
32 | // - applies to: flex containers
33 | // nowrap | wrap | wrap-reverse
34 | @mixin flex-wrap($wrap) {
35 | -webkit-flex-wrap: $wrap;
36 | -moz-flex-wrap: $wrap;
37 | -ms-flex-wrap: $wrap;
38 | flex-wrap: $wrap;
39 | }
40 |
41 | // Flex Direction and Wrap
42 | // - applies to: flex containers
43 | // ||
44 | @mixin flex-flow($flow) {
45 | -webkit-flex-flow: $flow;
46 | -moz-flex-flow: $flow;
47 | -ms-flex-flow: $flow;
48 | flex-flow: $flow;
49 | }
50 |
51 | // Display Order
52 | // - applies to: flex items
53 | //
54 | @mixin order($val) {
55 | -webkit-box-ordinal-group: $val;
56 | -moz-box-ordinal-group: $val;
57 | -ms-flex-order: $val;
58 | -webkit-order: $val;
59 | order: $val;
60 | }
61 |
62 | // Flex grow factor
63 | // - applies to: flex items
64 | //
65 | @mixin flex-grow($grow) {
66 | -webkit-flex-grow: $grow;
67 | -moz-flex-grow: $grow;
68 | -ms-flex-grow: $grow;
69 | flex-grow: $grow;
70 | }
71 |
72 | // Flex shrink
73 | // - applies to: flex item shrink factor
74 | //
75 | @mixin flex-shrink($shrink) {
76 | -webkit-flex-shrink: $shrink;
77 | -moz-flex-shrink: $shrink;
78 | -ms-flex-shrink: $shrink;
79 | flex-shrink: $shrink;
80 | }
81 |
82 | // Flex basis
83 | // - the initial main size of the flex item
84 | // - applies to: flex itemsnitial main size of the flex item
85 | //
86 | @mixin flex-basis($width) {
87 | -webkit-flex-basis: $width;
88 | -moz-flex-basis: $width;
89 | -ms-flex-basis: $width;
90 | flex-basis: $width;
91 | }
92 |
93 | // Axis Alignment
94 | // - applies to: flex containers
95 | // flex-start | flex-end | center | space-between | space-around
96 | @mixin justify-content($justify) {
97 | -webkit-justify-content: $justify;
98 | -moz-justify-content: $justify;
99 | -ms-justify-content: $justify;
100 | justify-content: $justify;
101 | -ms-flex-pack: $justify;
102 | }
103 |
104 | // Packing Flex Lines
105 | // - applies to: multi-line flex containers
106 | // flex-start | flex-end | center | space-between | space-around | stretch
107 | @mixin align-content($align) {
108 | -webkit-align-content: $align;
109 | -moz-align-content: $align;
110 | -ms-align-content: $align;
111 | align-content: $align;
112 | }
113 |
114 | // Cross-axis Alignment
115 | // - applies to: flex containers
116 | // flex-start | flex-end | center | baseline | stretch
117 | @mixin align-items($align) {
118 | -webkit-align-items: $align;
119 | -moz-align-items: $align;
120 | -ms-align-items: $align;
121 | align-items: $align;
122 | }
123 |
124 | // Cross-axis Alignment
125 | // - applies to: flex items
126 | // auto | flex-start | flex-end | center | baseline | stretch
127 | @mixin align-self($align) {
128 | -webkit-align-self: $align;
129 | -moz-align-self: $align;
130 | -ms-align-self: $align;
131 | align-self: $align;
132 | }
133 |
--------------------------------------------------------------------------------
/src/sass/partials/_home.scss:
--------------------------------------------------------------------------------
1 | @import '../base/_variables.scss';
2 | @import '../utils/_flex';
3 |
4 | $info-box-height: 90px;
5 | $widget-action-button-size: 22px;
6 |
7 | .home{
8 |
9 | .mat-card{
10 |
11 | .mat-card-title{
12 | .widget-header{
13 | @include flexbox();
14 | align-items: center;
15 | }
16 | }
17 | }
18 |
19 | .info-card{
20 |
21 | background-color: #607d8b !important;
22 | color: #ffffff;
23 | padding: 0;
24 |
25 | &.info-card-link{
26 | cursor: pointer;
27 | }
28 |
29 | .info-card-icon{
30 | color: #607d8b;
31 | background-color: #455a64;
32 | border-radius: 2px 0 0 2px;
33 |
34 | display: block;
35 | float: left;
36 | height: $info-box-height;
37 | width: $info-box-height;
38 | text-align: center;
39 | line-height: $info-box-height;
40 |
41 | .mat-icon{
42 | height: $info-box-height;
43 | width: $info-box-height;
44 | font-size: 48px;
45 | line-height: $info-box-height;
46 | }
47 | }
48 |
49 | .info-card-content{
50 | padding: 12px 10px 10px;
51 | margin-left: 90px;
52 | color: currentColor!important;
53 | text-transform: uppercase;
54 | font-weight: 400;
55 |
56 | overflow: hidden;
57 | white-space: nowrap;
58 | text-overflow: ellipsis;
59 |
60 | h3 {
61 | font-family: $heading-font-family;
62 | font-weight: 300;
63 | font-size: 32px;
64 | margin: 0 0 12px 0;
65 | }
66 | }
67 |
68 | &.info-card-green{
69 | background-color: #4caf50 !important;
70 |
71 | .info-card-icon{
72 | color: #4caf50;
73 | background-color: #43A047;
74 | }
75 | }
76 |
77 | &.info-card-red{
78 | background-color: #e53935 !important;
79 |
80 | .info-card-icon{
81 | color: #E53935;
82 | background-color: #d32f2f;
83 | }
84 | }
85 |
86 | &.info-card-blue{
87 | background-color: #039be5 !important;
88 |
89 | .info-card-icon{
90 | color: #29B6F6;
91 | background-color: #0288d1;
92 | }
93 | }
94 | }
95 |
96 | .chart{
97 | padding: 16px;
98 |
99 | .mat-card-title {
100 | font-size: 18px;
101 | }
102 | }
103 |
104 | canvas {
105 | width: 100% !important;
106 | }
107 |
108 | .first-chart{
109 | canvas {
110 | min-height: 150px;
111 | max-height: 150px;
112 | }
113 | }
114 |
115 | .horizontal-bar{
116 | canvas {
117 | min-height: 400px;
118 | max-height: 400px;
119 | }
120 | }
121 |
122 | .pie-charts{
123 | canvas {
124 | min-height: 160px;
125 | max-height: 160px;
126 | }
127 | }
128 |
129 | .progress-metrics{
130 | h3{
131 | font-weight: 400;
132 | font-size: 18px;
133 | }
134 |
135 | .progress-wrapper {
136 | position: relative;
137 | margin: 20px auto;
138 | font-size: 24px;
139 | max-width: 160px;
140 |
141 | .progress-label {
142 | font-family: $heading-font-family;
143 | position: absolute;
144 | top: 50%;
145 | left: 50%;
146 | transform: translate(-50%,-50%);
147 | -webkit-transform: translate(-50%,-50%);
148 | -moz-transform: translate(-50%,-50%);
149 | color: currentColor;
150 | opacity: 0.3;
151 | font-size: 32px;
152 | }
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/app/components/users/list/user-list.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | cached
4 |
5 |
6 | person_add
7 |
8 |
9 | delete
10 |
11 |
12 |
13 |
14 |
49 |
50 |
51 |
52 |
53 |
54 | Search: {{email}}
55 | cancel
56 |
57 | Start date: {{startDate | date: 'dd/MM/yyyy'}}
58 | cancel
59 |
60 | End date: {{endDate | date: 'dd/MM/yyyy'}}
61 | cancel
62 |
63 | State: {{state}}
64 | cancel
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | ID
76 | Name
77 | Username
78 | Email
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | {{user.id}}
87 |
88 | {{user.name}}
89 |
90 | {{user.username}}
91 | {{user.email}}
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | add
101 |
102 |
--------------------------------------------------------------------------------
/src/sass/base/_layout.scss:
--------------------------------------------------------------------------------
1 | @import '../utils/flex';
2 | @import '_variables';
3 |
4 | body{
5 | @media(min-width: 768px){
6 | &.full-width{
7 | .mat-sidenav-container{
8 | .mat-toolbar{
9 | min-width: 100%;
10 | max-width: 100%!important;
11 |
12 | // Set logo content and size on full width toobar
13 | .logo{
14 | margin-left: 10px;
15 | margin-right: 10px;
16 | margin-top: 2px;
17 | width: 125px;
18 | height: 24px;
19 |
20 | background-image: url('/assets/logos.png');
21 | background-repeat: no-repeat;
22 | background-position-y: -50px;
23 | }
24 | }
25 |
26 | .mat-sidenav{
27 | margin-top: 64px;
28 | z-index: 0;
29 |
30 | .logo{
31 | // Hide sidenav logo on full width toolbar
32 | display: none;
33 | }
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
40 | .mat-sidenav-container {
41 |
42 | .mat-card-title{
43 | font-family: $heading-font-family;
44 | font-weight: 300;
45 | }
46 |
47 | @media(min-width: 768px) {
48 |
49 | .mat-toolbar {
50 | // Use the same transition sidenav is using, so it animates smoothly
51 | transition-property: max-width;
52 | transition-duration: .4s;
53 | transition-timing-function: cubic-bezier(.25,.8,.25,1);
54 | // Set width based on sidenav width
55 | max-width: calc(100% - #{$sidenav-width});
56 | }
57 |
58 | &.sidenav-closed {
59 | .mat-toolbar {
60 | max-width: 100%;
61 | }
62 | }
63 | }
64 |
65 | .mat-toolbar {
66 | position: fixed;
67 | top: 0;
68 | right: 0;
69 | z-index: 10;
70 |
71 | text-rendering: optimizeLegibility;
72 | -webkit-font-smoothing: antialiased;
73 |
74 | .app-title{
75 | margin-left: 10px;
76 | font-size: 20px;
77 | font-weight: 400;
78 | }
79 | }
80 |
81 | main {
82 | padding: 80px 16px 16px;
83 |
84 | .mat-tab-body{
85 | margin-top: 10px;
86 | }
87 | }
88 | }
89 |
90 | // Force dark backdrop for all themes
91 | .mat-drawer-backdrop{
92 | &.mat-drawer-shown {
93 | background-color: rgba(0, 0, 0, 0.6)!important;
94 | }
95 | }
96 |
97 | .flex-container{
98 |
99 | @include flexbox();
100 | align-items: stretch;
101 |
102 | @media(min-width: 768px){
103 | flex-direction: row;
104 |
105 | .col {
106 | @include flex(1);
107 | margin: 0 0 0 1em;
108 |
109 | &:first-child{
110 | margin: 0;
111 | }
112 |
113 | &.col-x2{
114 | @include flex-grow(2);
115 | }
116 |
117 | &.col-x3{
118 | @include flex-grow(3);
119 | }
120 |
121 | &.col-x4{
122 | @include flex-grow(4);
123 | }
124 | }
125 | }
126 |
127 | @media(max-width: 767px){
128 | flex-direction: column;
129 |
130 | .col {
131 | flex: 1;
132 | margin: 1em 0 0 0;
133 |
134 | &:first-child{
135 | margin: 0;
136 | }
137 | }
138 | }
139 | }
140 |
141 | //////////////////////////////////////////////////////////////////////////////
142 | // Layout classes
143 | //////////////////////////////////////////////////////////////////////////////
144 |
145 | section {
146 | margin-bottom: 20px;
147 | }
148 |
149 | [fill], .fill {
150 | flex: 1 1 auto;
151 | }
152 |
153 | [flex] {
154 | -ms-flex: 1;
155 | flex: 1;
156 | box-sizing: border-box;
157 | }
158 |
159 | [layout=column], [layout=row], [layout] {
160 | box-sizing: border-box;
161 | display: -ms-flexbox;
162 | display: flex;
163 | }
164 |
165 | [layout=row] {
166 | -ms-flex-direction: row;
167 | flex-direction: row;
168 | }
169 |
170 | .text-center {
171 | text-align: center !important;
172 | }
173 |
174 | [center], .center{
175 | margin: 0 auto;
176 | }
177 |
178 | .fixed-bottom-right {
179 | position: fixed !important;
180 | @media(min-width:768px){
181 | bottom: 24px;
182 | right: 32px;
183 | }
184 | @media(max-width:767px){
185 | bottom: 20px;
186 | right: 30px;
187 | }
188 | }
189 |
190 | form{
191 | &.full-width{
192 | width: 100%;
193 | .mat-form-field{
194 | &.full-width{
195 | width: 100%;
196 | }
197 | }
198 | }
199 | }
200 |
201 | .float-right{
202 | float: right;
203 | &::after{
204 | clear: both;
205 | }
206 | }
207 |
208 | .clearfix{
209 | clear: both;
210 | }
211 |
212 | .hide-md{
213 | @media(max-width: 767px){
214 | display: none!important;
215 | }
216 | }
217 |
218 | .hide-lg{
219 | @media(min-width: 768px){
220 | display: none!important;
221 | }
222 | }
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
14 |
16 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule, Title } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 | import { RouterModule, Routes } from '@angular/router';
4 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
5 | import { FormsModule } from '@angular/forms';
6 |
7 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
8 |
9 | import {
10 | MatButtonModule,
11 | MatButtonToggleModule,
12 | MatTooltipModule,
13 | MatCheckboxModule,
14 | MatToolbarModule,
15 | MatMenuModule,
16 | MatSidenavModule,
17 | MatFormFieldModule,
18 | MatInputModule,
19 | MatIconModule,
20 | MatSlideToggleModule,
21 | MatDatepickerModule,
22 | MatNativeDateModule,
23 | MatSelectModule,
24 | MatRadioModule,
25 | MatGridListModule,
26 | MatProgressBarModule,
27 | MatListModule,
28 | MatCardModule,
29 | MatDialogModule,
30 | MatTabsModule,
31 | MatChipsModule,
32 | MatSnackBarModule } from '@angular/material';
33 |
34 | import { ChartsModule } from 'ng2-charts';
35 | import { RoundProgressModule } from 'angular-svg-round-progressbar';
36 | import { NgProgressModule, NgProgressInterceptor } from 'ngx-progressbar';
37 |
38 | import { HttpService } from './services';
39 |
40 | import { NgInitDirective } from './directives/ng-init.directive';
41 |
42 | import { NavBarComponent } from './components/shared/navbar/navbar.component';
43 | import { ToolbarComponent } from './components/shared/toolbar/toolbar.component';
44 | import { AppComponent } from './components/app/app.component';
45 |
46 | import { HomeComponent } from './components/home/home.component';
47 | import { MainLayoutComponent } from './layouts/main-layout/main-layout.component';
48 | import { LoginLayoutComponent } from './layouts/login-layout/login-layout.component';
49 | import { LoginComponent } from './components/login/login.component';
50 | import { UserListComponent } from './components/users/list/user-list.component';
51 | import { UserDetailsComponent } from './components/users/details/user-details.component';
52 | import { CreateEditUserComponent } from './components/users/shared/create-edit-user/create-edit-user.component';
53 | import { SettingsComponent } from './components/settings/settings.component';
54 | import { ProfileComponent } from './components/profile/profile.component';
55 | import { LayoutComponent } from './components/layout/base/layout.component';
56 | import { AlertsLayoutComponent } from './components/layout/alerts-layout/alerts-layout.component';
57 | import { ButtonsLayoutComponent } from './components/layout/buttons-layout/buttons-layout.component';
58 | import { TypographyComponent } from './components/layout/typography/typography.component';
59 | import { ConfirmDialogComponent } from './components/dialogs/confirm-dialog/confirm-dialog.component';
60 |
61 | const appRoutes: Routes = [
62 | {
63 | path: '',
64 | component: MainLayoutComponent,
65 | // canActivate: [AuthGuard],
66 | children: [
67 | { path: '', pathMatch: 'full', redirectTo: '/home' },
68 | { path: 'home', component: HomeComponent, data: {title: 'Dashboard'} },
69 | { path: 'users', component: UserListComponent, data: {title: 'Users'}},
70 | { path: 'users/new', component: CreateEditUserComponent, data: {title: 'New user'} },
71 | { path: 'users/edit/:id', component: CreateEditUserComponent, data: {title: 'Edit user'} },
72 | { path: 'users/details/:id', component: UserDetailsComponent, data: {title: 'User details'} },
73 | { path: 'settings', component: SettingsComponent, data: {title: 'Settings'} },
74 | { path: 'profile', component: ProfileComponent, data: {title: 'Profile'} },
75 | {
76 | path: 'layout', data: {title: 'Layout'},
77 | children:[
78 | { path: 'base', component: LayoutComponent, data: {title: 'Base layout'} },
79 | { path: 'alerts', component: AlertsLayoutComponent, data: {title: 'Alerts & Callouts'} },
80 | { path: 'buttons', component: ButtonsLayoutComponent, data: {title: 'Buttons'} },
81 | { path: 'typography', component: TypographyComponent, data: {title: 'Typography'} }
82 | ]
83 | }
84 | ]
85 | },
86 | {
87 | path: '',
88 | component: LoginLayoutComponent,
89 | children: [
90 | {
91 | path: 'login',
92 | component: LoginComponent
93 | }
94 | ]
95 | },
96 | { path: '**', redirectTo: '/home' }
97 |
98 | ];
99 |
100 | @NgModule({
101 | declarations: [
102 | AppComponent,
103 | HomeComponent,
104 | MainLayoutComponent,
105 | NavBarComponent,
106 | LoginLayoutComponent,
107 | LoginComponent,
108 | UserListComponent,
109 | UserListComponent,
110 | ToolbarComponent,
111 | UserDetailsComponent,
112 | SettingsComponent,
113 | ProfileComponent,
114 | NgInitDirective,
115 | LayoutComponent,
116 | CreateEditUserComponent,
117 | AlertsLayoutComponent,
118 | ButtonsLayoutComponent,
119 | TypographyComponent,
120 | ConfirmDialogComponent
121 | ],
122 | imports: [
123 | RouterModule.forRoot(appRoutes),
124 | BrowserModule,
125 | HttpClientModule,
126 | NgProgressModule,
127 | FormsModule,
128 | BrowserAnimationsModule,
129 | MatButtonModule,
130 | MatButtonToggleModule,
131 | MatTooltipModule,
132 | MatCheckboxModule,
133 | MatToolbarModule,
134 | MatMenuModule,
135 | MatSidenavModule,
136 | MatFormFieldModule,
137 | MatInputModule,
138 | MatIconModule,
139 | MatSlideToggleModule,
140 | MatCardModule,
141 | MatDialogModule,
142 | MatDatepickerModule,
143 | MatNativeDateModule,
144 | MatSelectModule,
145 | MatRadioModule,
146 | MatListModule,
147 | MatGridListModule,
148 | MatSnackBarModule,
149 | MatProgressBarModule,
150 | MatTabsModule,
151 | MatChipsModule,
152 |
153 | ChartsModule,
154 | RoundProgressModule
155 | ],
156 | providers: [
157 | HttpService,
158 | Title,
159 | {
160 | provide: HTTP_INTERCEPTORS,
161 | useClass: NgProgressInterceptor,
162 | multi: true
163 | }
164 | ],
165 | bootstrap: [AppComponent],
166 | entryComponents: [ConfirmDialogComponent]
167 | })
168 | export class AppModule { }
169 |
--------------------------------------------------------------------------------
/src/app/components/home/home.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | supervisor_account
8 |
9 |
10 |
2345
11 | Downloads
12 |
13 |
14 |
15 |
16 |
17 | verified_user
18 |
19 |
20 |
456
21 | Verified users
22 |
23 |
24 |
25 |
26 |
27 | done_all
28 |
29 |
30 |
123
31 | Comments
32 |
33 |
34 |
35 |
36 |
37 | person_pin
38 |
39 |
40 |
56
41 | Registered
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
81 |
82 |
83 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
100 |
101 |
Metric 2
102 |
107 |
108 |
109 |
Metric 3
110 |
115 |
116 |
117 |
Metric 4
118 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | Horizontal Bar Example
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | Pie Chart Example
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | Available on Github
162 |
163 |
164 |
166 |
167 |
168 |
169 |
170 |
175 |
176 |
177 | cached
178 |
179 |
--------------------------------------------------------------------------------