mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-12-27 20:58:48 +01:00
commit
3e3bf8cb2b
90 changed files with 1553 additions and 614 deletions
40
CHANGELOG.md
Normal file
40
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<a name="0.3.0"></a>
|
||||
# 0.3.0 (2016-06-29)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Sidebar menu angle fixed
|
||||
* Sidebar menu selected item fixed
|
||||
|
||||
### Features
|
||||
|
||||
* Angular updated to rc.3
|
||||
* Dependencies updated accordingly
|
||||
|
||||
### How to update
|
||||
|
||||
* Remove `node_modules` and `typings` folders
|
||||
* run `npm install`
|
||||
|
||||
<a name="0.2.1"></a>
|
||||
# 0.2.1 (2016-06-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Multiple bugfixes
|
||||
|
||||
### Features
|
||||
|
||||
* Angular updated to rc.2
|
||||
* Dependencies updated accordingly
|
||||
* Login page component [Demo](http://akveo.com/ng2-admin/#/login)
|
||||
* Sign up page component [Demo](http://akveo.com/ng2-admin/#/register)
|
||||
|
||||
### BREAKING CHANGES
|
||||
* `$` renamed to `jQuery` because of name resolution conflicts
|
||||
|
||||
### How to update
|
||||
|
||||
* Remove `node_modules` and `typings` folders
|
||||
* run `npm install`
|
||||
37
Dockerfile
37
Dockerfile
|
|
@ -1,33 +1,16 @@
|
|||
FROM node:latest
|
||||
|
||||
COPY . /var/www
|
||||
WORKDIR /var/www
|
||||
|
||||
#Install rimraf globally, so root can perform delete operation
|
||||
RUN npm install --global rimraf
|
||||
RUN npm run clean
|
||||
|
||||
#install bower and dependcies with --allow-root flag
|
||||
RUN npm install --global bower
|
||||
RUN bower install --allow-root
|
||||
|
||||
#install right version of typings
|
||||
RUN npm install --global typings@0.8.1
|
||||
RUN npm run typings -- install
|
||||
|
||||
#install all
|
||||
RUN npm install --global webpack webpack-dev-server typescript
|
||||
RUN npm install
|
||||
|
||||
#build
|
||||
RUN npm run prebuild:prod
|
||||
RUN npm run build:prod
|
||||
RUN git clone https://github.com/akveo/ng2-admin.git /var/www \
|
||||
&& cd /var/www \
|
||||
&& npm install --global rimraf \
|
||||
&& npm run clean \
|
||||
&& npm install --global bower typings webpack webpack-dev-server typescript \
|
||||
&& bower install --allow-root \
|
||||
&& npm run typings -- install \
|
||||
&& npm install \
|
||||
&& npm run prebuild:prod && npm run build:prod
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
WORKDIR /var/www
|
||||
ENTRYPOINT ["npm", "run", "server:prod"]
|
||||
|
||||
#to build image - docker quick terminal, navigate to folder, docker build -t [your docker hub account]/ng2-admin .
|
||||
#to run docker run -p 8080:8080 [your docker hub account]/ng2-admin
|
||||
#or you can simply pull from my registry - docker pull dimkk/ng2-admin, docker run -p8080:8080 dimkk/ng2-admin
|
||||
#now you can navigate to docker-machine (assuming you are on windows or osx) in browser - 192.168.99.100:8080
|
||||
1
_VERSION
Normal file
1
_VERSION
Normal file
|
|
@ -0,0 +1 @@
|
|||
_VERSION=0.3.0
|
||||
9
build.sh
Executable file
9
build.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
_tag=$1
|
||||
|
||||
if [ -z "${_tag}" ]; then
|
||||
source _VERSION
|
||||
_tag=${_VERSION}
|
||||
fi
|
||||
|
||||
docker build --tag "ng2-admin:${_tag}" --no-cache=true .
|
||||
|
|
@ -87,7 +87,9 @@ module.exports = {
|
|||
loader: 'source-map-loader',
|
||||
exclude: [
|
||||
// these packages have problems with their sourcemaps
|
||||
helpers.root('node_modules/rxjs')
|
||||
helpers.root('node_modules/rxjs'),
|
||||
helpers.root('node_modules/ng2-bootstrap'),
|
||||
helpers.root('node_modules/ng2-branchy')
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ module.exports = webpackMerge(commonConfig, {
|
|||
*
|
||||
* See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
|
||||
*/
|
||||
sourceMapFilename: '[name].map',
|
||||
sourceMapFilename: '[file].map',
|
||||
|
||||
/** The filename of non-entry chunks as relative path
|
||||
* inside the output.path directory.
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ module.exports = webpackMerge(commonConfig, {
|
|||
*
|
||||
* See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
|
||||
*/
|
||||
sourceMapFilename: '[name].[chunkhash].bundle.map',
|
||||
sourceMapFilename: '[file].map',
|
||||
|
||||
/**
|
||||
* The filename of non-entry chunks as relative path
|
||||
|
|
@ -154,10 +154,7 @@ module.exports = webpackMerge(commonConfig, {
|
|||
|
||||
beautify: false, //prod
|
||||
|
||||
mangle: {
|
||||
screw_ie8 : true,
|
||||
keep_fnames: true
|
||||
}, //prod
|
||||
mangle: false, //prod
|
||||
|
||||
compress: {
|
||||
screw_ie8: true
|
||||
|
|
|
|||
44
package.json
44
package.json
|
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
"name": "ng2-admin",
|
||||
"version": "0.0.1",
|
||||
"version": "0.3.0",
|
||||
"description": "Angular 2 and Bootstrap 4 Admin Template.",
|
||||
"author": "akveo",
|
||||
"homepage": "http://akveo.github.io/ng2-admin/",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/common": "2.0.0-rc.1",
|
||||
"@angular/compiler": "2.0.0-rc.1",
|
||||
"@angular/core": "2.0.0-rc.1",
|
||||
"@angular/http": "2.0.0-rc.1",
|
||||
"@angular/platform-browser": "2.0.0-rc.1",
|
||||
"@angular/platform-browser-dynamic": "2.0.0-rc.1",
|
||||
"@angular/platform-server": "2.0.0-rc.1",
|
||||
"@angular/router": "2.0.0-rc.1",
|
||||
"@angular/router-deprecated": "2.0.0-rc.1",
|
||||
"@angular/common": "2.0.0-rc.4",
|
||||
"@angular/compiler": "2.0.0-rc.4",
|
||||
"@angular/core": "2.0.0-rc.4",
|
||||
"@angular/http": "2.0.0-rc.4",
|
||||
"@angular/platform-browser": "2.0.0-rc.4",
|
||||
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
|
||||
"@angular/platform-server": "2.0.0-rc.4",
|
||||
"@angular/router": "3.0.0-beta.2",
|
||||
"@angular/forms":"0.2.0",
|
||||
"amcharts3": "github:amcharts/amcharts3",
|
||||
"ammap3": "github:amcharts/ammap3",
|
||||
"animate.css": "^3.5.1",
|
||||
|
|
@ -22,7 +22,8 @@
|
|||
"bootstrap-loader": "^1.0.8",
|
||||
"chart.js": "^1.1.1",
|
||||
"chartist": "^0.9.7",
|
||||
"core-js": "^2.2.2",
|
||||
"ckeditor": "^4.5.9",
|
||||
"core-js": "^2.4.0",
|
||||
"easy-pie-chart": "^2.1.7",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"font-awesome": "^4.6.1",
|
||||
|
|
@ -34,18 +35,21 @@
|
|||
"leaflet": "^0.7.7",
|
||||
"leaflet-map": "^0.2.1",
|
||||
"lodash": "^4.12.0",
|
||||
"ng2-bootstrap": "^1.0.16",
|
||||
"ng2-bootstrap": "^1.0.20",
|
||||
"ng2-ckeditor": "^1.0.4",
|
||||
"ng2-branchy": "^0.0.2-5",
|
||||
"ng2-uploader": "^0.5.2",
|
||||
"normalize.css": "^4.1.1",
|
||||
"rxjs": "5.0.0-beta.6",
|
||||
"tether": "^1.2.4",
|
||||
"zone.js": "~0.6.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular2-hmr": "~0.6.0",
|
||||
"awesome-typescript-loader": "~0.17.0",
|
||||
"angular2-hmr": "~0.7.0",
|
||||
"awesome-typescript-loader": "1.1.1",
|
||||
"codelyzer": "~0.0.19",
|
||||
"compression-webpack-plugin": "^0.3.1",
|
||||
"copy-webpack-plugin": "^2.1.3",
|
||||
"copy-webpack-plugin": "^3.0.1",
|
||||
"css-loader": "^0.23.1",
|
||||
"es6-promise": "^3.1.2",
|
||||
"es6-promise-loader": "^1.0.1",
|
||||
|
|
@ -68,17 +72,17 @@
|
|||
"source-map-loader": "^0.1.5",
|
||||
"style-loader": "^0.13.1",
|
||||
"ts-helpers": "1.1.1",
|
||||
"ts-node": "^0.7.1",
|
||||
"ts-node": "^0.9.0",
|
||||
"tslint": "^3.7.1",
|
||||
"tslint-loader": "^2.1.3",
|
||||
"typedoc": "^0.3.12",
|
||||
"typedoc": "^0.4.4",
|
||||
"typescript": "~1.8.9",
|
||||
"typings": "^0.8.1",
|
||||
"typings": "^1.0.5",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.12.14",
|
||||
"webpack": "^1.13.1",
|
||||
"webpack-dev-server": "^1.14.1",
|
||||
"webpack-md5-hash": "^0.0.5",
|
||||
"webpack-merge": "^0.12.0"
|
||||
"webpack-merge": "^0.14.0"
|
||||
},
|
||||
"scripts": {
|
||||
"rimraf": "rimraf",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
import './app.loader.ts';
|
||||
|
||||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
|
||||
import {Pages} from './pages';
|
||||
import {AppState} from './app.state';
|
||||
import {BaThemeConfigProvider, BaThemeConfig} from './theme';
|
||||
import {BaThemeRun} from './theme/directives';
|
||||
import {BaImageLoaderService, BaThemePreloader, BaThemeSpinner} from './theme/services';
|
||||
|
||||
import {layoutPaths} from './theme/theme.constants';
|
||||
import {Component, ViewEncapsulation} from "@angular/core";
|
||||
import {AppState} from "./app.state";
|
||||
import {BaThemeConfigProvider, BaThemeConfig} from "./theme";
|
||||
import {BaThemeRun} from "./theme/directives";
|
||||
import {BaImageLoaderService, BaThemePreloader, BaThemeSpinner} from "./theme/services";
|
||||
import {layoutPaths} from "./theme/theme.constants";
|
||||
|
||||
/*
|
||||
* App Component
|
||||
|
|
@ -29,21 +24,6 @@ import {layoutPaths} from './theme/theme.constants';
|
|||
</main>
|
||||
`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
path: '/pages/...',
|
||||
name: 'Pages',
|
||||
component: Pages,
|
||||
useAsDefault: true
|
||||
},
|
||||
// handle any non-registered route
|
||||
// and simply redirects back to dashboard page
|
||||
// you can specify any customer 404 page while it's not built in ito ng2-admin
|
||||
{
|
||||
path: '/**',
|
||||
redirectTo: ['Pages']
|
||||
}
|
||||
])
|
||||
export class App {
|
||||
|
||||
isMenuCollapsed:boolean = false;
|
||||
|
|
|
|||
|
|
@ -1,144 +0,0 @@
|
|||
export const menuItems = [
|
||||
{
|
||||
title: 'Dashboard',
|
||||
component: 'Dashboard',
|
||||
icon: 'ion-android-home',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 0
|
||||
},
|
||||
{
|
||||
title: 'Charts',
|
||||
component: 'Charts',
|
||||
icon: 'ion-stats-bars',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 200,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Chartist.Js',
|
||||
component: 'ChartistJs',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'UI Features',
|
||||
component: 'Ui',
|
||||
icon: 'ion-android-laptop',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 300,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Typography',
|
||||
component: 'Typography',
|
||||
},
|
||||
{
|
||||
title: 'Buttons',
|
||||
component: 'Buttons',
|
||||
},
|
||||
{
|
||||
title: 'Icons',
|
||||
component: 'Icons',
|
||||
},
|
||||
{
|
||||
title: 'Grid',
|
||||
component: 'Grid',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Form Elements',
|
||||
component: 'Forms',
|
||||
icon: 'ion-compose',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 400,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Form Inputs',
|
||||
component: 'Inputs',
|
||||
},
|
||||
{
|
||||
title: 'Form Layouts',
|
||||
component: 'Layouts',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Tables',
|
||||
component: 'Tables',
|
||||
icon: 'ion-grid',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 500,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Basic Tables',
|
||||
component: 'BasicTables',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Maps',
|
||||
component: 'Maps',
|
||||
icon: 'ion-ios-location-outline',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 600,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Google Maps',
|
||||
component: 'GoogleMaps',
|
||||
},
|
||||
{
|
||||
title: 'Leaflet Maps',
|
||||
component: 'LeafletMaps',
|
||||
},
|
||||
{
|
||||
title: 'Bubble Maps',
|
||||
component: 'BubbleMaps',
|
||||
},
|
||||
{
|
||||
title: 'Line Maps',
|
||||
component: 'LineMaps',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Menu Level 1',
|
||||
icon: 'ion-ios-more',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 700,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Menu Level 1.1',
|
||||
url: '#',
|
||||
disabled: true,
|
||||
selected: false,
|
||||
expanded: false
|
||||
},
|
||||
{
|
||||
title: 'Menu Level 1.2',
|
||||
url: '#',
|
||||
subMenu: [{
|
||||
title: 'Menu Level 1.2.1',
|
||||
url: '#',
|
||||
disabled: true,
|
||||
selected: false,
|
||||
expanded: false
|
||||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'External Link',
|
||||
url: 'http://akveo.com',
|
||||
icon: 'ion-android-exit',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 800,
|
||||
target: '_blank'
|
||||
}
|
||||
];
|
||||
18
src/app/app.routes.ts
Normal file
18
src/app/app.routes.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import {provideRouter, RouterConfig} from '@angular/router';
|
||||
import {LoginRoutes} from "./pages/login/login.routes";
|
||||
import {PagesRoutes} from "./pages/pages.routes";
|
||||
import {RegisterRoutes} from "./pages/register/register.routes";
|
||||
|
||||
export const routes:RouterConfig = [
|
||||
...LoginRoutes,
|
||||
...RegisterRoutes,
|
||||
...PagesRoutes,
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: '/pages/dashboard'
|
||||
},
|
||||
];
|
||||
|
||||
export const APP_ROUTER_PROVIDERS = [
|
||||
provideRouter(routes)
|
||||
];
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
import {Component} from "@angular/core";
|
||||
|
||||
// import {ChartJs} from "./components/chartJs";
|
||||
import {ChartistJs} from "./components/chartistJs/chartistJs.component";
|
||||
|
||||
@Component({
|
||||
selector: 'maps',
|
||||
|
|
@ -11,19 +9,6 @@ import {ChartistJs} from "./components/chartistJs/chartistJs.component";
|
|||
styles: [],
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
name: 'ChartistJs',
|
||||
component: ChartistJs,
|
||||
path: '/chartist-js',
|
||||
useAsDefault: true,
|
||||
},
|
||||
// {
|
||||
// name: 'ChartJs',
|
||||
// component: ChartJs,
|
||||
// path: '/chart-js',
|
||||
// },
|
||||
])
|
||||
export class Charts {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
15
src/app/pages/components/components.component.ts
Normal file
15
src/app/pages/components/components.component.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'components',
|
||||
pipes: [],
|
||||
providers: [],
|
||||
styles: [],
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
export class Components {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
||||
1
src/app/pages/components/components.scss
Normal file
1
src/app/pages/components/components.scss
Normal file
|
|
@ -0,0 +1 @@
|
|||
@import '../../theme/sass/treeView';
|
||||
1
src/app/pages/components/components/treeView/index.ts
Normal file
1
src/app/pages/components/components/treeView/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './treeView.component';
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {BranchyComponent, TreeModel} from 'ng2-branchy';
|
||||
import {BaCard} from '../../../../theme/components/baCard';
|
||||
|
||||
@Component({
|
||||
selector: 'tree-view',
|
||||
directives: [BranchyComponent, BaCard],
|
||||
template: require('./treeView.html'),
|
||||
})
|
||||
|
||||
export class TreeView {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
private tree: TreeModel = {
|
||||
value: 'Programming languages by programming paradigm',
|
||||
children: [
|
||||
{
|
||||
value: 'Object-oriented programming',
|
||||
children: [
|
||||
{value: 'Java'},
|
||||
{value: 'C++'},
|
||||
{value: 'C#'},
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'Prototype-based programming',
|
||||
children: [
|
||||
{value: 'JavaScript'},
|
||||
{value: 'CoffeeScript'},
|
||||
{value: 'Lua'},
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<div class="col-md-6">
|
||||
<ba-card title="basic">
|
||||
<branchy id="tree-view" [tree]="tree"></branchy>
|
||||
</ba-card>
|
||||
</div>
|
||||
1
src/app/pages/components/index.ts
Normal file
1
src/app/pages/components/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './components.component';
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {BaFullCalendar} from '../../../theme/components';
|
||||
import {CalendarService} from "./calendar.service";
|
||||
import {CalendarService} from './calendar.service';
|
||||
|
||||
@Component({
|
||||
selector: 'calendar',
|
||||
|
|
@ -36,9 +36,9 @@ export class Calendar {
|
|||
start: start,
|
||||
end: end
|
||||
};
|
||||
$(this._calendar).fullCalendar('renderEvent', eventData, true);
|
||||
jQuery(this._calendar).fullCalendar('renderEvent', eventData, true);
|
||||
}
|
||||
$(this._calendar).fullCalendar('unselect');
|
||||
jQuery(this._calendar).fullCalendar('unselect');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ export class PieChart {
|
|||
|
||||
private _loadPieCharts() {
|
||||
|
||||
$('.chart').each(function () {
|
||||
let chart = $(this);
|
||||
jQuery('.chart').each(function () {
|
||||
let chart = jQuery(this);
|
||||
chart.easyPieChart({
|
||||
easing: 'easeOutBounce',
|
||||
onStep: function (from, to, percent) {
|
||||
$(this.el).find('.percent').text(Math.round(percent));
|
||||
jQuery(this.el).find('.percent').text(Math.round(percent));
|
||||
},
|
||||
barColor: $(this).attr('data-rel'),
|
||||
barColor: jQuery(this).attr('data-rel'),
|
||||
trackColor: 'rgba(0,0,0,0)',
|
||||
size: 84,
|
||||
scaleLength: 0,
|
||||
|
|
@ -54,8 +54,8 @@ export class PieChart {
|
|||
private _updatePieCharts() {
|
||||
let getRandomArbitrary = (min, max) => { return Math.random() * (max - min) + min };
|
||||
|
||||
$('.pie-charts .chart').each(function(index, chart) {
|
||||
$(chart).data('easyPieChart').update(getRandomArbitrary(55, 90));
|
||||
jQuery('.pie-charts .chart').each(function(index, chart) {
|
||||
jQuery(chart).data('easyPieChart').update(getRandomArbitrary(55, 90));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export class TrafficChart {
|
|||
}
|
||||
|
||||
private _loadDoughnutCharts() {
|
||||
let el = $('.chart-area').get(0);
|
||||
let el = jQuery('.chart-area').get(0);
|
||||
new Chart(el.getContext('2d')).Doughnut(this.doughnutData, {
|
||||
segmentShowStroke: false,
|
||||
percentageInnerCutout : 64,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {CKEditor} from 'ng2-ckeditor';
|
||||
import {BaCard} from '../../../../theme/components/baCard';
|
||||
|
||||
import './ckeditor.loader.ts';
|
||||
|
||||
@Component({
|
||||
selector: 'ckeditor',
|
||||
directives: [CKEditor, BaCard],
|
||||
template: require('./ckeditor.html')
|
||||
})
|
||||
|
||||
export class Ckeditor {
|
||||
public ckeditorContent:string = '<p>Hello CKEditor</p>';
|
||||
public config = {
|
||||
uiColor: '#F0F3F4',
|
||||
height: '600'
|
||||
};
|
||||
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
7
src/app/pages/editors/components/ckeditor/ckeditor.html
Normal file
7
src/app/pages/editors/components/ckeditor/ckeditor.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ba-card title="ckeditor" baCardClass="with-scroll">
|
||||
<ckeditor [(ngModel)]="ckeditorContent" [config]="config"></ckeditor>
|
||||
</ba-card>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
window['CKEDITOR_BASEPATH'] = '//cdn.ckeditor.com/4.5.9/standard/';
|
||||
require('ckeditor');
|
||||
1
src/app/pages/editors/components/ckeditor/index.ts
Normal file
1
src/app/pages/editors/components/ckeditor/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './ckeditor.component';
|
||||
10
src/app/pages/editors/editors.component.ts
Normal file
10
src/app/pages/editors/editors.component.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'editors',
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
export class Editors {
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
1
src/app/pages/editors/index.ts
Normal file
1
src/app/pages/editors/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './editors.component';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from './ratinginputs.component';
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { RatingComponent } from 'ng2-bootstrap/ng2-bootstrap';
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'rating-inputs',
|
||||
directives: [RatingComponent],
|
||||
template: require('./ratinginputs.html')
|
||||
})
|
||||
|
||||
export class Rating {
|
||||
private _rate1:number = 3;
|
||||
private _rate2:number = 4;
|
||||
|
||||
private _max1:number = 5;
|
||||
private _max2:number = 10;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<div class="col-md-4">
|
||||
<rating [(ngModel)]="_rate1" max="{{_max1}}" stateOn="ion-android-star" stateOff="ion-android-star-outline" class="rating"></rating>
|
||||
<span class="help-block">Rate: {{_rate1}}</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<rating [(ngModel)]="_rate2" max="{{_max2}}" stateOn="ion-ios-heart" stateOff="ion-ios-heart-outline" class="rating"></rating>
|
||||
<span class="help-block">Rate: {{_rate2}}</span>
|
||||
</div>
|
||||
|
|
@ -6,11 +6,13 @@ import {StandardInputs} from './components/standardInputs';
|
|||
import {ValidationInputs} from './components/validationInputs';
|
||||
import {GroupInputs} from './components/groupInputs';
|
||||
import {CheckboxInputs} from './components/checkboxInputs';
|
||||
import {Rating} from './components/ratinginputs';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'inputs',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
directives: [BaCard, StandardInputs, ValidationInputs, GroupInputs, CheckboxInputs],
|
||||
directives: [BaCard, StandardInputs, ValidationInputs, GroupInputs, CheckboxInputs, Rating],
|
||||
template: require('./inputs.html'),
|
||||
})
|
||||
export class Inputs {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
<ba-card title="Checkboxes & Radios" baCardClass="with-scroll">
|
||||
<checkbox-inputs></checkbox-inputs>
|
||||
</ba-card>
|
||||
|
||||
<ba-card title="Rating" baCardClass="with-scroll">
|
||||
<rating-inputs></rating-inputs>
|
||||
</ba-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,16 +7,25 @@ import {BlockForm} from './components/blockForm';
|
|||
import {HorizontalForm} from './components/horizontalForm';
|
||||
import {BasicForm} from './components/basicForm';
|
||||
import {WithoutLabelsForm} from './components/withoutLabelsForm';
|
||||
import {BaPictureUploader} from '../../../../theme/components';
|
||||
|
||||
@Component({
|
||||
selector: 'layouts',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
directives: [BaCard, InlineForm, BlockForm, HorizontalForm, BasicForm, WithoutLabelsForm],
|
||||
directives: [BaCard, InlineForm, BlockForm, HorizontalForm, BasicForm, WithoutLabelsForm, BaPictureUploader],
|
||||
styles: [],
|
||||
template: require('./layouts.html'),
|
||||
})
|
||||
export class Layouts {
|
||||
|
||||
public defaultPicture = 'assets/img/theme/no-photo.png';
|
||||
public profile:any = {
|
||||
picture: 'assets/img/app/profile/Nasta.png'
|
||||
};
|
||||
public uploaderOptions:any = {
|
||||
// url: 'http://website.com/upload'
|
||||
};
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,4 +35,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<ba-card title="Picture Uploader" baCardClass="with-scroll">
|
||||
<ba-picture-uploader [picture]="profile.picture" [defaultPicture]="defaultPicture" [uploaderOptions]="uploaderOptions"></ba-picture-uploader>
|
||||
</ba-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
|
||||
import {Inputs} from './components/inputs';
|
||||
import {Layouts} from './components/layouts';
|
||||
|
||||
@Component({
|
||||
selector: 'forms',
|
||||
|
|
@ -11,19 +7,6 @@ import {Layouts} from './components/layouts';
|
|||
styles: [],
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
name: 'Inputs',
|
||||
component: Inputs,
|
||||
path: '/inputs',
|
||||
useAsDefault: true
|
||||
},
|
||||
{
|
||||
name: 'Layouts',
|
||||
component: Layouts,
|
||||
path: '/layouts',
|
||||
}
|
||||
])
|
||||
export class Forms {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
1
src/app/pages/login/index.ts
Normal file
1
src/app/pages/login/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './login.component';
|
||||
35
src/app/pages/login/login.component.ts
Normal file
35
src/app/pages/login/login.component.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {FormGroup, AbstractControl, FormBuilder, Validators} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
directives: [],
|
||||
styles: [require('./login.scss')],
|
||||
template: require('./login.html'),
|
||||
})
|
||||
export class Login {
|
||||
|
||||
public form:FormGroup;
|
||||
public email:AbstractControl;
|
||||
public password:AbstractControl;
|
||||
public submitted:boolean = false;
|
||||
|
||||
constructor(fb:FormBuilder) {
|
||||
this.form = fb.group({
|
||||
'email': ['', Validators.compose([Validators.required, Validators.minLength(4)])],
|
||||
'password': ['', Validators.compose([Validators.required, Validators.minLength(4)])]
|
||||
});
|
||||
|
||||
this.email = this.form.controls['email'];
|
||||
this.password = this.form.controls['password'];
|
||||
}
|
||||
|
||||
public onSubmit(values:Object):void {
|
||||
this.submitted = true;
|
||||
if (this.form.valid) {
|
||||
// your code goes here
|
||||
// console.log(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/app/pages/login/login.html
Normal file
39
src/app/pages/login/login.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<div class="auth-main">
|
||||
<div class="auth-block">
|
||||
<h1>Sign in to ng2-admin</h1>
|
||||
<a [routerLink]="['/register']" class="auth-link">New to ng2-admin? Sign up!</a>
|
||||
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" class="form-horizontal">
|
||||
<div class="form-group row" [ngClass]="{'has-error': (!email.valid && email.touched), 'has-success': (email.valid && email.touched)}">
|
||||
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input [formControl]="email" type="email" class="form-control" id="inputEmail3" placeholder="Email">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row" [ngClass]="{'has-error': (!password.valid && password.touched), 'has-success': (password.valid && password.touched)}">
|
||||
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input [formControl]="password" type="password" class="form-control" id="inputPassword3" placeholder="Password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button [disabled]="!form.valid" type="submit" class="btn btn-default btn-auth">Sign in</button>
|
||||
<a [routerLink]="['Login']" class="forgot-pass">Forgot password?</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="auth-sep"><span><span>or Sign in with one click</span></span></div>
|
||||
|
||||
<div class="al-share-auth">
|
||||
<ul class="al-share clearfix">
|
||||
<li><i class="socicon socicon-facebook" title="Share on Facebook"></i></li>
|
||||
<li><i class="socicon socicon-twitter" title="Share on Twitter"></i></li>
|
||||
<li><i class="socicon socicon-google" title="Share on Google Plus"></i></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
10
src/app/pages/login/login.routes.ts
Normal file
10
src/app/pages/login/login.routes.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import {RouterConfig} from '@angular/router';
|
||||
import {Login} from './login.component';
|
||||
|
||||
//noinspection TypeScriptValidateTypes
|
||||
export const LoginRoutes: RouterConfig = [
|
||||
{
|
||||
path: 'login',
|
||||
component: Login
|
||||
}
|
||||
];
|
||||
1
src/app/pages/login/login.scss
Normal file
1
src/app/pages/login/login.scss
Normal file
|
|
@ -0,0 +1 @@
|
|||
@import '../../theme/sass/auth';
|
||||
|
|
@ -1,10 +1,4 @@
|
|||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
|
||||
import {GoogleMaps} from './components/googleMaps';
|
||||
import {LeafletMaps} from "./components/leafletMaps";
|
||||
import {BubbleMaps} from "./components/bubbleMaps";
|
||||
import {LineMaps} from "./components/lineMaps";
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'maps',
|
||||
|
|
@ -13,29 +7,6 @@ import {LineMaps} from "./components/lineMaps";
|
|||
styles: [],
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
name: 'GoogleMaps',
|
||||
component: GoogleMaps,
|
||||
path: '/google-maps',
|
||||
useAsDefault: true
|
||||
},
|
||||
{
|
||||
name: 'LeafletMaps',
|
||||
component: LeafletMaps,
|
||||
path: '/leaflet-maps',
|
||||
},
|
||||
{
|
||||
name: 'BubbleMaps',
|
||||
component: BubbleMaps,
|
||||
path: '/bubble-maps',
|
||||
},
|
||||
{
|
||||
name: 'LineMaps',
|
||||
component: LineMaps,
|
||||
path: '/line-maps',
|
||||
},
|
||||
])
|
||||
export class Maps {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
|
||||
import {BaPageTop, BaContentTop, BaSidebar, BaBackTop} from '../theme/components';
|
||||
|
||||
import {Dashboard} from './dashboard';
|
||||
import {Ui} from './ui';
|
||||
import {Maps} from './maps';
|
||||
import {Charts} from './charts';
|
||||
import {Forms} from './forms';
|
||||
import {Tables} from './tables';
|
||||
|
||||
@Component({
|
||||
selector: 'pages',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
|
@ -39,39 +30,6 @@ import {Tables} from './tables';
|
|||
<ba-back-top position="200"></ba-back-top>
|
||||
`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
name: 'Dashboard',
|
||||
component: Dashboard,
|
||||
path: '/dashboard',
|
||||
useAsDefault: true,
|
||||
},
|
||||
{
|
||||
name: 'Ui',
|
||||
component: Ui,
|
||||
path: '/ui/...',
|
||||
},
|
||||
{
|
||||
name: 'Maps',
|
||||
component: Maps,
|
||||
path: '/maps/...',
|
||||
},
|
||||
{
|
||||
name: 'Charts',
|
||||
component: Charts,
|
||||
path: '/charts/...',
|
||||
},
|
||||
{
|
||||
name: 'Forms',
|
||||
component: Forms,
|
||||
path: '/forms/...',
|
||||
},
|
||||
{
|
||||
name: 'Tables',
|
||||
component: Tables,
|
||||
path: '/tables/...',
|
||||
}
|
||||
])
|
||||
export class Pages {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
333
src/app/pages/pages.routes.ts
Normal file
333
src/app/pages/pages.routes.ts
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
import {RouterConfig} from '@angular/router';
|
||||
import {Dashboard} from './dashboard/dashboard.component';
|
||||
import {Charts} from './charts/charts.component';
|
||||
import {ChartistJs} from './charts/components/chartistJs/chartistJs.component';
|
||||
import {Pages} from './pages.component';
|
||||
import {Ui} from './ui/ui.component';
|
||||
import {Typography} from './ui/components/typography/typography.component';
|
||||
import {Buttons} from './ui/components/buttons/buttons.component';
|
||||
import {Icons} from './ui/components/incons/icons.component';
|
||||
import {Grid} from './ui/components/grid/grid.component';
|
||||
import {Forms} from './forms/forms.component';
|
||||
import {Inputs} from './forms/components/inputs/inputs.component';
|
||||
import {Layouts} from './forms/components/layouts/layouts.component';
|
||||
import {BasicTables} from './tables/components/basicTables/basicTables.component';
|
||||
import {Tables} from './tables/tables.component';
|
||||
import {Maps} from './maps/maps.component';
|
||||
import {GoogleMaps} from './maps/components/googleMaps/googleMaps.component';
|
||||
import {LeafletMaps} from './maps/components/leafletMaps/leafletMaps.component';
|
||||
import {BubbleMaps} from './maps/components/bubbleMaps/bubbleMaps.component';
|
||||
import {LineMaps} from './maps/components/lineMaps/lineMaps.component';
|
||||
import {Editors} from './editors/editors.component';
|
||||
import {Ckeditor} from './editors/components/ckeditor/ckeditor.component';
|
||||
import {Components} from './components/components.component';
|
||||
import {TreeView} from './components/components/treeView/treeView.component';
|
||||
|
||||
//noinspection TypeScriptValidateTypes
|
||||
export const PagesRoutes:RouterConfig = [
|
||||
{
|
||||
path: 'pages',
|
||||
component: Pages,
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: Dashboard,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Dashboard',
|
||||
icon: 'ion-android-home',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'editors',
|
||||
component: Editors,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Editors',
|
||||
icon: 'ion-edit',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 100,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'ckeditor',
|
||||
component: Ckeditor,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'CKEditor',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'components',
|
||||
component: Components,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Components',
|
||||
icon: 'ion-gear-a',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 250,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'treeview',
|
||||
component: TreeView,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Tree View',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'charts',
|
||||
component: Charts,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Charts',
|
||||
icon: 'ion-stats-bars',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 200,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'chartist-js',
|
||||
component: ChartistJs,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Chartist.Js',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'ui',
|
||||
component: Ui,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'UI Features',
|
||||
icon: 'ion-android-laptop',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 300,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'typography',
|
||||
component: Typography,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Typography',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'buttons',
|
||||
component: Buttons,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Buttons',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'icons',
|
||||
component: Icons,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Icons',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'grid',
|
||||
component: Grid,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Grid',
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'forms',
|
||||
component: Forms,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Form Elements',
|
||||
icon: 'ion-compose',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 400,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'inputs',
|
||||
component: Inputs,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Form Inputs',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'layouts',
|
||||
component: Layouts,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Form Layouts',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'tables',
|
||||
component: Tables,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Tables',
|
||||
icon: 'ion-grid',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 500,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basictables',
|
||||
component: BasicTables,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Basic Tables',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'maps',
|
||||
component: Maps,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Maps',
|
||||
icon: 'ion-ios-location-outline',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 600,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'googlemaps',
|
||||
component: GoogleMaps,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Google Maps',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'leafletmaps',
|
||||
component: LeafletMaps,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Leaflet Maps',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'bubblemaps',
|
||||
component: BubbleMaps,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Bubble Maps',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'linemaps',
|
||||
component: LineMaps,
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Line Maps',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Menu Level 1',
|
||||
icon: 'ion-ios-more',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 700,
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Menu Level 1.1',
|
||||
url: '#'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Menu Level 1.2',
|
||||
url: '#'
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
menu: {
|
||||
title: 'Menu Level 1.2.1',
|
||||
url: '#'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
menu: {
|
||||
title: 'External Link',
|
||||
url: 'http://akveo.com',
|
||||
icon: 'ion-android-exit',
|
||||
order: 800,
|
||||
target: '_blank'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
1
src/app/pages/register/index.ts
Normal file
1
src/app/pages/register/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './register.component';
|
||||
48
src/app/pages/register/register.component.ts
Normal file
48
src/app/pages/register/register.component.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {FormGroup, AbstractControl, FormBuilder, Validators} from '@angular/forms';
|
||||
import {EmailValidator, EqualPasswordsValidator} from '../../theme/validators';
|
||||
|
||||
@Component({
|
||||
selector: 'register',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
directives: [],
|
||||
styles: [require('./register.scss')],
|
||||
template: require('./register.html'),
|
||||
})
|
||||
export class Register {
|
||||
|
||||
public form:FormGroup;
|
||||
public name:AbstractControl;
|
||||
public email:AbstractControl;
|
||||
public password:AbstractControl;
|
||||
public repeatPassword:AbstractControl;
|
||||
public passwords:FormGroup;
|
||||
|
||||
public submitted:boolean = false;
|
||||
|
||||
constructor(fb:FormBuilder) {
|
||||
|
||||
this.form = fb.group({
|
||||
'name': ['', Validators.compose([Validators.required, Validators.minLength(4)])],
|
||||
'email': ['', Validators.compose([Validators.required, EmailValidator.validate])],
|
||||
'passwords': fb.group({
|
||||
'password': ['', Validators.compose([Validators.required, Validators.minLength(4)])],
|
||||
'repeatPassword': ['', Validators.compose([Validators.required, Validators.minLength(4)])]
|
||||
}, {validator: EqualPasswordsValidator.validate('password', 'repeatPassword')})
|
||||
});
|
||||
|
||||
this.name = this.form.controls['name'];
|
||||
this.email = this.form.controls['email'];
|
||||
this.passwords = <FormGroup> this.form.controls['passwords'];
|
||||
this.password = this.passwords.controls['password'];
|
||||
this.repeatPassword = this.passwords.controls['repeatPassword'];
|
||||
}
|
||||
|
||||
public onSubmit(values:Object):void {
|
||||
this.submitted = true;
|
||||
if (this.form.valid) {
|
||||
// your code goes here
|
||||
// console.log(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/app/pages/register/register.html
Normal file
53
src/app/pages/register/register.html
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<div class="auth-main">
|
||||
<div class="auth-block">
|
||||
<h1>Sign up to ng2-admin</h1>
|
||||
<a [routerLink]="['/login']" class="auth-link">Already have an ng2-admin account? Sign in!</a>
|
||||
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" class="form-horizontal">
|
||||
<div class="form-group row" [ngClass]="{'has-error': (!name.valid && name.touched), 'has-success': (name.valid && name.touched)}">
|
||||
<label for="inputName3" class="col-sm-2 control-label">Name</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input [formControl]="name" type="text" class="form-control" id="inputName3" placeholder="Full Name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row" [ngClass]="{'has-error': (!email.valid && email.touched), 'has-success': (email.valid && email.touched)}">
|
||||
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input [formControl]="email" type="email" class="form-control" id="inputEmail3" placeholder="Email">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row" [ngClass]="{'has-error': (!password.valid && password.touched), 'has-success': (password.valid && password.touched)}">
|
||||
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input [formControl]="password" type="password" class="form-control" id="inputPassword3" placeholder="Password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row" [ngClass]="{'has-error': (!repeatPassword.valid && repeatPassword.touched), 'has-success': (repeatPassword.valid && repeatPassword.touched)}">
|
||||
<label for="inputPassword4" class="col-sm-2 control-label">Repeat</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input [formControl]="repeatPassword" type="password" class="form-control" id="inputPassword4" placeholder="Repeat">
|
||||
<span *ngIf="!passwords.valid && (password.touched || repeatPassword.touched)" class="help-block sub-little-text">Passwords don't match.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button [disabled]="!form.valid" type="submit" class="btn btn-default btn-auth">Sign up</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="auth-sep"><span><span>or Sign up with one click</span></span></div>
|
||||
|
||||
<div class="al-share-auth">
|
||||
<ul class="al-share clearfix">
|
||||
<li><i class="socicon socicon-facebook" title="Share on Facebook"></i></li>
|
||||
<li><i class="socicon socicon-twitter" title="Share on Twitter"></i></li>
|
||||
<li><i class="socicon socicon-google" title="Share on Google Plus"></i></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
10
src/app/pages/register/register.routes.ts
Normal file
10
src/app/pages/register/register.routes.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import {RouterConfig} from '@angular/router';
|
||||
import {Register} from './register.component';
|
||||
|
||||
//noinspection TypeScriptValidateTypes
|
||||
export const RegisterRoutes: RouterConfig = [
|
||||
{
|
||||
path: 'register',
|
||||
component: Register
|
||||
}
|
||||
];
|
||||
1
src/app/pages/register/register.scss
Normal file
1
src/app/pages/register/register.scss
Normal file
|
|
@ -0,0 +1 @@
|
|||
@import '../../theme/sass/auth';
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
|
||||
import {BasicTables} from './components/basicTables';
|
||||
|
||||
@Component({
|
||||
selector: 'forms',
|
||||
|
|
@ -10,14 +7,6 @@ import {BasicTables} from './components/basicTables';
|
|||
styles: [],
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
name: 'BasicTables',
|
||||
component: BasicTables,
|
||||
path: '/basic',
|
||||
useAsDefault: true
|
||||
}
|
||||
])
|
||||
export class Tables {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router-deprecated';
|
||||
|
||||
import {Typography} from './components/typography';
|
||||
import {Buttons} from './components/buttons';
|
||||
import {Icons} from './components/incons';
|
||||
import {Grid} from './components/grid';
|
||||
|
||||
@Component({
|
||||
selector: 'ui',
|
||||
|
|
@ -13,29 +7,6 @@ import {Grid} from './components/grid';
|
|||
styles: [],
|
||||
template: `<router-outlet></router-outlet>`
|
||||
})
|
||||
@RouteConfig([
|
||||
{
|
||||
name: 'Typography',
|
||||
component: Typography,
|
||||
path: '/typography',
|
||||
useAsDefault: true
|
||||
},
|
||||
{
|
||||
name: 'Buttons',
|
||||
component: Buttons,
|
||||
path: '/buttons',
|
||||
},
|
||||
{
|
||||
name: 'Icons',
|
||||
component: Icons,
|
||||
path: '/icons',
|
||||
},
|
||||
{
|
||||
name: 'Grid',
|
||||
component: Grid,
|
||||
path: '/grid',
|
||||
}
|
||||
])
|
||||
export class Ui {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ export class BaBackTop {
|
|||
|
||||
@HostListener('click')
|
||||
_onClick():boolean {
|
||||
$('html, body').animate({scrollTop:0}, {duration:this.moveSpeed});
|
||||
jQuery('html, body').animate({scrollTop:0}, {duration:this.moveSpeed});
|
||||
return false;
|
||||
}
|
||||
|
||||
@HostListener('window:scroll')
|
||||
_onWindowScroll():void {
|
||||
let el = this._selector.nativeElement;
|
||||
window.scrollY > this.position ? $(el).fadeIn(this.showSpeed) : $(el).fadeOut(this.showSpeed);
|
||||
window.scrollY > this.position ? jQuery(el).fadeIn(this.showSpeed) : jQuery(el).fadeOut(this.showSpeed);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import {Component, ViewEncapsulation, Input} from '@angular/core';
|
||||
|
||||
import {Component, ViewEncapsulation, ViewChild, Input} from '@angular/core';
|
||||
import {BaCardBlur} from './baCardBlur.directive';
|
||||
|
||||
@Component({
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
export * from './baCard.component.ts';
|
||||
export * from './baCardBlur.directive';
|
||||
export * from './baCard.component';
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export class BaFullCalendar {
|
|||
@ViewChild('baFullCalendar') private _selector:ElementRef;
|
||||
|
||||
ngAfterViewInit() {
|
||||
let calendar = $(this._selector.nativeElement).fullCalendar(this.baFullCalendarConfiguration);
|
||||
let calendar = jQuery(this._selector.nativeElement).fullCalendar(this.baFullCalendarConfiguration);
|
||||
this.onCalendarReady.emit(calendar);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
71
src/app/theme/components/baMenu/baMenu.component.ts
Normal file
71
src/app/theme/components/baMenu/baMenu.component.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import {Component, ViewEncapsulation, Input, Output, EventEmitter} from '@angular/core';
|
||||
import {Router, RouterConfig, NavigationEnd} from '@angular/router';
|
||||
import {Subscription} from 'rxjs/Rx';
|
||||
|
||||
import {BaSlimScroll} from '../../../theme/directives';
|
||||
import {BaMenuService} from './baMenu.service';
|
||||
import {BaMenuItem} from './components/baMenuItem';
|
||||
|
||||
@Component({
|
||||
selector: 'ba-menu',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
styles: [require('./baMenu.scss')],
|
||||
template: require('./baMenu.html'),
|
||||
providers: [BaMenuService],
|
||||
directives: [BaMenuItem, BaSlimScroll]
|
||||
})
|
||||
export class BaMenu {
|
||||
|
||||
@Input() menuRoutes:RouterConfig = [];
|
||||
@Input() sidebarCollapsed:boolean = false;
|
||||
@Input() menuHeight:number;
|
||||
|
||||
@Output() expandMenu = new EventEmitter<any>();
|
||||
|
||||
public menuItems:any[];
|
||||
public showHoverElem:boolean;
|
||||
public hoverElemHeight:number;
|
||||
public hoverElemTop:number;
|
||||
protected _onRouteChange:Subscription;
|
||||
public outOfArea:number = -200;
|
||||
|
||||
constructor(private _router:Router, private _service:BaMenuService) {
|
||||
|
||||
this._onRouteChange = this._router.events.subscribe((event) => {
|
||||
if (this.menuItems && event instanceof NavigationEnd) {
|
||||
this.menuItems = this._service.selectMenuItem(this.menuItems);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnInit():void {
|
||||
this.menuItems = this._service.convertRoutesToMenus(this.menuRoutes);
|
||||
}
|
||||
|
||||
public ngOnDestroy():void {
|
||||
this._onRouteChange.unsubscribe();
|
||||
}
|
||||
|
||||
public hoverItem($event):void {
|
||||
this.showHoverElem = true;
|
||||
this.hoverElemHeight = $event.currentTarget.clientHeight;
|
||||
// TODO: get rid of magic 66 constant
|
||||
this.hoverElemTop = $event.currentTarget.getBoundingClientRect().top - 66;
|
||||
}
|
||||
|
||||
public toggleSubMenu($event):boolean {
|
||||
var submenu = jQuery($event.currentTarget).next();
|
||||
|
||||
if (this.sidebarCollapsed) {
|
||||
this.expandMenu.emit(null);
|
||||
if (!$event.item.expanded) {
|
||||
$event.item.expanded = true;
|
||||
}
|
||||
} else {
|
||||
$event.item.expanded = !$event.item.expanded;
|
||||
submenu.slideToggle();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
11
src/app/theme/components/baMenu/baMenu.html
Normal file
11
src/app/theme/components/baMenu/baMenu.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<aside class="al-sidebar" (mouseleave)="hoverElemTop=outOfArea" sidebarResize>
|
||||
<ul id="al-sidebar-list" class="al-sidebar-list" baSlimScroll [baSlimScrollOptions]="{height: menuHeight}">
|
||||
<ba-menu-item
|
||||
[menuItem]="item"
|
||||
(itemHover)="hoverItem($event)"
|
||||
(toggleSubMenu)="toggleSubMenu($event)"
|
||||
*ngFor="let item of menuItems"></ba-menu-item>
|
||||
</ul>
|
||||
<div class="sidebar-hover-elem" [ngStyle]="{top: hoverElemTop + 'px', height: hoverElemHeight + 'px'}"
|
||||
[ngClass]="{'show-hover-elem': showHoverElem }"></div>
|
||||
</aside>
|
||||
1
src/app/theme/components/baMenu/baMenu.scss
Normal file
1
src/app/theme/components/baMenu/baMenu.scss
Normal file
|
|
@ -0,0 +1 @@
|
|||
@import '../../sass/conf/conf';
|
||||
103
src/app/theme/components/baMenu/baMenu.service.ts
Normal file
103
src/app/theme/components/baMenu/baMenu.service.ts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {Router, UrlTree, RouterConfig} from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class BaMenuService {
|
||||
|
||||
constructor(private _router:Router) {
|
||||
}
|
||||
|
||||
public convertRoutesToMenus(routes:RouterConfig):any[] {
|
||||
let items = this._convertArrayToItems(routes);
|
||||
return this._skipEmpty(items);
|
||||
}
|
||||
|
||||
public selectMenuItem(menuItems:any[]):any[] {
|
||||
let items = [];
|
||||
menuItems.forEach((item) => {
|
||||
this._selectItem(item);
|
||||
|
||||
if (item.children && item.children.length > 0) {
|
||||
item.children = this.selectMenuItem(item.children);
|
||||
}
|
||||
items.push(item);
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
protected _skipEmpty(items:any[]):any[] {
|
||||
let menu = [];
|
||||
items.forEach((item) => {
|
||||
let menuItem;
|
||||
if (item.skip) {
|
||||
if (item.children && item.children.length > 0) {
|
||||
menuItem = item.children;
|
||||
}
|
||||
} else {
|
||||
menuItem = item;
|
||||
}
|
||||
|
||||
if (menuItem) {
|
||||
menu.push(menuItem);
|
||||
}
|
||||
});
|
||||
|
||||
return [].concat.apply([], menu);
|
||||
}
|
||||
|
||||
protected _convertArrayToItems(routes:any[], parent?:any):any[] {
|
||||
let items = [];
|
||||
routes.forEach((route) => {
|
||||
items.push(this._convertObjectToItem(route, parent));
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
protected _convertObjectToItem(object, parent?:any):any {
|
||||
let item:any = {};
|
||||
if (object.data && object.data.menu) {
|
||||
// this is a menu object
|
||||
item = object.data.menu;
|
||||
item.route = object;
|
||||
delete item.route.data.menu;
|
||||
} else {
|
||||
item.route = object;
|
||||
item.skip = true;
|
||||
}
|
||||
|
||||
// we have to collect all paths to correctly build the url then
|
||||
item.route.paths = parent && parent.route && parent.route.paths ? parent.route.paths.slice(0) : [];
|
||||
item.route.paths.push(item.route.path);
|
||||
|
||||
if (object.children && object.children.length > 0) {
|
||||
item.children = this._convertArrayToItems(object.children, item);
|
||||
}
|
||||
|
||||
let prepared = this._prepareItem(item);
|
||||
|
||||
// if current item is selected or expanded - then parent is expanded too
|
||||
if ((prepared.selected || prepared.expanded) && parent) {
|
||||
parent.expanded = true;
|
||||
}
|
||||
|
||||
return prepared;
|
||||
}
|
||||
|
||||
protected _prepareItem(object:any):any {
|
||||
if (!object.skip) {
|
||||
|
||||
let itemUrl = this._router.serializeUrl(this._router.createUrlTree(object.route.paths));
|
||||
object.url = object.url ? object.url : '/#' + itemUrl;
|
||||
|
||||
object.target = object.target || '';
|
||||
return this._selectItem(object);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
protected _selectItem(object:any):any {
|
||||
object.selected = object.url == ('/#' + this._router.url);
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import {Component, ViewEncapsulation, Input, Output, EventEmitter} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ba-menu-item',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
styles: [require('./baMenuItem.scss')],
|
||||
template: require('./baMenuItem.html'),
|
||||
providers: [],
|
||||
directives: [BaMenuItem]
|
||||
})
|
||||
export class BaMenuItem {
|
||||
|
||||
@Input() menuItem:any;
|
||||
@Input() child:boolean = false;
|
||||
|
||||
@Output() itemHover = new EventEmitter<any>();
|
||||
@Output() toggleSubMenu = new EventEmitter<any>();
|
||||
|
||||
public onHoverItem($event):void {
|
||||
this.itemHover.emit($event);
|
||||
}
|
||||
|
||||
public onToggleSubMenu($event, item):boolean {
|
||||
$event.item = item;
|
||||
this.toggleSubMenu.emit($event);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<li [ngClass]="{'al-sidebar-list-item': !child, 'ba-sidebar-sublist-item': child, 'selected': menuItem.selected && !menuItem.expanded, 'with-sub-menu': menuItem.children, 'ba-sidebar-item-expanded': menuItem.expanded}">
|
||||
|
||||
|
||||
<a *ngIf="!menuItem.children" (mouseenter)="onHoverItem($event, item)" [href]="menuItem.url" [target]="menuItem.target" class="al-sidebar-list-link">
|
||||
<i *ngIf="menuItem.icon" class="{{ menuItem.icon }}"></i><span>{{ menuItem.title }}</span>
|
||||
</a>
|
||||
|
||||
<a *ngIf="menuItem.children" (mouseenter)="onHoverItem($event, item)" (click)="onToggleSubMenu($event, menuItem)" class="al-sidebar-list-link">
|
||||
<i *ngIf="menuItem.icon" class="{{ menuItem.icon }}"></i><span>{{ menuItem.title }}</span>
|
||||
<b class="fa fa-angle-down" [ngClass]="{'fa-angle-up': menuItem.expanded}"></b>
|
||||
</a>
|
||||
|
||||
<ul *ngIf="menuItem.children" class="al-sidebar-sublist" [ngClass]="{'slide-right': menuItem.slideRight}">
|
||||
<ba-menu-item [menuItem]="subItem"
|
||||
[child]="true"
|
||||
(itemHover)="onHoverItem($event)"
|
||||
(toggleSubMenu)="onToggleSubMenu($event, subItem)"
|
||||
*ngFor="let subItem of menuItem.children"></ba-menu-item>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
|
@ -0,0 +1 @@
|
|||
@import '../../../../sass/conf/conf';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from './baMenuItem.component';
|
||||
1
src/app/theme/components/baMenu/index.ts
Normal file
1
src/app/theme/components/baMenu/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './baMenu.component.ts';
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import {Component, ViewChild, Input, Output, EventEmitter, ElementRef, Renderer} from '@angular/core';
|
||||
import {Ng2Uploader} from 'ng2-uploader/ng2-uploader';
|
||||
|
||||
@Component({
|
||||
selector: 'ba-picture-uploader',
|
||||
styles: [require('./baPictureUploader.scss')],
|
||||
template: require('./baPictureUploader.html'),
|
||||
providers: [Ng2Uploader]
|
||||
})
|
||||
export class BaPictureUploader {
|
||||
|
||||
@Input() defaultPicture:string = '';
|
||||
@Input() picture:string = '';
|
||||
|
||||
@Input() uploaderOptions:any = {};
|
||||
@Input() canDelete:boolean = true;
|
||||
|
||||
onUpload:EventEmitter<any> = new EventEmitter();
|
||||
onUploadCompleted:EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@ViewChild('fileUpload') protected _fileUpload:ElementRef;
|
||||
|
||||
public uploadInProgress:boolean = false;
|
||||
|
||||
constructor(private renderer:Renderer, protected _uploader:Ng2Uploader) {
|
||||
}
|
||||
|
||||
public ngOnInit():void {
|
||||
if (this._canUploadOnServer()) {
|
||||
setTimeout(() => {
|
||||
this._uploader.setOptions(this.uploaderOptions);
|
||||
});
|
||||
|
||||
this._uploader._emitter.subscribe((data) => {
|
||||
this._onUpload(data);
|
||||
});
|
||||
} else {
|
||||
console.warn('Please specify url parameter to be able to upload the file on the back-end');
|
||||
}
|
||||
}
|
||||
|
||||
public onFiles():void {
|
||||
let files = this._fileUpload.nativeElement.files;
|
||||
|
||||
if (files.length) {
|
||||
const file = files[0];
|
||||
this._changePicture(file);
|
||||
|
||||
if (this._canUploadOnServer()) {
|
||||
this.uploadInProgress = true;
|
||||
this._uploader.addFilesToQueue(files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bringFileSelector():boolean {
|
||||
this.renderer.invokeElementMethod(this._fileUpload.nativeElement, 'click');
|
||||
return false;
|
||||
}
|
||||
|
||||
public removePicture():boolean {
|
||||
this.picture = '';
|
||||
return false;
|
||||
}
|
||||
|
||||
protected _changePicture(file:File):void {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('load', (event:Event) => {
|
||||
this.picture = (<any> event.target).result;
|
||||
}, false);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
protected _onUpload(data):void {
|
||||
if (data['done'] || data['abort'] || data['error']) {
|
||||
this._onUploadCompleted(data);
|
||||
} else {
|
||||
this.onUpload.emit(data);
|
||||
}
|
||||
}
|
||||
|
||||
protected _onUploadCompleted(data):void {
|
||||
this.uploadInProgress = false;
|
||||
this.onUploadCompleted.emit(data);
|
||||
}
|
||||
|
||||
protected _canUploadOnServer():boolean {
|
||||
return !!this.uploaderOptions['url'];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<div class="picture-group" [ngClass]="{uploading: uploadInProgress}">
|
||||
<div class="picture-wrapper" (click)="bringFileSelector();">
|
||||
<img src="{{ picture }}" *ngIf="picture">
|
||||
<img src="{{ defaultPicture }}" *ngIf="!picture && defaultPicture">
|
||||
|
||||
<div class="loading" *ngIf="uploadInProgress">
|
||||
<div class="spinner">
|
||||
<div class="double-bounce1"></div>
|
||||
<div class="double-bounce2"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<i class="ion-ios-close-outline" (click)="removePicture();" *ngIf="picture && canDelete"></i>
|
||||
<a href class="change-picture" (click)="bringFileSelector();">Change profile Picture</a>
|
||||
<input #fileUpload type="file" hidden="true" id="uploadFile" (change)="onFiles()">
|
||||
</div>
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
@import '../../sass/conf/conf';
|
||||
|
||||
.picture-group {
|
||||
border: 1px dashed #b8b8b8;
|
||||
width: 202px;
|
||||
height: 202px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
.picture-wrapper {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
i {
|
||||
display: none;
|
||||
position: absolute;
|
||||
font-size: 32px;
|
||||
background: $default;
|
||||
cursor: pointer;
|
||||
color: $primary;
|
||||
top: -11px;
|
||||
right: -11px;
|
||||
height: 26px;
|
||||
border-radius: 50%;
|
||||
&:before {
|
||||
line-height: 26px;
|
||||
}
|
||||
&:hover {
|
||||
color: $danger;
|
||||
}
|
||||
}
|
||||
a.change-picture {
|
||||
display: none;
|
||||
width: 202px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
transition: all 200ms ease-in-out;
|
||||
color: $default-text;
|
||||
text-decoration: none;
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: -1px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
&:hover {
|
||||
i {
|
||||
display: block;
|
||||
}
|
||||
.change-picture {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.spinner {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.double-bounce1, .double-bounce2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
opacity: 0.6;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
-webkit-animation: sk-bounce 2.0s infinite ease-in-out;
|
||||
animation: sk-bounce 2.0s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.double-bounce2 {
|
||||
-webkit-animation-delay: -1.0s;
|
||||
animation-delay: -1.0s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-bounce {
|
||||
0%, 100% {
|
||||
-webkit-transform: scale(0.0)
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: scale(1.0)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-bounce {
|
||||
0%, 100% {
|
||||
transform: scale(0.0);
|
||||
-webkit-transform: scale(0.0);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.0);
|
||||
-webkit-transform: scale(1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/app/theme/components/baPictureUploader/index.ts
Normal file
1
src/app/theme/components/baPictureUploader/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './baPictureUploader.component.ts';
|
||||
|
|
@ -1,41 +1,32 @@
|
|||
import {Component, ElementRef, HostListener, ViewEncapsulation} from '@angular/core';
|
||||
import {Router} from '@angular/router-deprecated';
|
||||
|
||||
import {AppState} from '../../../app.state';
|
||||
import {layoutSizes} from '../../../theme';
|
||||
import {BaSlimScroll} from '../../../theme/directives';
|
||||
import {BaSidebarService} from './baSidebar.service';
|
||||
import {BaMenu} from '../baMenu';
|
||||
import {routes} from '../../../../app/app.routes';
|
||||
|
||||
@Component({
|
||||
selector: 'ba-sidebar',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
styles: [require('./baSidebar.scss')],
|
||||
template: require('./baSidebar.html'),
|
||||
providers: [BaSidebarService],
|
||||
directives: [BaSlimScroll]
|
||||
providers: [],
|
||||
directives: [BaMenu]
|
||||
})
|
||||
export class BaSidebar {
|
||||
|
||||
public menuItems:Array<any>;
|
||||
// here we declare which routes we want to use as a menu in our sidebar
|
||||
public routes = routes;
|
||||
|
||||
public menuHeight:number;
|
||||
public isMenuCollapsed:boolean = false;
|
||||
|
||||
public showHoverElem:boolean;
|
||||
public hoverElemHeight:number;
|
||||
public hoverElemTop:number;
|
||||
|
||||
public outOfArea:number = -200;
|
||||
|
||||
public isMenuShouldCollapsed:boolean = false;
|
||||
|
||||
constructor(private _elementRef:ElementRef,
|
||||
private _router:Router,
|
||||
private _sidebarService:BaSidebarService,
|
||||
private _state:AppState) {
|
||||
|
||||
this.menuItems = this._sidebarService.getMenuItems();
|
||||
this._router.root.subscribe((path) => this._selectMenuItem(path));
|
||||
this._state.subscribe('menu.isCollapsed', (isCollapsed) => { this.isMenuCollapsed = isCollapsed; });
|
||||
constructor(private _elementRef:ElementRef, private _state:AppState) {
|
||||
|
||||
this._state.subscribe('menu.isCollapsed', (isCollapsed) => {
|
||||
this.isMenuCollapsed = isCollapsed;
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnInit():void {
|
||||
|
|
@ -45,7 +36,7 @@ export class BaSidebar {
|
|||
}
|
||||
|
||||
public ngAfterViewInit():void {
|
||||
this.updateSidebarHeight();
|
||||
setTimeout(() => this.updateSidebarHeight());
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
|
|
@ -73,45 +64,12 @@ export class BaSidebar {
|
|||
this._state.notifyDataChanged('menu.isCollapsed', this.isMenuCollapsed);
|
||||
}
|
||||
|
||||
public hoverItem($event):void {
|
||||
this.showHoverElem = true;
|
||||
this.hoverElemHeight = $event.currentTarget.clientHeight;
|
||||
// TODO: get rid of magic 66 constant
|
||||
this.hoverElemTop = $event.currentTarget.getBoundingClientRect().top - 66;
|
||||
}
|
||||
|
||||
public updateSidebarHeight():void {
|
||||
// TODO: get rid of magic 84 constant
|
||||
this.menuHeight = this._elementRef.nativeElement.childNodes[0].clientHeight - 84;
|
||||
}
|
||||
|
||||
public toggleSubMenu($event, item):boolean {
|
||||
var submenu = $($event.currentTarget).next();
|
||||
|
||||
if (this.isMenuCollapsed) {
|
||||
this.menuExpand();
|
||||
if (!item.expanded) {
|
||||
item.expanded = true;
|
||||
}
|
||||
} else {
|
||||
item.expanded = !item.expanded;
|
||||
submenu.slideToggle();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private _shouldMenuCollapse():boolean {
|
||||
return window.innerWidth <= layoutSizes.resWidthCollapseSidebar;
|
||||
}
|
||||
|
||||
private _selectMenuItem(currentPath = null):void {
|
||||
|
||||
let currentMenu = this._sidebarService.setRouter(this._router).selectMenuItem(this.menuItems, currentPath);
|
||||
this._state.notifyDataChanged('menu.activeLink', currentMenu);
|
||||
// hide menu after natigation on mobile devises
|
||||
if (this._shouldMenuCollapse()) {
|
||||
this.menuCollapse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,55 +1,6 @@
|
|||
<aside class="al-sidebar" (mouseleave)="hoverElemTop=outOfArea" sidebarResize>
|
||||
<ul id="al-sidebar-list" class="al-sidebar-list" baSlimScroll [baSlimScrollOptions]="{height: menuHeight}">
|
||||
<li *ngFor="let item of menuItems" class="al-sidebar-list-item"
|
||||
[ngClass]="{'selected': item.selected && !item.expanded, 'with-sub-menu': item.subMenu, 'ba-sidebar-item-expanded': item.expanded}">
|
||||
|
||||
|
||||
<a *ngIf="!item.component && !item.subMenu" [attr.href]="item.url || ''" [attr.target]="item.target || ''" class="al-sidebar-list-link">
|
||||
<i class="{{ item.icon }}"></i><span>{{ item.title }}</span>
|
||||
</a>
|
||||
<a *ngIf="item.component && !item.subMenu" [routerLink]="[item.component]" [attr.target]="item.target || ''" class="al-sidebar-list-link">
|
||||
<i class="{{ item.icon }}"></i><span>{{ item.title }}</span>
|
||||
</a>
|
||||
|
||||
<a *ngIf="item.subMenu" (mouseenter)="hoverItem($event, item)" (click)="toggleSubMenu($event, item)"
|
||||
class="al-sidebar-list-link">
|
||||
<i class="{{ item.icon }}"></i><span>{{ item.title }}</span>
|
||||
<b class="fa" [ngClass]="{'fa-angle-up': item.expanded, 'fa-angle-down': !item.expanded}"
|
||||
*ngIf="item.subMenu"></b>
|
||||
</a>
|
||||
|
||||
<ul *ngIf="item.subMenu" class="al-sidebar-sublist"
|
||||
[ngClass]="{'slide-right': item.slideRight}">
|
||||
<li *ngFor="let subitem of item.subMenu" class="ba-sidebar-sublist-item"
|
||||
[ngClass]="{'selected': subitem.selected, 'with-sub-menu': subitem.subMenu}">
|
||||
<a (mouseenter)="hoverItem($event, item)" *ngIf="subitem.subMenu" (click)="toggleSubMenu($event, subitem);"
|
||||
class="al-sidebar-list-link subitem-submenu-link"><span>{{ subitem.title }}</span>
|
||||
<b class="fa" *ngIf="subitem.subMenu"
|
||||
[ngClass]="{'fa-angle-up': subitem.expanded, 'fa-angle-down': !subitem.expanded}"></b>
|
||||
</a>
|
||||
<ul *ngIf="subitem.subMenu" class="al-sidebar-sublist subitem-submenu-list"
|
||||
[ngClass]="{expanded: subitem.expanded, 'slide-right': subitem.slideRight}">
|
||||
<li *ngFor="let subSubitem of subitem.subMenu" (mouseenter)="hoverItem($event, item)"
|
||||
[ngClass]="{selected: subitem.selected}">
|
||||
<a *ngIf="!item.component" (mouseenter)="hoverItem($event, item)" [attr.href]="subSubitem.url || ''" [attr.target]="subSubitem.target || ''">
|
||||
{{ subSubitem.title }}</a>
|
||||
<a *ngIf="item.component" (mouseenter)="hoverItem($event, item)" [attr.target]="subSubitem.target || ''" [routerLink]="[item.component, subitem.component, subSubitem.component]">
|
||||
{{ subSubitem.title }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a *ngIf="!item.component && !subitem.subMenu" [attr.href]="subitem.url || ''"
|
||||
(mouseenter)="hoverItem($event, item)" [attr.target]="subitem.target || ''">
|
||||
{{ subitem.title}}
|
||||
</a>
|
||||
<a *ngIf="item.component && !subitem.subMenu" [routerLink]="[item.component, subitem.component]"
|
||||
(mouseenter)="hoverItem($event, item)" [attr.target]="subitem.target || ''">
|
||||
{{ subitem.title}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<div class="sidebar-hover-elem" [ngStyle]="{top: hoverElemTop + 'px', height: hoverElemHeight + 'px'}"
|
||||
[ngClass]="{'show-hover-elem': showHoverElem }"></div>
|
||||
<ba-menu [menuRoutes]="routes"
|
||||
[menuHeight]="menuHeight"
|
||||
[sidebarCollapsed]="isMenuCollapsed"
|
||||
(expandMenu)="menuExpand()"></ba-menu>
|
||||
</aside>
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ a.al-sidebar-list-link {
|
|||
&.expanded {
|
||||
display: block;
|
||||
}
|
||||
> li {
|
||||
> ba-menu-item > li {
|
||||
display: block;
|
||||
float: none;
|
||||
padding: 0;
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {menuItems} from '../../../app.menu';
|
||||
|
||||
@Injectable()
|
||||
export class BaSidebarService {
|
||||
|
||||
private _router;
|
||||
|
||||
public getMenuItems():Array<Object> {
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
public setRouter(router): BaSidebarService {
|
||||
this._router = router;
|
||||
return this;
|
||||
}
|
||||
|
||||
public selectMenuItem(items:Array<any>, currentPath:string) {
|
||||
let currentMenu;
|
||||
|
||||
let assignCurrent = (menu) => (menu.selected ? currentMenu = menu : null);
|
||||
|
||||
items.forEach((menu: any) => {
|
||||
|
||||
this._selectItem(currentPath, [menu.component], menu);
|
||||
assignCurrent(menu);
|
||||
|
||||
if (menu.subMenu) {
|
||||
menu.subMenu.forEach((subMenu) => {
|
||||
this._selectItem(currentPath, [menu.component, subMenu.component], subMenu, menu);
|
||||
assignCurrent(subMenu);
|
||||
});
|
||||
}
|
||||
});
|
||||
return currentMenu;
|
||||
}
|
||||
|
||||
private _selectItem(currentPath, instructions, item, parentMenu = null) {
|
||||
let route = this._generateRoute(instructions);
|
||||
item.selected = !item.disabled && this._isCurrent(route) && this._resolvePath(route, '') == currentPath;
|
||||
if (parentMenu) {
|
||||
parentMenu.expanded = parentMenu.expanded || item.selected;
|
||||
}
|
||||
}
|
||||
|
||||
private _isCurrent(route) {
|
||||
return route ? this._router.isRouteActive(route) : false;
|
||||
}
|
||||
|
||||
private _generateRoute(instructions) {
|
||||
return instructions.filter(i => typeof i !== 'undefined').length > 0 ? this._router.generate(instructions) : null;
|
||||
}
|
||||
|
||||
private _resolvePath(instruction, collected) {
|
||||
if (instruction !== null) {
|
||||
collected += instruction.urlPath + '/';
|
||||
return this._resolvePath(instruction.child, collected)
|
||||
} else {
|
||||
return collected.slice(0, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
export * from './baPageTop';
|
||||
export * from './baMsgCenter';
|
||||
export * from './baSidebar';
|
||||
export * from './baMenu';
|
||||
export * from './baContentTop';
|
||||
export * from './baCard';
|
||||
export * from './baAmChart';
|
||||
export * from './baChartistChart';
|
||||
export * from './baBackTop';
|
||||
export * from './baFullCalendar';
|
||||
export * from './baPictureUploader';
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ export class BaSlimScroll {
|
|||
}
|
||||
|
||||
private _init() {
|
||||
$(this._elementRef.nativeElement).slimScroll(this.baSlimScrollOptions);
|
||||
jQuery(this._elementRef.nativeElement).slimScroll(this.baSlimScrollOptions);
|
||||
}
|
||||
|
||||
private _destroy() {
|
||||
$(this._elementRef.nativeElement).slimScroll({ destroy: true });
|
||||
jQuery(this._elementRef.nativeElement).slimScroll({ destroy: true });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
127
src/app/theme/sass/_auth.scss
Normal file
127
src/app/theme/sass/_auth.scss
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
@import 'conf/conf';
|
||||
|
||||
$text-color: #ffffff;
|
||||
|
||||
|
||||
.auth-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.auth-block {
|
||||
width: 540px;
|
||||
margin: 0 auto;
|
||||
border-radius: 5px;
|
||||
@include bg-translucent-dark(0.55);
|
||||
color: #fff;
|
||||
padding: 32px;
|
||||
h1 {
|
||||
font-weight: $font-light;
|
||||
margin-bottom: 28px;
|
||||
text-align: center;
|
||||
}
|
||||
p {
|
||||
font-size: 16px;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
transition: all 0.2s ease;
|
||||
color: $primary;
|
||||
&:hover {
|
||||
color: $primary-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.control-label {
|
||||
padding-top: 11px;
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.auth-input {
|
||||
width: 300px;
|
||||
margin-bottom: 24px;
|
||||
input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
padding: 4px 10px;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
a.forgot-pass {
|
||||
display: block;
|
||||
text-align: right;
|
||||
margin-bottom: -20px;
|
||||
float: right;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.auth-link {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 33px;
|
||||
}
|
||||
|
||||
.auth-sep {
|
||||
margin-top: 36px;
|
||||
margin-bottom: 24px;
|
||||
line-height: 20px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
position: relative;
|
||||
& > span {
|
||||
display: table-cell;
|
||||
width: 30%;
|
||||
white-space: nowrap;
|
||||
padding: 0 24px;
|
||||
color: $text-color;
|
||||
& > span {
|
||||
margin-top: -12px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&:before, &:after {
|
||||
border-top: solid 1px $text-color;
|
||||
content: "";
|
||||
height: 1px;
|
||||
width: 35%;
|
||||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.al-share-auth {
|
||||
text-align: center;
|
||||
.al-share {
|
||||
float: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
li {
|
||||
margin-left: 24px;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
i {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-auth {
|
||||
color: #ffffff!important;
|
||||
}
|
||||
|
|
@ -582,3 +582,11 @@ label.custom-input-danger {
|
|||
.sub-little-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.rating {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
rating-inputs span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ a {
|
|||
|
||||
.al-footer {
|
||||
height: 34px;
|
||||
padding: 0px 18px 0 $left-space;
|
||||
padding: 0 18px 0 200px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
display: block;
|
||||
|
|
|
|||
27
src/app/theme/sass/_treeView.scss
Normal file
27
src/app/theme/sass/_treeView.scss
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#tree-view .tree {
|
||||
& .node-value {
|
||||
color: white;
|
||||
}
|
||||
& .folding {
|
||||
&.node-expanded::before {
|
||||
color: white;
|
||||
}
|
||||
&.node-collapsed::before {
|
||||
color: white;
|
||||
}
|
||||
&.node-leaf::before {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
& .over-drop-target {
|
||||
border: 4px solid ghostwhite;
|
||||
}
|
||||
& .node-value{
|
||||
& .node-selected::after {
|
||||
background-color: white;
|
||||
}
|
||||
&:after {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {colorHelper} from './theme.constants';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@Injectable()
|
||||
export class BaThemeConfigProvider {
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@
|
|||
@import "sass/socicon";
|
||||
@import "sass/table";
|
||||
@import "sass/form";
|
||||
@import "sass/treeView";
|
||||
|
|
|
|||
14
src/app/theme/validators/email.validator.ts
Normal file
14
src/app/theme/validators/email.validator.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import {AbstractControl} from '@angular/forms';
|
||||
|
||||
export class EmailValidator {
|
||||
|
||||
public static validate(c:AbstractControl) {
|
||||
let EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
||||
|
||||
return EMAIL_REGEXP.test(c.value) ? null : {
|
||||
validateEmail: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
16
src/app/theme/validators/equalPasswords.validator.ts
Normal file
16
src/app/theme/validators/equalPasswords.validator.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import {FormGroup} from '@angular/forms';
|
||||
|
||||
export class EqualPasswordsValidator {
|
||||
|
||||
public static validate(firstField, secondField) {
|
||||
|
||||
return (c:FormGroup) => {
|
||||
|
||||
return (c.controls && c.controls[firstField].value == c.controls[secondField].value) ? null : {
|
||||
passwordsEqual: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
2
src/app/theme/validators/index.ts
Normal file
2
src/app/theme/validators/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from './email.validator';
|
||||
export * from './equalPasswords.validator';
|
||||
2
src/custom-typings.d.ts
vendored
2
src/custom-typings.d.ts
vendored
|
|
@ -29,7 +29,7 @@ import * as _ from 'lodash'
|
|||
*
|
||||
*/
|
||||
|
||||
declare var $:any;
|
||||
declare var jQuery:any;
|
||||
declare var GoogleMapsLoader:any;
|
||||
declare var L:any;
|
||||
declare var AmCharts:any;
|
||||
|
|
|
|||
|
|
@ -5,11 +5,14 @@
|
|||
import {PLATFORM_DIRECTIVES} from '@angular/core';
|
||||
|
||||
// Angular 2 Router
|
||||
import {ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
||||
import {ROUTER_DIRECTIVES} from '@angular/router';
|
||||
// Angular 2 forms
|
||||
import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms';
|
||||
|
||||
// application_directives: directives that are global through out the application
|
||||
export const APPLICATION_DIRECTIVES = [
|
||||
...ROUTER_DIRECTIVES
|
||||
...ROUTER_DIRECTIVES,
|
||||
...REACTIVE_FORM_DIRECTIVES
|
||||
];
|
||||
|
||||
export const DIRECTIVES = [
|
||||
|
|
|
|||
|
|
@ -7,18 +7,24 @@ import {FORM_PROVIDERS, LocationStrategy, HashLocationStrategy} from '@angular/c
|
|||
|
||||
// Angular 2 Http
|
||||
import {HTTP_PROVIDERS} from '@angular/http';
|
||||
// Angular 2 Router
|
||||
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
||||
import {APP_ROUTER_PROVIDERS} from '../../app/app.routes';
|
||||
|
||||
|
||||
// Angular 2 forms
|
||||
import {disableDeprecatedForms, provideForms} from '@angular/forms';
|
||||
|
||||
/*
|
||||
* Application Providers/Directives/Pipes
|
||||
* providers/directives/pipes that only live in our browser environment
|
||||
*/
|
||||
* Application Providers/Directives/Pipes
|
||||
* providers/directives/pipes that only live in our browser environment
|
||||
*/
|
||||
export const APPLICATION_PROVIDERS = [
|
||||
...FORM_PROVIDERS,
|
||||
// new Angular 2 forms
|
||||
disableDeprecatedForms(),
|
||||
provideForms(),
|
||||
...HTTP_PROVIDERS,
|
||||
...ROUTER_PROVIDERS,
|
||||
{provide: LocationStrategy, useClass: HashLocationStrategy }
|
||||
...APP_ROUTER_PROVIDERS,
|
||||
{provide: LocationStrategy, useClass: HashLocationStrategy},
|
||||
{provide: LocationStrategy, useClass: HashLocationStrategy}
|
||||
];
|
||||
|
||||
export const PROVIDERS = [
|
||||
|
|
|
|||
|
|
@ -1,25 +1,39 @@
|
|||
// Angular 2
|
||||
import {enableProdMode} from '@angular/core';
|
||||
|
||||
// rc2 workaround
|
||||
import { enableDebugTools, disableDebugTools } from '@angular/platform-browser';
|
||||
import { enableProdMode } from '@angular/core';
|
||||
// Environment Providers
|
||||
let PROVIDERS = [];
|
||||
let PROVIDERS = [
|
||||
// common env directives
|
||||
];
|
||||
|
||||
// Angular debug tools in the dev console
|
||||
// https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
|
||||
let _decorateComponentRef = function identity(value) { return value; };
|
||||
|
||||
if ('production' === ENV) {
|
||||
// Production
|
||||
disableDebugTools();
|
||||
enableProdMode();
|
||||
|
||||
PROVIDERS = [
|
||||
...PROVIDERS
|
||||
...PROVIDERS,
|
||||
// custom providers in production
|
||||
];
|
||||
|
||||
} else {
|
||||
|
||||
_decorateComponentRef = (cmpRef) => enableDebugTools(cmpRef);
|
||||
|
||||
// Development
|
||||
PROVIDERS = [
|
||||
...PROVIDERS
|
||||
...PROVIDERS,
|
||||
// custom providers in development
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
export const decorateComponentRef = _decorateComponentRef;
|
||||
|
||||
export const ENV_PROVIDERS = [
|
||||
...PROVIDERS
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import '@angular/platform-browser-dynamic';
|
|||
import '@angular/core';
|
||||
import '@angular/common';
|
||||
import '@angular/http';
|
||||
import '@angular/router-deprecated';
|
||||
import '@angular/router';
|
||||
|
||||
// RxJS
|
||||
import 'rxjs/add/operator/map';
|
||||
|
|
|
|||
|
|
@ -8,19 +8,9 @@
|
|||
"noEmitHelpers": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"typings/main.d.ts",
|
||||
"typings/main"
|
||||
],
|
||||
"filesGlob": [
|
||||
"./src/**/*.ts",
|
||||
"./test/**/*.ts",
|
||||
"!./node_modules/**/*.ts",
|
||||
"src/custom-typings.d.ts",
|
||||
"typings/browser.d.ts"
|
||||
"node_modules"
|
||||
],
|
||||
"awesomeTypescriptLoaderOptions": {
|
||||
"resolveGlobs": true,
|
||||
"forkChecker": true
|
||||
},
|
||||
"compileOnSave": false,
|
||||
|
|
|
|||
17
tslint.json
17
tslint.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"rulesDirectory": [
|
||||
"node_modules/codelyzer/dist/src"
|
||||
"node_modules/codelyzer"
|
||||
],
|
||||
"rules": {
|
||||
"member-access": false,
|
||||
|
|
@ -133,19 +133,6 @@
|
|||
"check-separator",
|
||||
"check-type"
|
||||
],
|
||||
|
||||
"directive-selector-name": [true, "kebab-case"],
|
||||
"component-selector-name": [true, "kebab-case"],
|
||||
"directive-selector-type": [true, "attribute"],
|
||||
"component-selector-type": [true, "element"],
|
||||
"directive-selector-prefix": false,
|
||||
"component-selector-prefix": false,
|
||||
"host-parameter-decorator": true,
|
||||
"input-parameter-decorator": true,
|
||||
"output-parameter-decorator": true,
|
||||
"attribute-parameter-decorator": false,
|
||||
"input-property-directive": true,
|
||||
"output-property-directive": true,
|
||||
"call-forward-ref":true
|
||||
"import-destructuring-spacing": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
21
typings.json
21
typings.json
|
|
@ -1,13 +1,16 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"zone.js": "github:gdi2290/typed-zone.js#66ea8a3451542bb7798369306840e46be1d6ec89"
|
||||
"globalDependencies": {
|
||||
"angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459",
|
||||
"core-js": "registry:dt/core-js#0.0.0+20160602141332",
|
||||
"hammerjs": "registry:dt/hammerjs#2.0.4+20160417130828",
|
||||
"jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
|
||||
"node": "registry:dt/node#6.0.0+20160621231320",
|
||||
"selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654",
|
||||
"source-map": "registry:dt/source-map#0.0.0+20160317120654",
|
||||
"uglify-js": "registry:dt/uglify-js#2.6.1+20160316155526",
|
||||
"webpack": "registry:dt/webpack#1.12.9+20160523035535"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"ambientDependencies": {
|
||||
"core-js": "registry:dt/core-js#0.0.0+20160317120654",
|
||||
"hammerjs": "github:DefinitelyTyped/DefinitelyTyped/hammerjs/hammerjs.d.ts#74a4dfc1bc2dfadec47b8aae953b28546cb9c6b7",
|
||||
"lodash": "registry:dt/lodash#3.10.0+20160330154726",
|
||||
"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#8cf8164641be73e8f1e652c2a5b967c7210b6729",
|
||||
"webpack": "github:DefinitelyTyped/DefinitelyTyped/webpack/webpack.d.ts#95c02169ba8fa58ac1092422efbd2e3174a206f4"
|
||||
"dependencies": {
|
||||
"lodash": "registry:npm/lodash#4.0.0+20160416211519"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue