├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── LICENSE ├── README.md ├── angular-cli.json ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.json ├── karma.conf.js ├── package.json ├── protractor.conf.js ├── src ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routing.ts │ ├── dnd │ │ ├── custom-data-dnd.component.ts │ │ ├── custom-function-dnd.component.ts │ │ ├── demo-dnd.module.ts │ │ ├── dnd.component.html │ │ ├── dnd.component.ts │ │ ├── embedded-sortable.component.ts │ │ ├── multi-sortable.component.ts │ │ ├── recycle-multi-sortable.component.ts │ │ ├── shopping-basket-dnd.component.ts │ │ ├── simple-dnd.component.ts │ │ ├── simple-sortable-copy.component.ts │ │ ├── simple-sortable.component.ts │ │ └── zone-dnd.component.ts │ ├── home │ │ ├── home.component.html │ │ └── home.component.ts │ ├── index.ts │ ├── slim │ │ ├── slim.component.html │ │ └── slim.component.ts │ └── toast │ │ ├── index.ts │ │ ├── toast-communication.service.ts │ │ └── toast.component.ts ├── assets │ ├── .gitkeep │ └── .npmignore ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── skeleton.css ├── styles.css ├── test.ts ├── tsconfig.json └── typings.d.ts └── tslint.json /.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 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Read and contribute to the Wiki 2 | 3 | Make sure you read the Wiki 4 | https://github.com/akserg/ng2-webpack-demo/wiki 5 | 6 | ## Submitting Pull Requests 7 | If you're changing the structure of the repository please create an issue first 8 | 9 | ## Submitting bug reports 10 | 11 | Make sure you are on latest changes and that you ran this command `npm run clean:install` after updating your local repository. If you can, please provide more infomation about your environment such as browser, operating system, node version, and npm version -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | * **I'm submitting a ...** 2 | [ ] bug report 3 | [ ] feature request 4 | [ ] question about the decisions made in the repository 5 | 6 | * **Do you want to request a *feature* or report a *bug*?** 7 | 8 | 9 | 10 | * **What is the current behavior?** 11 | 12 | 13 | 14 | * **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via https://plnkr.co or similar. 15 | 16 | 17 | 18 | * **What is the expected behavior?** 19 | 20 | 21 | 22 | * **What is the motivation / use case for changing the behavior?** 23 | 24 | 25 | 26 | * **Please tell us about your environment:** 27 | 28 | - Angular version: 2.0.0-beta.X 29 | - Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] 30 | 31 | 32 | 33 | * **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc) 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | * **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...) 2 | 3 | 4 | 5 | * **What is the current behavior?** (You can also link to an open issue here) 6 | 7 | 8 | 9 | * **What is the new behavior (if this is a feature change)?** 10 | 11 | 12 | 13 | * **Other information**: 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | 10 | # IDEs and editors 11 | /.idea 12 | .project 13 | .classpath 14 | .c9/ 15 | *.launch 16 | .settings/ 17 | 18 | # IDE - VSCode 19 | .vscode/* 20 | !.vscode/settings.json 21 | !.vscode/tasks.json 22 | !.vscode/launch.json 23 | !.vscode/extensions.json 24 | 25 | # misc 26 | /.sass-cache 27 | /connect.lock 28 | /coverage/* 29 | /libpeerconnection.log 30 | npm-debug.log 31 | testem.log 32 | /typings 33 | 34 | # e2e 35 | /e2e/*.js 36 | /e2e/*.map 37 | 38 | #System Files 39 | .DS_Store 40 | Thumbs.db 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 AngularClass LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ng2-webpack-demo 2 | 3 | This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.24. 4 | It demonstrates the use of different libraries such: 5 | > - [ng2-dnd](https://github.com/akserg/ng2-dnd): Angular 2 Drag-and-Drop without dependencies 6 | > - [ng2-toasty](https://github.com/akserg/ng2-toasty): Angular2 Toasty component shows growl-style alerts and messages for your application 7 | > - [ng2-slim-loading-bar](https://github.com/akserg/ng2-slim-loading-bar): Angular 2 component shows slim loading bar at the top of the page 8 | 9 | Online demo available [here](http://akserg.github.io/ng2-webpack-demo) 10 | 11 | 12 | ## Development server 13 | Run `npm start` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 14 | 15 | ## Code scaffolding 16 | 17 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`. 18 | 19 | ## Build 20 | 21 | 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. 22 | 23 | ## Build with AOT 24 | 25 | Run `npm run aot:buildd` to build the project for production with Ahead of Time (AOT) compilation. The build artifacts will be stored in the `dist/` directory. 26 | Use the `npm run aot:start` to start server in production with AOT. 27 | 28 | ## Running unit tests 29 | 30 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 31 | 32 | ## Running end-to-end tests 33 | 34 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 35 | Before running the tests make sure you are serving the app via `ng serve`. 36 | 37 | ## Deploying to Github Pages 38 | 39 | Run `ng github-pages:deploy` to deploy to Github Pages. 40 | 41 | ## Further help 42 | 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). 43 | 44 | # License 45 | [MIT](/LICENSE) -------------------------------------------------------------------------------- /angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": { 3 | "version": "1.0.0-beta.24", 4 | "name": "ng2-webpack-demo" 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 | "test": "test.ts", 17 | "tsconfig": "tsconfig.json", 18 | "prefix": "app", 19 | "mobile": false, 20 | "styles": [ 21 | "../node_modules/ng2-toasty/style.css", 22 | "../node_modules/ng2-dnd/style.css", 23 | "../node_modules/ng2-slim-loading-bar/style.css", 24 | "skeleton.css", 25 | "styles.css" 26 | ], 27 | "scripts": [], 28 | "environmentSource": "environments/environment.ts", 29 | "environments": { 30 | "dev": "environments/environment.ts", 31 | "prod": "environments/environment.prod.ts" 32 | } 33 | } 34 | ], 35 | "addons": [], 36 | "packages": [], 37 | "e2e": { 38 | "protractor": { 39 | "config": "./protractor.conf.js" 40 | } 41 | }, 42 | "test": { 43 | "karma": { 44 | "config": "./karma.conf.js" 45 | } 46 | }, 47 | "defaults": { 48 | "styleExt": "css", 49 | "prefixInterfaces": false, 50 | "inline": { 51 | "style": false, 52 | "template": false 53 | }, 54 | "spec": { 55 | "class": false, 56 | "component": true, 57 | "directive": true, 58 | "module": false, 59 | "pipe": true, 60 | "service": true 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Ng2WebpackDemoPage } from './app.po'; 2 | 3 | describe('ng2-webpack-demo App', function() { 4 | let page: Ng2WebpackDemoPage; 5 | 6 | beforeEach(() => { 7 | page = new Ng2WebpackDemoPage(); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | export class Ng2WebpackDemoPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "outDir": "../dist/out-tsc-e2e", 10 | "sourceMap": true, 11 | "target": "es5", 12 | "typeRoots": [ 13 | "../node_modules/@types" 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', 'angular-cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-remap-istanbul'), 12 | require('angular-cli/plugins/karma') 13 | ], 14 | files: [ 15 | { pattern: './src/test.ts', watched: false } 16 | ], 17 | preprocessors: { 18 | './src/test.ts': ['angular-cli'] 19 | }, 20 | mime: { 21 | 'text/x-typescript': ['ts','tsx'] 22 | }, 23 | remapIstanbulReporter: { 24 | reports: { 25 | html: 'coverage', 26 | lcovonly: './coverage/coverage.lcov' 27 | } 28 | }, 29 | angularCli: { 30 | config: './angular-cli.json', 31 | environment: 'dev' 32 | }, 33 | reporters: config.angularCli && config.angularCli.codeCoverage 34 | ? ['progress', 'karma-remap-istanbul'] 35 | : ['progress'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-webpack-demo", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "angular-cli": {}, 6 | "scripts": { 7 | "ng": "ng", 8 | "start": "ng serve", 9 | "lint": "tslint \"src/**/*.ts\"", 10 | "test": "ng test", 11 | "pree2e": "webdriver-manager update --standalone false --gecko false", 12 | "e2e": "protractor", 13 | "aot:build": "ng build --prod --aot", 14 | "aot:start": "ng serve --prod --aot" 15 | }, 16 | "private": true, 17 | "dependencies": { 18 | "@angular/common": "^2.4.7", 19 | "@angular/compiler": "^2.4.7", 20 | "@angular/core": "^2.4.7", 21 | "@angular/forms": "^2.4.7", 22 | "@angular/http": "^2.4.7", 23 | "@angular/platform-browser": "^2.4.7", 24 | "@angular/platform-browser-dynamic": "^2.4.7", 25 | "@angular/router": "^3.4.7", 26 | "core-js": "^2.4.1", 27 | "rxjs": "^5.1.1", 28 | "ts-helpers": "^1.1.1", 29 | "zone.js": "^0.7.7", 30 | "ng2-dnd": "^2.2.2", 31 | "ng2-slim-loading-bar": "^2.3.0", 32 | "ng2-toasty": "^2.4.0" 33 | }, 34 | "devDependencies": { 35 | "@angular/cli": "1.0.0-beta.32.3", 36 | "@angular/compiler-cli": "^2.4.7", 37 | "@types/jasmine": "2.5.43", 38 | "@types/node": "^7.0.5", 39 | "codelyzer": "~2.0.0-beta.2", 40 | "jasmine-core": "2.5.2", 41 | "jasmine-spec-reporter": "3.2.0", 42 | "karma": "1.4.0", 43 | "karma-chrome-launcher": "^2.0.0", 44 | "karma-cli": "^1.0.1", 45 | "karma-jasmine": "^1.0.2", 46 | "karma-remap-istanbul": "^0.6.0", 47 | "protractor": "~5.1.1", 48 | "ts-node": "2.1.0", 49 | "tslint": "4.3.1", 50 | "typescript": "~2.1.6" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | /*global jasmine */ 5 | var SpecReporter = require('jasmine-spec-reporter'); 6 | 7 | exports.config = { 8 | allScriptsTimeout: 11000, 9 | specs: [ 10 | './e2e/**/*.e2e-spec.ts' 11 | ], 12 | capabilities: { 13 | 'browserName': 'chrome' 14 | }, 15 | directConnect: true, 16 | baseUrl: 'http://localhost:4200/', 17 | framework: 'jasmine', 18 | jasmineNodeOpts: { 19 | showColors: true, 20 | defaultTimeoutInterval: 30000, 21 | print: function() {} 22 | }, 23 | useAllAngular2AppRoots: true, 24 | beforeLaunch: function() { 25 | require('ts-node').register({ 26 | project: 'e2e' 27 | }); 28 | }, 29 | onPrepare: function() { 30 | jasmine.getEnv().addReporter(new SpecReporter()); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akserg/ng2-webpack-demo/8e524bc87a41dae716a288306d76afda610fe1e7/src/app/app.component.css -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | Fork me on GitHub 2 |
3 |
4 | 10 | 11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { AppComponent } from './app.component'; 5 | 6 | describe('AppComponent', () => { 7 | beforeEach(() => { 8 | TestBed.configureTestingModule({ 9 | declarations: [ 10 | AppComponent 11 | ], 12 | }); 13 | TestBed.compileComponents(); 14 | }); 15 | 16 | it('should create the app', async(() => { 17 | let fixture = TestBed.createComponent(AppComponent); 18 | let app = fixture.debugElement.componentInstance; 19 | expect(app).toBeTruthy(); 20 | })); 21 | 22 | it(`should have as title 'app works!'`, async(() => { 23 | let fixture = TestBed.createComponent(AppComponent); 24 | let app = fixture.debugElement.componentInstance; 25 | expect(app.title).toEqual('app works!'); 26 | })); 27 | 28 | it('should render title in a h1 tag', async(() => { 29 | let fixture = TestBed.createComponent(AppComponent); 30 | fixture.detectChanges(); 31 | let compiled = fixture.debugElement.nativeElement; 32 | expect(compiled.querySelector('h1').textContent).toContain('app works!'); 33 | })); 34 | }); 35 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Sergey Akopkokhyants 2 | // This project is licensed under the terms of the MIT license. 3 | // https://github.com/akserg 4 | 5 | import { Component, OnDestroy } from '@angular/core'; 6 | import { Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router'; 7 | 8 | import { SlimLoadingBarService } from 'ng2-slim-loading-bar'; 9 | 10 | import { ToastCommunicationService } from './toast/toast-communication.service'; 11 | 12 | @Component({ 13 | selector: 'app-root', 14 | templateUrl: './app.component.html' 15 | }) 16 | export class AppComponent implements OnDestroy { 17 | private sub: any; 18 | // Position of Ng2ToastyComponent 19 | private toastyComponentPosition: string; 20 | 21 | constructor(private slimLoader: SlimLoadingBarService, private router: Router, 22 | private toastCommunicationService: ToastCommunicationService) { 23 | // We listen the position's changes 24 | this.toastCommunicationService.position$.subscribe(pos => this.toastyComponentPosition = pos); 25 | // Listen the navigation events to start or complete the slim bar loading 26 | this.sub = this.router.events.subscribe(event => { 27 | if (event instanceof NavigationStart) { 28 | this.slimLoader.start(); 29 | } else if ( event instanceof NavigationEnd || 30 | event instanceof NavigationCancel || 31 | event instanceof NavigationError) { 32 | this.slimLoader.complete(); 33 | } 34 | }, (error: any) => { 35 | this.slimLoader.complete(); 36 | }); 37 | } 38 | 39 | ngOnDestroy(): any { 40 | this.sub.unsubscribe(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Sergey Akopkokhyants 2 | // This project is licensed under the terms of the MIT license. 3 | // https://github.com/akserg 4 | 5 | import { NgModule } from '@angular/core'; 6 | import { BrowserModule } from '@angular/platform-browser'; 7 | import { FormsModule } from '@angular/forms'; 8 | import { LocationStrategy, HashLocationStrategy } from '@angular/common'; 9 | 10 | import { AppComponent } from './app.component'; 11 | 12 | import { ToastyModule } from 'ng2-toasty'; 13 | import { DndModule } from 'ng2-dnd'; 14 | import { SlimLoadingBarModule } from 'ng2-slim-loading-bar'; 15 | import { DemoDndModule } from './dnd/demo-dnd.module'; 16 | 17 | import { HomeComponent } from './home/home.component'; 18 | import { SlimComponent } from './slim/slim.component'; 19 | import { DndComponent } from './dnd/dnd.component'; 20 | import { ToastComponent, ToastCommunicationService } from './toast'; 21 | 22 | import { routing } from './app.routing'; 23 | 24 | @NgModule({ 25 | imports: [BrowserModule, FormsModule, routing, 26 | ToastyModule.forRoot(), DndModule.forRoot(), SlimLoadingBarModule.forRoot(), DemoDndModule], 27 | declarations: [AppComponent, HomeComponent, SlimComponent, DndComponent, ToastComponent], 28 | providers: [{ provide: LocationStrategy, useClass: HashLocationStrategy }, ToastCommunicationService], 29 | bootstrap: [AppComponent] 30 | }) 31 | export class AppModule { } 32 | -------------------------------------------------------------------------------- /src/app/app.routing.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Sergey Akopkokhyants 2 | // This project is licensed under the terms of the MIT license. 3 | // https://github.com/akserg 4 | 5 | import { ModuleWithProviders } from '@angular/core'; 6 | import { Routes, RouterModule } from '@angular/router'; 7 | 8 | import { HomeComponent } from './home/home.component'; 9 | import { SlimComponent } from './slim/slim.component'; 10 | import { DndComponent } from './dnd/dnd.component'; 11 | import { ToastComponent } from './toast/toast.component'; 12 | 13 | const appRoutes: Routes = [ 14 | {path: '', component: HomeComponent}, 15 | {path: 'toasty', component: ToastComponent}, 16 | {path: 'dnd', component: DndComponent}, 17 | {path: 'slim', component: SlimComponent} 18 | ]; 19 | 20 | export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); 21 | -------------------------------------------------------------------------------- /src/app/dnd/custom-data-dnd.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'custom-data-dnd', 5 | template: ` 6 |

Transfer custom data in Drag-and-Drop

7 |
8 |
9 |
10 |
Available to drag
11 |
12 |
13 |
14 |
Drag Me
15 |
{{transferData | json}}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Place to drop (Items:{{receivedData.length}})
24 |
25 |
{{data | json}}
26 |
27 |
28 |
29 |
` 30 | }) 31 | export class CustomDataDndComponent { 32 | transferData: Object = {id: 1, msg: 'Hello'}; 33 | receivedData: Array = []; 34 | 35 | transferDataSuccess($event: any) { 36 | this.receivedData.push($event); 37 | } 38 | } -------------------------------------------------------------------------------- /src/app/dnd/custom-function-dnd.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'custom-function-dnd', 5 | template: ` 6 |

Use a custom function to determine where dropping is allowed

7 |
8 |
9 |
10 |
Available to drag
11 |
12 |
13 |
dragData = 6
14 |
15 |
16 |
dragData = 10
17 |
18 |
19 |
dragData = 30
20 |
21 |
22 |
23 |
24 |
25 |
allowDropFunction(baseInteger: any): any {{ '{' }}
26 |   return (dragData: any) => dragData % baseInteger === 0;
27 | {{ '}' }}
28 |
29 |
30 |
31 |
32 | Multiples of 33 | 34 | only 35 |
36 |
37 |
dragData = {{item}}
38 |
39 |
40 |
41 |
42 |
43 |
44 | Multiples of 45 | 46 | only 47 |
48 |
49 |
dragData = {{item}}
50 |
51 |
52 |
53 |
54 |
55 |
56 | ` 57 | }) 58 | export class CustomFunctionDndComponent { 59 | box1Integer: number = 3; 60 | box2Integer: number = 10; 61 | 62 | box1Items: string[] = []; 63 | box2Items: string[] = []; 64 | 65 | allowDropFunction(baseInteger: number): any { 66 | return (dragData: any) => dragData % baseInteger === 0; 67 | } 68 | 69 | addTobox1Items($event: any) { 70 | this.box1Items.push($event.dragData); 71 | } 72 | 73 | addTobox2Items($event: any) { 74 | this.box2Items.push($event.dragData); 75 | } 76 | } -------------------------------------------------------------------------------- /src/app/dnd/demo-dnd.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Sergey Akopkokhyants 2 | // This project is licensed under the terms of the MIT license. 3 | // https://github.com/akserg 4 | 5 | import { NgModule } from '@angular/core'; 6 | import { BrowserModule } from '@angular/platform-browser'; 7 | import { FormsModule } from '@angular/forms'; 8 | 9 | import { DndModule } from 'ng2-dnd'; 10 | 11 | import { SimpleDndComponent } from './simple-dnd.component'; 12 | import { ZoneDndComponent } from './zone-dnd.component'; 13 | import { CustomDataDndComponent } from './custom-data-dnd.component'; 14 | import { CustomFunctionDndComponent } from './custom-function-dnd.component'; 15 | import { ShoppingBasketDndComponent } from './shopping-basket-dnd.component'; 16 | 17 | import { SimpleSortableComponent } from './simple-sortable.component'; 18 | import { MultiSortableComponent } from './multi-sortable.component'; 19 | import { RecycleMultiSortableComponent } from './recycle-multi-sortable.component'; 20 | import { EmbeddedSortableComponent} from './embedded-sortable.component'; 21 | import { SimpleSortableCopyComponent } from './simple-sortable-copy.component'; 22 | 23 | const dndComponents = [SimpleDndComponent, ZoneDndComponent, CustomDataDndComponent, CustomFunctionDndComponent, ShoppingBasketDndComponent]; 24 | const sortableComponents = [SimpleSortableComponent, MultiSortableComponent, RecycleMultiSortableComponent, EmbeddedSortableComponent, SimpleSortableCopyComponent]; 25 | 26 | @NgModule({ 27 | imports: [BrowserModule, FormsModule, DndModule.forRoot()], 28 | declarations: [...dndComponents, ...sortableComponents], 29 | exports: [...dndComponents, ...sortableComponents] 30 | }) 31 | export class DemoDndModule { } -------------------------------------------------------------------------------- /src/app/dnd/dnd.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
-------------------------------------------------------------------------------- /src/app/dnd/dnd.component.ts: -------------------------------------------------------------------------------- 1 | // // Copyright (C) 2016 Sergey Akopkokhyants 2 | // // This project is licensed under the terms of the MIT license. 3 | // // https://github.com/akserg 4 | 5 | import {Component, Injectable} from '@angular/core'; 6 | 7 | @Component({ 8 | selector: 'demo-dnd', 9 | templateUrl: './dnd.component.html' 10 | }) 11 | export class DndComponent {} 12 | -------------------------------------------------------------------------------- /src/app/dnd/embedded-sortable.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'embedded-sortable', 5 | template: ` 6 |

Move items between multi list sortable containers

7 |
8 |
9 | Drag Containers 10 |
11 |
14 |
16 |
17 | {{container.id}} - {{container.name}} 18 |
19 |
20 |
    21 |
  • {{widget.name}}
  • 24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Widgets
33 |
34 |
35 |
36 | {{widget.name}} 37 |
38 |
39 |
40 |
41 |
42 |
` 43 | }) 44 | export class EmbeddedSortableComponent { 45 | dragOperation: boolean = false; 46 | 47 | containers: Array = [ 48 | new Container(1, 'Container 1', [new Widget('1'), new Widget('2')]), 49 | new Container(2, 'Container 2', [new Widget('3'), new Widget('4')]), 50 | new Container(3, 'Container 3', [new Widget('5'), new Widget('6')]) 51 | ]; 52 | 53 | widgets: Array = []; 54 | addTo($event: any) { 55 | if ($event) { 56 | this.widgets.push($event.dragData); 57 | } 58 | } 59 | } 60 | 61 | class Container { 62 | constructor(public id: number, public name: string, public widgets: Array) {} 63 | } 64 | 65 | class Widget { 66 | constructor(public name: string) {} 67 | } -------------------------------------------------------------------------------- /src/app/dnd/multi-sortable.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'multi-sortable', 5 | template: ` 6 |

Multi list sortable

7 |
8 |
9 |
10 |
11 | Available boxers 12 |
13 |
14 |
    15 |
  • {{item}}
  • 16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | First Team 24 |
25 |
26 |
    27 |
  • {{item}}
  • 28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | Second Team 36 |
37 |
38 |
    39 |
  • {{item}}
  • 40 |
41 |
42 |
43 |
44 |
` 45 | }) 46 | export class MultiSortableComponent { 47 | listBoxers: Array = ['Sugar Ray Robinson', 'Muhammad Ali', 'George Foreman', 'Joe Frazier', 'Jake LaMotta', 'Joe Louis', 'Jack Dempsey', 'Rocky Marciano', 'Mike Tyson', 'Oscar De La Hoya']; 48 | listTeamOne: Array = []; 49 | listTeamTwo: Array = []; 50 | } -------------------------------------------------------------------------------- /src/app/dnd/recycle-multi-sortable.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'recycle-multi-sortable', 5 | template: ` 6 |

Simple sortable With Drop into recycle bin

7 |
8 |
9 |
10 |
11 | Favorite drinks 12 |
13 |
14 |
    15 |
  • {{item}}
  • 17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Recycle bin: Drag into me to delete it
25 |
26 |
27 |
28 | Recycled: {{listRecycled.toString()}} 29 |
30 |
31 |
` 32 | }) 33 | export class RecycleMultiSortableComponent { 34 | listOne: Array = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water']; 35 | listRecycled: Array = []; 36 | } -------------------------------------------------------------------------------- /src/app/dnd/shopping-basket-dnd.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'shoping-basket-dnd', 5 | template: ` 6 |

Drag-and-Drop - Shopping basket

7 |
8 | 9 |
10 |
11 |
Available products
12 |
13 |
15 |
16 |
{{product.name}} - \${{product.cost}}
(available: {{product.quantity}})
17 |
{{product.name}}
(NOT available)
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Shopping Basket
(to pay: \${{totalCost()}})
26 |
27 |
28 |
29 | {{product.name}}
(ordered: {{product.quantity}}
cost: \${{product.cost * product.quantity}}) 30 |
31 |
32 |
33 |
34 |
35 |
` 36 | }) 37 | export class ShoppingBasketDndComponent { 38 | availableProducts: Array = []; 39 | shoppingBasket: Array = []; 40 | 41 | constructor() { 42 | this.availableProducts.push(new Product('Blue Shoes', 3, 35)); 43 | this.availableProducts.push(new Product('Good Jacket', 1, 90)); 44 | this.availableProducts.push(new Product('Red Shirt', 5, 12)); 45 | this.availableProducts.push(new Product('Blue Jeans', 4, 60)); 46 | } 47 | 48 | orderedProduct($event: any) { 49 | let orderedProduct: Product = $event.dragData; 50 | orderedProduct.quantity--; 51 | } 52 | 53 | addToBasket($event: any) { 54 | let newProduct: Product = $event.dragData; 55 | for (let indx in this.shoppingBasket) { 56 | let product: Product = this.shoppingBasket[indx]; 57 | if (product.name === newProduct.name) { 58 | product.quantity++; 59 | return; 60 | } 61 | } 62 | this.shoppingBasket.push(new Product(newProduct.name, 1, newProduct.cost)); 63 | this.shoppingBasket.sort((a: Product, b: Product) => { 64 | return a.name.localeCompare(b.name); 65 | }); 66 | } 67 | 68 | totalCost(): number { 69 | let cost: number = 0; 70 | for (let indx in this.shoppingBasket) { 71 | let product: Product = this.shoppingBasket[indx]; 72 | cost += (product.cost * product.quantity); 73 | } 74 | return cost; 75 | } 76 | } 77 | 78 | class Product { 79 | constructor(public name: string, public quantity: number, public cost: number) {} 80 | } -------------------------------------------------------------------------------- /src/app/dnd/simple-dnd.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'simple-dnd', 5 | template: ` 6 |

Simple Drag-and-Drop

7 |
8 |
9 |
10 |
Available to drag
11 |
12 |
13 |
14 |
Drag Me
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
Place to drop
23 |
24 |
Item was dropped here
25 |
26 |
27 |
28 |
` 29 | }) 30 | export class SimpleDndComponent { 31 | simpleDrop: any = null; 32 | } -------------------------------------------------------------------------------- /src/app/dnd/simple-sortable-copy.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'simple-sortable-copy', 5 | template: ` 6 |

Simple sortable With Drop into something, without delete it

7 |
8 |
9 |
11 |
Source List
12 |
13 |
    14 |
  • {{source.name}}
  • 17 |
18 |
19 |
20 |
21 |
22 |
23 |
Target List
24 |
25 |
    26 |
  • 27 | {{target.name}} 28 |
  • 29 |
30 |
31 |
32 |
33 |
` 34 | }) 35 | export class SimpleSortableCopyComponent { 36 | 37 | sourceList: Widget[] = [ 38 | new Widget('1'), new Widget('2'), 39 | new Widget('3'), new Widget('4'), 40 | new Widget('5'), new Widget('6') 41 | ]; 42 | 43 | targetList: Widget[] = []; 44 | addTo($event: any) { 45 | this.targetList.push($event.dragData); 46 | } 47 | } 48 | 49 | class Widget { 50 | constructor(public name: string) {} 51 | } -------------------------------------------------------------------------------- /src/app/dnd/simple-sortable.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'simple-sortable', 5 | template: ` 6 |

Simple sortable

7 |
8 |
9 |
10 |
11 | Favorite drinks 12 |
13 |
14 |
    15 |
  • {{item}}
  • 16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | My prefences:
24 | {{i + 1}}) {{item}}
25 |
26 |
27 |
28 |
` 29 | }) 30 | export class SimpleSortableComponent { 31 | listOne: Array = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water']; 32 | } -------------------------------------------------------------------------------- /src/app/dnd/zone-dnd.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'zone-dnd', 5 | template: ` 6 |

Restricted Drag-and-Drop with zones

7 |
8 |
9 |
10 |
Available to drag
11 |
12 |
13 |
14 |
Drag Me
15 |
Zone 1 only
16 |
17 |
18 |
19 |
20 | 21 |
22 |
Available to drag
23 |
24 |
25 |
26 |
Drag Me
27 |
Zone 1 & 2
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Zone 1
36 |
37 |
Item was dropped here
38 |
39 |
40 |
41 |
42 |
43 |
Zone 2
44 |
45 |
Item was dropped here
46 |
47 |
48 |
49 |
` 50 | }) 51 | export class ZoneDndComponent { 52 | restrictedDrop1: any = null; 53 | restrictedDrop2: any = null; 54 | } -------------------------------------------------------------------------------- /src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to Demo

3 | There are features implemented on Angular 2: 4 | 9 |
-------------------------------------------------------------------------------- /src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | // // Copyright (C) 2016 Sergey Akopkokhyants 2 | // // This project is licensed under the terms of the MIT license. 3 | // // https://github.com/akserg 4 | 5 | import { Component } from '@angular/core'; 6 | 7 | @Component({ 8 | selector: 'demo-home', 9 | templateUrl: './home.component.html' 10 | }) 11 | export class HomeComponent { } 12 | -------------------------------------------------------------------------------- /src/app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app.component'; 2 | export * from './app.module'; 3 | export * from './home/home.component'; 4 | export * from './dnd/dnd.component'; 5 | export * from './slim/slim.component'; 6 | export * from './toast'; 7 | -------------------------------------------------------------------------------- /src/app/slim/slim.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |

9 | 10 |
11 |
12 |
13 |
14 |
-------------------------------------------------------------------------------- /src/app/slim/slim.component.ts: -------------------------------------------------------------------------------- 1 | // // Copyright (C) 2016 Sergey Akopkokhyants 2 | // // This project is licensed under the terms of the MIT license. 3 | // // https://github.com/akserg 4 | 5 | import {Component} from '@angular/core'; 6 | 7 | // import {Subject, Observable, Subscription} from 'rxjs/Rx'; 8 | 9 | import {SlimLoadingBarService} from 'ng2-slim-loading-bar'; 10 | 11 | @Component({ 12 | selector: 'demo-slim', 13 | templateUrl: './slim.component.html' 14 | }) 15 | export class SlimComponent { 16 | 17 | constructor(private slimLoader: SlimLoadingBarService) {} 18 | 19 | setProgres30() { 20 | this.slimLoader.progress = 30; 21 | } 22 | 23 | startProgress() { 24 | // We can listen when loading will be completed 25 | this.slimLoader.start(() => { 26 | console.log('Loading complete'); 27 | }); 28 | } 29 | 30 | completeProgress() { 31 | this.slimLoader.complete(); 32 | } 33 | 34 | stopProgress() { 35 | this.slimLoader.stop(); 36 | } 37 | 38 | resetProgress() { 39 | this.slimLoader.reset(); 40 | } 41 | 42 | incrementProgress() { 43 | this.slimLoader.progress++; 44 | } 45 | 46 | changeProgressTo4px() { 47 | this.slimLoader.height = '4px'; 48 | } 49 | 50 | changeProgressTo2px() { 51 | this.slimLoader.height = '2px'; 52 | } 53 | 54 | changeProgressToBlue() { 55 | this.slimLoader.color = 'blue'; 56 | } 57 | 58 | changeProgressToFirebrick() { 59 | this.slimLoader.color = 'firebrick'; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/app/toast/index.ts: -------------------------------------------------------------------------------- 1 | export { ToastComponent } from './toast.component'; 2 | export { ToastCommunicationService } from './toast-communication.service'; -------------------------------------------------------------------------------- /src/app/toast/toast-communication.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Subject } from 'rxjs/Subject'; 3 | 4 | /** 5 | * Service helps communicate between the ToastComponent and AppComponent. 6 | */ 7 | @Injectable() 8 | export class ToastCommunicationService { 9 | // Observable string sources 10 | private positionSource = new Subject(); 11 | 12 | // Observable string streams 13 | position$ = this.positionSource.asObservable(); 14 | 15 | setPosition(position) { 16 | this.positionSource.next(position); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/toast/toast.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Sergey Akopkokhyants 2 | // This project is licensed under the terms of the MIT license. 3 | // https://github.com/akserg 4 | 5 | import { Component } from '@angular/core'; 6 | 7 | import {Subject, Observable, Subscription} from 'rxjs/Rx'; 8 | 9 | import {ToastyService, ToastyConfig, ToastOptions, ToastData} from 'ng2-toasty'; 10 | 11 | import {ToastCommunicationService} from './toast-communication.service'; 12 | 13 | @Component({ 14 | selector: 'demo-toast', 15 | template: ` 16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 36 | 37 | 38 | 41 | 42 | 43 | 44 |
45 |
46 | 47 | 48 |
49 |
50 |
 51 | toastyService.{{ options.type }}({{ '{' }}
 52 |     title: "{{ options.title }}",
 53 |     msg: "{{ options.msg }}",
 54 |     showClose: {{ options.showClose }},
 55 |     timeout: {{ options.timeout || false }},
 56 |     theme: "{{ options.theme }}"
 57 | {{ '}' }});
 58 | 
 59 | toastyConfig({{ '{' }}
 60 |     position: "{{ position }}"
 61 | {{ '}' }});
 62 | 
 63 |                 
64 |
65 |
66 | 67 | 68 | 69 | 70 |
71 |
72 |
` 73 | }) 74 | export class ToastComponent { 75 | 76 | themes = [{ 77 | name: 'Default Theme', 78 | code: 'default' 79 | }, { 80 | name: 'Material Design', 81 | code: 'material' 82 | }, { 83 | name: 'Bootstrap 3', 84 | code: 'bootstrap' 85 | }]; 86 | 87 | types = [{ 88 | name: 'Default', 89 | code: 'default', 90 | }, { 91 | name: 'Info', 92 | code: 'info' 93 | }, { 94 | name: 'Success', 95 | code: 'success' 96 | }, { 97 | name: 'Wait', 98 | code: 'wait' 99 | }, { 100 | name: 'Error', 101 | code: 'error' 102 | }, { 103 | name: 'Warning', 104 | code: 'warning' 105 | }]; 106 | 107 | positions = [{ 108 | name: 'Top Left', 109 | code: 'top-left', 110 | }, { 111 | name: 'Top Center', 112 | code: 'top-center', 113 | }, { 114 | name: 'Top Right', 115 | code: 'top-right', 116 | }, { 117 | name: 'Bottom Left', 118 | code: 'bottom-left', 119 | }, { 120 | name: 'Bottom Center', 121 | code: 'bottom-center', 122 | }, { 123 | name: 'Bottom Right', 124 | code: 'bottom-right', 125 | }, { 126 | name: 'Center Center', 127 | code: 'center-center', 128 | }]; 129 | 130 | position: string = this.positions[5].code; 131 | 132 | options = { 133 | title: 'Toast It!', 134 | msg: 'Mmmm, tasties...', 135 | showClose: true, 136 | timeout: 5000, 137 | theme: this.themes[0].code, 138 | type: this.types[0].code 139 | }; 140 | 141 | getTitle(num: number): string { 142 | return 'Countdown: ' + num; 143 | } 144 | 145 | getMessage(num: number): string { 146 | return 'Seconds left: ' + num; 147 | } 148 | 149 | constructor(private toastyService: ToastyService, private toastCommunicationService: ToastCommunicationService) { } 150 | 151 | newToast() { 152 | let toastOptions: ToastOptions = { 153 | title: this.options.title, 154 | msg: this.options.msg, 155 | showClose: this.options.showClose, 156 | timeout: this.options.timeout, 157 | theme: this.options.theme, 158 | // position: this.options.position, 159 | onAdd: (toast: ToastData) => { 160 | console.log('Toast ' + toast.id + ' has been added!'); 161 | }, 162 | onRemove: function(toast: ToastData) { 163 | console.log('Toast ' + toast.id + ' has been removed!'); 164 | } 165 | }; 166 | 167 | switch (this.options.type) { 168 | case 'default': this.toastyService.default(toastOptions); break; 169 | case 'info': this.toastyService.info(toastOptions); break; 170 | case 'success': this.toastyService.success(toastOptions); break; 171 | case 'wait': this.toastyService.wait(toastOptions); break; 172 | case 'error': this.toastyService.error(toastOptions); break; 173 | case 'warning': this.toastyService.warning(toastOptions); break; 174 | } 175 | } 176 | 177 | newCountdownToast() { 178 | let interval = 1000; 179 | let seconds = this.options.timeout / 1000; 180 | let subscription: Subscription; 181 | 182 | let toastOptions: ToastOptions = { 183 | title: this.getTitle(seconds || 0), 184 | msg: this.getMessage(seconds || 0), 185 | showClose: this.options.showClose, 186 | timeout: this.options.timeout, 187 | theme: this.options.theme, 188 | onAdd: (toast: ToastData) => { 189 | console.log('Toast ' + toast.id + ' has been added!'); 190 | // Run the timer with 1 second iterval 191 | let observable = Observable.interval(interval).take(seconds); 192 | // Start listen seconds bit 193 | subscription = observable.subscribe((count: number) => { 194 | // Update title 195 | toast.title = this.getTitle(seconds - count - 1 || 0); 196 | // Update message 197 | toast.msg = this.getMessage(seconds - count - 1 || 0); 198 | }); 199 | 200 | }, 201 | onRemove: function(toast: ToastData) { 202 | console.log('Toast ' + toast.id + ' has been removed!'); 203 | // Stop listenning 204 | subscription.unsubscribe(); 205 | } 206 | }; 207 | 208 | switch (this.options.type) { 209 | case 'default': this.toastyService.default(toastOptions); break; 210 | case 'info': this.toastyService.info(toastOptions); break; 211 | case 'success': this.toastyService.success(toastOptions); break; 212 | case 'wait': this.toastyService.wait(toastOptions); break; 213 | case 'error': this.toastyService.error(toastOptions); break; 214 | case 'warning': this.toastyService.warning(toastOptions); break; 215 | } 216 | } 217 | 218 | clearToasties() { 219 | this.toastyService.clearAll(); 220 | } 221 | 222 | changePosition($event) { 223 | this.position = $event; 224 | // Update position of the Toasty Component 225 | this.toastCommunicationService.setPosition(this.position); 226 | } 227 | 228 | } 229 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akserg/ng2-webpack-demo/8e524bc87a41dae716a288306d76afda610fe1e7/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akserg/ng2-webpack-demo/8e524bc87a41dae716a288306d76afda610fe1e7/src/assets/.npmignore -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /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 | }; 9 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akserg/ng2-webpack-demo/8e524bc87a41dae716a288306d76afda610fe1e7/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ng2WebpackDemo 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | Loading... 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import './polyfills.ts'; 2 | 3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 4 | import { enableProdMode } from '@angular/core'; 5 | import { environment } from './environments/environment'; 6 | import { AppModule } from './app/app.module'; 7 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } 11 | 12 | platformBrowserDynamic().bootstrapModule(AppModule); 13 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | // This file includes polyfills needed by Angular 2 and is loaded before 2 | // the app. You can add your own extra polyfills to this file. 3 | import 'core-js/es6/symbol'; 4 | import 'core-js/es6/object'; 5 | import 'core-js/es6/function'; 6 | import 'core-js/es6/parse-int'; 7 | import 'core-js/es6/parse-float'; 8 | import 'core-js/es6/number'; 9 | import 'core-js/es6/math'; 10 | import 'core-js/es6/string'; 11 | import 'core-js/es6/date'; 12 | import 'core-js/es6/array'; 13 | import 'core-js/es6/regexp'; 14 | import 'core-js/es6/map'; 15 | import 'core-js/es6/set'; 16 | import 'core-js/es6/reflect'; 17 | 18 | import 'core-js/es7/reflect'; 19 | import 'zone.js/dist/zone'; 20 | -------------------------------------------------------------------------------- /src/skeleton.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Skeleton V2.0.4 3 | * Copyright 2014, Dave Gamache 4 | * www.getskeleton.com 5 | * Free to use under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 12/29/2014 8 | */ 9 | 10 | 11 | /* Table of contents 12 | –––––––––––––––––––––––––––––––––––––––––––––––––– 13 | - Grid 14 | - Base Styles 15 | - Typography 16 | - Links 17 | - Buttons 18 | - Forms 19 | - Lists 20 | - Code 21 | - Tables 22 | - Spacing 23 | - Utilities 24 | - Clearing 25 | - Media Queries 26 | */ 27 | 28 | 29 | /* Grid 30 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 31 | .container { 32 | position: relative; 33 | width: 100%; 34 | max-width: 960px; 35 | margin: 0 auto; 36 | padding: 0 20px; 37 | box-sizing: border-box; } 38 | .column, 39 | .columns { 40 | width: 100%; 41 | float: left; 42 | box-sizing: border-box; } 43 | 44 | /* For devices larger than 400px */ 45 | @media (min-width: 400px) { 46 | .container { 47 | width: 85%; 48 | padding: 0; } 49 | } 50 | 51 | /* For devices larger than 550px */ 52 | @media (min-width: 550px) { 53 | .container { 54 | width: 80%; } 55 | .column, 56 | .columns { 57 | margin-left: 4%; } 58 | .column:first-child, 59 | .columns:first-child { 60 | margin-left: 0; } 61 | 62 | .one.column, 63 | .one.columns { width: 4.66666666667%; } 64 | .two.columns { width: 13.3333333333%; } 65 | .three.columns { width: 22%; } 66 | .four.columns { width: 30.6666666667%; } 67 | .five.columns { width: 39.3333333333%; } 68 | .six.columns { width: 48%; } 69 | .seven.columns { width: 56.6666666667%; } 70 | .eight.columns { width: 65.3333333333%; } 71 | .nine.columns { width: 74.0%; } 72 | .ten.columns { width: 82.6666666667%; } 73 | .eleven.columns { width: 91.3333333333%; } 74 | .twelve.columns { width: 100%; margin-left: 0; } 75 | 76 | .one-third.column { width: 30.6666666667%; } 77 | .two-thirds.column { width: 65.3333333333%; } 78 | 79 | .one-half.column { width: 48%; } 80 | 81 | /* Offsets */ 82 | .offset-by-one.column, 83 | .offset-by-one.columns { margin-left: 8.66666666667%; } 84 | .offset-by-two.column, 85 | .offset-by-two.columns { margin-left: 17.3333333333%; } 86 | .offset-by-three.column, 87 | .offset-by-three.columns { margin-left: 26%; } 88 | .offset-by-four.column, 89 | .offset-by-four.columns { margin-left: 34.6666666667%; } 90 | .offset-by-five.column, 91 | .offset-by-five.columns { margin-left: 43.3333333333%; } 92 | .offset-by-six.column, 93 | .offset-by-six.columns { margin-left: 52%; } 94 | .offset-by-seven.column, 95 | .offset-by-seven.columns { margin-left: 60.6666666667%; } 96 | .offset-by-eight.column, 97 | .offset-by-eight.columns { margin-left: 69.3333333333%; } 98 | .offset-by-nine.column, 99 | .offset-by-nine.columns { margin-left: 78.0%; } 100 | .offset-by-ten.column, 101 | .offset-by-ten.columns { margin-left: 86.6666666667%; } 102 | .offset-by-eleven.column, 103 | .offset-by-eleven.columns { margin-left: 95.3333333333%; } 104 | 105 | .offset-by-one-third.column, 106 | .offset-by-one-third.columns { margin-left: 34.6666666667%; } 107 | .offset-by-two-thirds.column, 108 | .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } 109 | 110 | .offset-by-one-half.column, 111 | .offset-by-one-half.columns { margin-left: 52%; } 112 | 113 | } 114 | 115 | 116 | /* Base Styles 117 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 118 | /* NOTE 119 | html is set to 62.5% so that all the REM measurements throughout Skeleton 120 | are based on 10px sizing. So basically 1.5rem = 15px :) */ 121 | html { 122 | font-size: 62.5%; } 123 | body { 124 | font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ 125 | line-height: 1.6; 126 | font-weight: 400; 127 | font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; 128 | color: #222; } 129 | 130 | 131 | /* Typography 132 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 133 | h1, h2, h3, h4, h5, h6 { 134 | margin-top: 0; 135 | margin-bottom: 2rem; 136 | font-weight: 300; } 137 | h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} 138 | h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } 139 | h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } 140 | h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } 141 | h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } 142 | h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } 143 | 144 | /* Larger than phablet */ 145 | @media (min-width: 550px) { 146 | h1 { font-size: 5.0rem; } 147 | h2 { font-size: 4.2rem; } 148 | h3 { font-size: 3.6rem; } 149 | h4 { font-size: 3.0rem; } 150 | h5 { font-size: 2.4rem; } 151 | h6 { font-size: 1.5rem; } 152 | } 153 | 154 | p { 155 | margin-top: 0; } 156 | 157 | 158 | /* Links 159 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 160 | a { 161 | color: #1EAEDB; } 162 | a:hover { 163 | color: #0FA0CE; } 164 | 165 | 166 | /* Buttons 167 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 168 | .button, 169 | button, 170 | input[type="submit"], 171 | input[type="reset"], 172 | input[type="button"] { 173 | display: inline-block; 174 | height: 38px; 175 | padding: 0 30px; 176 | color: #555; 177 | text-align: center; 178 | font-size: 11px; 179 | font-weight: 600; 180 | line-height: 38px; 181 | letter-spacing: .1rem; 182 | text-transform: uppercase; 183 | text-decoration: none; 184 | white-space: nowrap; 185 | background-color: transparent; 186 | border-radius: 4px; 187 | border: 1px solid #bbb; 188 | cursor: pointer; 189 | box-sizing: border-box; } 190 | .button:hover, 191 | button:hover, 192 | input[type="submit"]:hover, 193 | input[type="reset"]:hover, 194 | input[type="button"]:hover, 195 | .button:focus, 196 | button:focus, 197 | input[type="submit"]:focus, 198 | input[type="reset"]:focus, 199 | input[type="button"]:focus { 200 | color: #333; 201 | border-color: #888; 202 | outline: 0; } 203 | .button.button-primary, 204 | button.button-primary, 205 | input[type="submit"].button-primary, 206 | input[type="reset"].button-primary, 207 | input[type="button"].button-primary { 208 | color: #FFF; 209 | background-color: #33C3F0; 210 | border-color: #33C3F0; } 211 | .button.button-primary:hover, 212 | button.button-primary:hover, 213 | input[type="submit"].button-primary:hover, 214 | input[type="reset"].button-primary:hover, 215 | input[type="button"].button-primary:hover, 216 | .button.button-primary:focus, 217 | button.button-primary:focus, 218 | input[type="submit"].button-primary:focus, 219 | input[type="reset"].button-primary:focus, 220 | input[type="button"].button-primary:focus { 221 | color: #FFF; 222 | background-color: #1EAEDB; 223 | border-color: #1EAEDB; } 224 | 225 | 226 | /* Forms 227 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 228 | input[type="email"], 229 | input[type="number"], 230 | input[type="search"], 231 | input[type="text"], 232 | input[type="tel"], 233 | input[type="url"], 234 | input[type="password"], 235 | textarea, 236 | select { 237 | height: 38px; 238 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ 239 | background-color: #fff; 240 | border: 1px solid #D1D1D1; 241 | border-radius: 4px; 242 | box-shadow: none; 243 | box-sizing: border-box; } 244 | /* Removes awkward default styles on some inputs for iOS */ 245 | input[type="email"], 246 | input[type="number"], 247 | input[type="search"], 248 | input[type="text"], 249 | input[type="tel"], 250 | input[type="url"], 251 | input[type="password"], 252 | textarea { 253 | -webkit-appearance: none; 254 | -moz-appearance: none; 255 | appearance: none; } 256 | textarea { 257 | min-height: 65px; 258 | padding-top: 6px; 259 | padding-bottom: 6px; } 260 | input[type="email"]:focus, 261 | input[type="number"]:focus, 262 | input[type="search"]:focus, 263 | input[type="text"]:focus, 264 | input[type="tel"]:focus, 265 | input[type="url"]:focus, 266 | input[type="password"]:focus, 267 | textarea:focus, 268 | select:focus { 269 | border: 1px solid #33C3F0; 270 | outline: 0; } 271 | label, 272 | legend { 273 | display: block; 274 | margin-bottom: .5rem; 275 | font-weight: 600; } 276 | fieldset { 277 | padding: 0; 278 | border-width: 0; } 279 | input[type="checkbox"], 280 | input[type="radio"] { 281 | display: inline; } 282 | label > .label-body { 283 | display: inline-block; 284 | margin-left: .5rem; 285 | font-weight: normal; } 286 | 287 | 288 | /* Lists 289 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 290 | ul { 291 | list-style: circle inside; } 292 | ol { 293 | list-style: decimal inside; } 294 | ol, ul { 295 | padding-left: 0; 296 | margin-top: 0; } 297 | ul ul, 298 | ul ol, 299 | ol ol, 300 | ol ul { 301 | margin: 1.5rem 0 1.5rem 3rem; 302 | font-size: 90%; } 303 | li { 304 | margin-bottom: 1rem; } 305 | 306 | 307 | /* Code 308 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 309 | code { 310 | padding: .2rem .5rem; 311 | margin: 0 .2rem; 312 | font-size: 90%; 313 | white-space: nowrap; 314 | background: #F1F1F1; 315 | border: 1px solid #E1E1E1; 316 | border-radius: 4px; } 317 | pre > code { 318 | display: block; 319 | padding: 1rem 1.5rem; 320 | white-space: pre; } 321 | 322 | 323 | /* Tables 324 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 325 | th, 326 | td { 327 | padding: 12px 15px; 328 | text-align: left; 329 | border-bottom: 1px solid #E1E1E1; } 330 | th:first-child, 331 | td:first-child { 332 | padding-left: 0; } 333 | th:last-child, 334 | td:last-child { 335 | padding-right: 0; } 336 | 337 | 338 | /* Spacing 339 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 340 | button, 341 | .button { 342 | margin-bottom: 1rem; } 343 | input, 344 | textarea, 345 | select, 346 | fieldset { 347 | margin-bottom: 1.5rem; } 348 | pre, 349 | blockquote, 350 | dl, 351 | figure, 352 | table, 353 | p, 354 | ul, 355 | ol, 356 | form { 357 | margin-bottom: 2.5rem; } 358 | 359 | 360 | /* Utilities 361 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 362 | .u-full-width { 363 | width: 100%; 364 | box-sizing: border-box; } 365 | .u-max-full-width { 366 | max-width: 100%; 367 | box-sizing: border-box; } 368 | .u-pull-right { 369 | float: right; } 370 | .u-pull-left { 371 | float: left; } 372 | 373 | 374 | /* Misc 375 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 376 | hr { 377 | margin-top: 3rem; 378 | margin-bottom: 3.5rem; 379 | border-width: 0; 380 | border-top: 1px solid #E1E1E1; } 381 | 382 | 383 | /* Clearing 384 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 385 | 386 | /* Self Clearing Goodness */ 387 | .container:after, 388 | .row:after, 389 | .u-cf { 390 | content: ""; 391 | display: table; 392 | clear: both; } 393 | 394 | 395 | /* Media Queries 396 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 397 | /* 398 | Note: The best way to structure the use of media queries is to create the queries 399 | near the relevant code. For example, if you wanted to change the styles for buttons 400 | on small devices, paste the mobile query code up in the buttons section and style it 401 | there. 402 | */ 403 | 404 | 405 | /* Larger than mobile */ 406 | @media (min-width: 400px) {} 407 | 408 | /* Larger than phablet (also point when grid becomes active) */ 409 | @media (min-width: 550px) {} 410 | 411 | /* Larger than tablet */ 412 | @media (min-width: 750px) {} 413 | 414 | /* Larger than desktop */ 415 | @media (min-width: 1000px) {} 416 | 417 | /* Larger than Desktop HD */ 418 | @media (min-width: 1200px) {} -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | header { 7 | border-bottom: 1px solid #eee; 8 | height: 6.5rem; 9 | } 10 | 11 | .navbar-list { 12 | list-style: none; 13 | margin-bottom: 0; 14 | } 15 | 16 | .navbar-item { 17 | margin-bottom: 0; 18 | position: relative; 19 | } 20 | 21 | .navbar-link { 22 | text-transform: uppercase; 23 | font-size: 11px; 24 | font-weight: 600; 25 | letter-spacing: .2rem; 26 | margin-right: 35px; 27 | text-decoration: none; 28 | line-height: 6.5rem; 29 | color: #222; 30 | } 31 | 32 | small { 33 | font-size: 6px; 34 | opacity: .2; 35 | } 36 | 37 | code { 38 | word-break: break-word; 39 | } 40 | 41 | @media (max-width: 400px) { 42 | header { 43 | display: none; 44 | } 45 | } -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | import './polyfills.ts'; 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 var __karma__: any; 17 | declare var 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 | let 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/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "", 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "lib": ["es6", "dom"], 8 | "mapRoot": "./", 9 | "module": "es6", 10 | "moduleResolution": "node", 11 | "outDir": "../dist/out-tsc", 12 | "sourceMap": true, 13 | "target": "es5", 14 | "typeRoots": [ 15 | "../node_modules/@types" 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | // Typings reference file, see links for more information 2 | // https://github.com/typings/typings 3 | // https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html 4 | 5 | declare var System: any; 6 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "class-name": true, 7 | "comment-format": [ 8 | true, 9 | "check-space" 10 | ], 11 | "curly": true, 12 | "eofline": true, 13 | "forin": true, 14 | "indent": [ 15 | true, 16 | "spaces" 17 | ], 18 | "label-position": true, 19 | "max-line-length": [ 20 | true, 21 | 140 22 | ], 23 | "member-access": false, 24 | "member-ordering": [ 25 | true, 26 | "static-before-instance", 27 | "variables-before-functions" 28 | ], 29 | "no-arg": true, 30 | "no-bitwise": true, 31 | "no-console": [ 32 | true, 33 | "debug", 34 | "info", 35 | "time", 36 | "timeEnd", 37 | "trace" 38 | ], 39 | "no-construct": true, 40 | "no-debugger": true, 41 | "no-duplicate-variable": true, 42 | "no-empty": false, 43 | "no-eval": true, 44 | "no-inferrable-types": true, 45 | "no-shadowed-variable": true, 46 | "no-string-literal": false, 47 | "no-switch-case-fall-through": true, 48 | "no-trailing-whitespace": true, 49 | "no-unused-expression": true, 50 | "no-use-before-declare": true, 51 | "no-var-keyword": true, 52 | "object-literal-sort-keys": false, 53 | "one-line": [ 54 | true, 55 | "check-open-brace", 56 | "check-catch", 57 | "check-else", 58 | "check-whitespace" 59 | ], 60 | "quotemark": [ 61 | true, 62 | "single" 63 | ], 64 | "radix": true, 65 | "semicolon": [ 66 | "always" 67 | ], 68 | "triple-equals": [ 69 | true, 70 | "allow-null-check" 71 | ], 72 | "typedef-whitespace": [ 73 | true, 74 | { 75 | "call-signature": "nospace", 76 | "index-signature": "nospace", 77 | "parameter": "nospace", 78 | "property-declaration": "nospace", 79 | "variable-declaration": "nospace" 80 | } 81 | ], 82 | "variable-name": false, 83 | "whitespace": [ 84 | true, 85 | "check-branch", 86 | "check-decl", 87 | "check-operator", 88 | "check-separator", 89 | "check-type" 90 | ], 91 | 92 | "directive-selector": [true, "attribute", "app", "camelCase"], 93 | "component-selector": [true, "element", "app", "kebab-case"], 94 | "use-input-property-decorator": true, 95 | "use-output-property-decorator": true, 96 | "use-host-property-decorator": true, 97 | "no-input-rename": true, 98 | "no-output-rename": true, 99 | "use-life-cycle-interface": true, 100 | "use-pipe-transform-interface": true, 101 | "component-class-suffix": true, 102 | "directive-class-suffix": true, 103 | "no-access-missing-member": true, 104 | "templates-use-public": true, 105 | "invoke-injectable": true 106 | } 107 | } 108 | --------------------------------------------------------------------------------