├── public
└── .npmignore
├── src
├── app
│ ├── shared
│ │ └── index.ts
│ ├── +snaps
│ │ ├── shared
│ │ │ └── index.ts
│ │ ├── +list
│ │ │ ├── shared
│ │ │ │ └── index.ts
│ │ │ ├── list.component.css
│ │ │ ├── index.ts
│ │ │ ├── list.component.html
│ │ │ ├── list.component.spec.ts
│ │ │ └── list.component.ts
│ │ ├── +post
│ │ │ ├── shared
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── post.component.ts
│ │ │ ├── post.component.css
│ │ │ ├── post.component.spec.ts
│ │ │ └── post.component.html
│ │ ├── snaps.component.css
│ │ ├── snaps.component.html
│ │ ├── index.ts
│ │ ├── snaps.component.ts
│ │ └── snaps.component.spec.ts
│ ├── progressive.component.css
│ ├── index.ts
│ ├── environment.ts
│ ├── dribbble.service.spec.ts
│ ├── progressive.component.spec.ts
│ ├── dribbble.service.ts
│ └── progressive.component.ts
├── typings.d.ts
├── favicon.ico
├── icons
│ ├── icon.png
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── mstile-70x70.png
│ ├── apple-touch-icon.png
│ ├── mstile-144x144.png
│ ├── mstile-150x150.png
│ ├── mstile-310x150.png
│ ├── mstile-310x310.png
│ ├── android-chrome-36x36.png
│ ├── android-chrome-48x48.png
│ ├── android-chrome-72x72.png
│ ├── android-chrome-96x96.png
│ ├── android-chrome-144x144.png
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon-57x57.png
│ ├── apple-touch-icon-60x60.png
│ ├── apple-touch-icon-72x72.png
│ ├── apple-touch-icon-76x76.png
│ ├── apple-touch-icon-114x114.png
│ ├── apple-touch-icon-120x120.png
│ ├── apple-touch-icon-144x144.png
│ ├── apple-touch-icon-152x152.png
│ ├── apple-touch-icon-180x180.png
│ ├── apple-touch-icon-precomposed.png
│ ├── ic_menu_24px.svg
│ ├── ic_chat_bubble_black_24px.svg
│ ├── ic_favorite_black_24px.svg
│ ├── ic_visibility_black_24px.svg
│ └── safari-pinned-tab.svg
├── system-import.js
├── tsconfig.json
├── main.ts
├── manifest.webapp
├── main-app-shell.ts
├── index.html
├── system-config.ts
└── styles
│ └── app.css
├── e2e
├── typings.d.ts
├── app.po.ts
├── app.e2e.ts
└── tsconfig.json
├── config
├── environment.dev.ts
├── environment.prod.ts
├── environment.js
├── protractor.conf.js
├── karma-test-shim.js
└── karma.conf.js
├── .clang-format
├── .editorconfig
├── typings.json
├── .gitignore
├── angular-cli-build.js
├── angular-cli.json
├── README.md
├── tslint.json
├── package.json
└── app.yaml
/public/.npmignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/shared/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/+snaps/shared/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/progressive.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/+snaps/+list/shared/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/+snaps/+post/shared/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/+snaps/snaps.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/+snaps/+list/list.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/e2e/typings.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/app/+snaps/snaps.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 |
--------------------------------------------------------------------------------
/src/app/+snaps/+list/index.ts:
--------------------------------------------------------------------------------
1 | export { ListComponent } from './list.component';
2 |
--------------------------------------------------------------------------------
/src/app/+snaps/+post/index.ts:
--------------------------------------------------------------------------------
1 | export { PostComponent } from './post.component';
2 |
--------------------------------------------------------------------------------
/src/app/+snaps/index.ts:
--------------------------------------------------------------------------------
1 | export { SnapsComponent } from './snaps.component';
2 |
--------------------------------------------------------------------------------
/config/environment.dev.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: false
3 | };
4 |
--------------------------------------------------------------------------------
/config/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | Language: JavaScript
2 | BasedOnStyle: Google
3 | ColumnLimit: 100
4 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/src/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/icon.png
--------------------------------------------------------------------------------
/src/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/favicon.ico
--------------------------------------------------------------------------------
/src/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/src/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/src/icons/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/favicon-96x96.png
--------------------------------------------------------------------------------
/src/icons/mstile-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/mstile-70x70.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/src/icons/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/mstile-144x144.png
--------------------------------------------------------------------------------
/src/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/src/icons/mstile-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/mstile-310x150.png
--------------------------------------------------------------------------------
/src/icons/mstile-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/mstile-310x310.png
--------------------------------------------------------------------------------
/src/app/index.ts:
--------------------------------------------------------------------------------
1 | export {environment} from './environment';
2 | export {ProgressiveAppComponent} from './progressive.component';
3 |
--------------------------------------------------------------------------------
/src/icons/android-chrome-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-36x36.png
--------------------------------------------------------------------------------
/src/icons/android-chrome-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-48x48.png
--------------------------------------------------------------------------------
/src/icons/android-chrome-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-72x72.png
--------------------------------------------------------------------------------
/src/icons/android-chrome-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-96x96.png
--------------------------------------------------------------------------------
/src/icons/android-chrome-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-144x144.png
--------------------------------------------------------------------------------
/src/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/src/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/src/system-import.js:
--------------------------------------------------------------------------------
1 | System.import('system-config.js').then(function () {
2 | System.import('main');
3 | }).catch(console.error.bind(console));
--------------------------------------------------------------------------------
/src/icons/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/addyosmani/angular2-dribbble-pwa/HEAD/src/icons/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | return {
5 | environment: environment,
6 | baseURL: '/',
7 | locationType: 'auto'
8 | };
9 | };
10 |
11 |
--------------------------------------------------------------------------------
/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | export class ProgressivePage {
2 | navigateTo() {
3 | return browser.get('/');
4 | }
5 |
6 | getParagraphText() {
7 | return element(by.css('progressive-app h1')).getText();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/icons/ic_menu_24px.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/icons/ic_chat_bubble_black_24px.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/environment.ts:
--------------------------------------------------------------------------------
1 | // The file for the current environment will overwrite this one during build
2 | // Different environments can be found in config/environment.{dev|prod}.ts
3 | // The build system defaults to the dev environment
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | max_line_length = 0
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/src/icons/ic_favorite_black_24px.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/e2e/app.e2e.ts:
--------------------------------------------------------------------------------
1 | import { ProgressivePage } from './app.po';
2 |
3 | describe('progressive App', function() {
4 | let page: ProgressivePage;
5 |
6 | beforeEach(() => {
7 | page = new ProgressivePage();
8 | });
9 |
10 | it('should display message saying app works', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('progressive works!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/icons/ic_visibility_black_24px.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "declaration": false,
5 | "emitDecoratorMetadata": true,
6 | "experimentalDecorators": true,
7 | "mapRoot": "",
8 | "module": "commonjs",
9 | "moduleResolution": "node",
10 | "noEmitOnError": true,
11 | "noImplicitAny": false,
12 | "rootDir": ".",
13 | "sourceMap": true,
14 | "sourceRoot": "/",
15 | "target": "es5"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/typings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ambientDevDependencies": {
3 | "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459",
4 | "jasmine": "registry:dt/jasmine#2.2.0+20160412134438",
5 | "selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654"
6 | },
7 | "ambientDependencies": {
8 | "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654",
9 | "node": "registry:dt/node#4.0.0+20160509154515"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/dribbble.service.spec.ts:
--------------------------------------------------------------------------------
1 | import {
2 | beforeEachProviders,
3 | it,
4 | describe,
5 | expect,
6 | inject
7 | } from '@angular/core/testing';
8 | import { DribbbleService } from './dribbble.service';
9 |
10 | describe('Dribbble Service', () => {
11 | beforeEachProviders(() => [DribbbleService]);
12 |
13 | it('should ...',
14 | inject([DribbbleService], (service: DribbbleService) => {
15 | expect(service).toBeTruthy();
16 | }));
17 | });
18 |
--------------------------------------------------------------------------------
/.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 | /bower_components
10 |
11 | # IDEs and editors
12 | /.idea
13 |
14 | # misc
15 | /.sass-cache
16 | /connect.lock
17 | /coverage/*
18 | /libpeerconnection.log
19 | npm-debug.log
20 | testem.log
21 | /typings
22 |
23 | # e2e
24 | /e2e/*.js
25 | /e2e/*.map
26 |
27 | #System Files
28 | .DS_Store
29 | Thumbs.db
30 |
--------------------------------------------------------------------------------
/src/app/progressive.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {
2 | beforeEachProviders,
3 | describe,
4 | expect,
5 | it,
6 | inject
7 | } from '@angular/core/testing';
8 | import { ProgressiveAppComponent } from '../app/progressive.component';
9 |
10 | beforeEachProviders(() => [ProgressiveAppComponent]);
11 |
12 | describe('App: Progressive', () => {
13 | it('should create the app',
14 | inject([ProgressiveAppComponent], (app: ProgressiveAppComponent) => {
15 | expect(app).toBeTruthy();
16 | }));
17 | });
18 |
--------------------------------------------------------------------------------
/angular-cli-build.js:
--------------------------------------------------------------------------------
1 | /* global require, module */
2 |
3 | var Angular2App = require('angular-cli/lib/broccoli/angular2-app');
4 |
5 | module.exports = function(defaults) {
6 | return new Angular2App(defaults, {
7 | vendorNpmFiles: [
8 | 'systemjs/dist/system-polyfills.js',
9 | 'systemjs/dist/system.src.js',
10 | 'zone.js/dist/*.js',
11 | 'es6-shim/es6-shim.js',
12 | 'reflect-metadata/*.js',
13 | 'rxjs/**/*.js',
14 | '@angular/**/*.js',
15 | '@angular2-material/**/*.+(js|css|map|svg)'
16 | ]
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/src/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "declaration": false,
5 | "emitDecoratorMetadata": true,
6 | "experimentalDecorators": true,
7 | "mapRoot": "",
8 | "module": "commonjs",
9 | "moduleResolution": "node",
10 | "noEmitOnError": true,
11 | "noImplicitAny": false,
12 | "outDir": "../dist/",
13 | "rootDir": ".",
14 | "sourceMap": true,
15 | "target": "es5",
16 | "inlineSources": true
17 | },
18 |
19 | "files": [
20 | "main.ts",
21 | "main-app-shell.ts",
22 | "typings.d.ts"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/angular-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "project": {
3 | "version": "1.0.0-beta.2-mobile",
4 | "name": "progressive"
5 | },
6 | "apps": [
7 | {
8 | "main": "src/main.ts",
9 | "tsconfig": "src/tsconfig.json",
10 | "mobile": true
11 | }
12 | ],
13 | "addons": [],
14 | "packages": [],
15 | "e2e": {
16 | "protractor": {
17 | "config": "config/protractor.conf.js"
18 | }
19 | },
20 | "test": {
21 | "karma": {
22 | "config": "config/karma.conf.js"
23 | }
24 | },
25 | "defaults": {
26 | "prefix": "app",
27 | "sourceDir": "src"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/dribbble.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {JSONP_PROVIDERS, Jsonp} from '@angular/http'
3 |
4 | @Injectable()
5 | export class DribbbleService {
6 | api: string = 'https://api.dribbble.com/v1/';
7 | token: string = 'bc0239a39745e8604bb996d5ae6cd73ca605d4a0b448de4ab3b21b31fd610966';
8 | constructor(public jsonp:Jsonp) {}
9 | getPosts(page){
10 | return this.jsonp.get(this.api + '/shots?page='+ page +'&access_token='+this.token+'&callback=JSONP_CALLBACK');
11 | }
12 | getPost(id){
13 | return this.jsonp.get(this.api + '/shots/'+id+'?access_token='+this.token+'&callback=JSONP_CALLBACK');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/+snaps/+post/post.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { DribbbleService } from '../../dribbble.service';
3 | import { RouteParams } from '@angular/router-deprecated';
4 |
5 | @Component({
6 | moduleId: module.id,
7 | selector: 'app-post',
8 | templateUrl: 'post.component.html',
9 | styleUrls: ['post.component.css']
10 | })
11 | export class PostComponent implements OnInit {
12 | post;
13 | constructor(private dl:DribbbleService, private rp:RouteParams){}
14 |
15 | ngOnInit() {
16 | this.dl.getPost(this.rp.get('id')).subscribe(res => {
17 | this.post = res.json().data;
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/+snaps/snaps.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { ROUTER_DIRECTIVES, RouteConfig, CanDeactivate, ComponentInstruction } from '@angular/router-deprecated';
3 | import { PostComponent } from './+post';
4 | import { DribbbleService } from '../dribbble.service';
5 | import { ListComponent } from './+list';
6 |
7 | @Component({
8 | moduleId: module.id,
9 | selector: 'app-snaps',
10 | templateUrl: 'snaps.component.html',
11 | styleUrls: ['snaps.component.css'],
12 | directives: [ROUTER_DIRECTIVES]
13 | })
14 | @RouteConfig([
15 | {path: '/:id', component: PostComponent, name: 'Post'},
16 | {path: 'list', component: ListComponent, useAsDefault: true}
17 | ])
18 | export class SnapsComponent {}
19 |
20 |
--------------------------------------------------------------------------------
/config/protractor.conf.js:
--------------------------------------------------------------------------------
1 | /*global jasmine */
2 | var SpecReporter = require('jasmine-spec-reporter');
3 |
4 | exports.config = {
5 | allScriptsTimeout: 11000,
6 | specs: [
7 | '../e2e/**/*.e2e.ts'
8 | ],
9 | capabilities: {
10 | 'browserName': 'chrome'
11 | },
12 | directConnect: true,
13 | baseUrl: 'http://localhost:4200/',
14 | framework: 'jasmine',
15 | jasmineNodeOpts: {
16 | showColors: true,
17 | defaultTimeoutInterval: 30000,
18 | print: function() {}
19 | },
20 | useAllAngular2AppRoots: true,
21 | beforeLaunch: function() {
22 | require('ts-node').register({
23 | project: 'e2e'
24 | });
25 | },
26 | onPrepare: function() {
27 | jasmine.getEnv().addReporter(new SpecReporter());
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { bootstrap } from '@angular/platform-browser-dynamic';
2 | import { enableProdMode } from '@angular/core';
3 | import { ProgressiveAppComponent, environment } from './app/';
4 | import { APP_SHELL_RUNTIME_PROVIDERS } from '@angular/app-shell';
5 |
6 | import { provide } from '@angular/core';
7 | import { Http, HTTP_PROVIDERS, Jsonp, JSONP_PROVIDERS } from '@angular/http'
8 | import { ROUTER_PROVIDERS } from '@angular/router-deprecated'
9 |
10 | import {
11 | PlatformLocation,
12 | Location,
13 | LocationStrategy,
14 | HashLocationStrategy,
15 | PathLocationStrategy,
16 | APP_BASE_HREF}
17 | from '@angular/common';
18 |
19 | import { DribbbleService } from './app/dribbble.service';
20 |
21 | if (environment.production) {
22 | enableProdMode();
23 | }
24 |
25 | bootstrap(ProgressiveAppComponent, [
26 | APP_SHELL_RUNTIME_PROVIDERS,
27 | JSONP_PROVIDERS,
28 | ROUTER_PROVIDERS,
29 | provide(APP_BASE_HREF, {useValue: '/'}),
30 | DribbbleService]);
31 |
--------------------------------------------------------------------------------
/src/manifest.webapp:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Berry",
3 | "short_name": "Berry",
4 | "icons": [
5 | {
6 | "src": "icons/android-chrome-36x36.png",
7 | "sizes": "36x36",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "icons/android-chrome-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "icons/android-chrome-72x72.png",
17 | "sizes": "72x72",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "icons/android-chrome-96x96.png",
22 | "sizes": "96x96",
23 | "type": "image/png"
24 | },
25 | {
26 | "src": "icons/android-chrome-144x144.png",
27 | "sizes": "144x144",
28 | "type": "image/png"
29 | },
30 | {
31 | "src": "icons/android-chrome-192x192.png",
32 | "sizes": "192x192",
33 | "type": "image/png"
34 | },
35 | {
36 | "src": "icons/android-chrome-512x512.png",
37 | "sizes": "512x512",
38 | "type": "image/png"
39 | }
40 | ],
41 | "theme_color": "#673AB7",
42 | "background_color": "#512DA8",
43 | "start_url": "/index.html",
44 | "display": "standalone",
45 | "orientation": "portrait"
46 | }
47 |
--------------------------------------------------------------------------------
/src/app/+snaps/+list/list.component.html:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/app/+snaps/+post/post.component.css:
--------------------------------------------------------------------------------
1 | .post-list-item .post__info--preview {
2 | position: relative;
3 | background: #fff;
4 | z-index: 10;
5 | -webkit-transition: all 100ms ease;
6 | transition: all 100ms ease;
7 | border-radius: 0 0 4px 4px;
8 | top: 0;
9 | }
10 |
11 | .post-preview__details {
12 | position: relative;
13 | min-height: 55px;
14 | }
15 |
16 | .clearfix:before, .clearfix:after {
17 | content: " ";
18 | display: table;
19 | }
20 |
21 | .post-maker {
22 | display: inline-block;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | .avatar__wrapper {
28 | position: relative;
29 | display: block;
30 | }
31 |
32 | .avatar__wrapper .avatar {
33 | display: block;
34 | border-radius: 50%;
35 | }
36 |
37 | .post-preview__details a {
38 | color: rgba(0,0,0,0.87);
39 | font-weight: 400;
40 | }
41 |
42 | .post-preview__details h2 {
43 | margin: 0;
44 | font-size: 15px;
45 | line-height: 20px;
46 | padding-right: 5px;
47 | font-weight: 700;
48 | color: rgba(0,0,0,0.87);
49 | }
50 |
51 | .shot_image {
52 | width: 100%;
53 | }
54 |
55 | .shot_description {
56 | padding: 14px;
57 | }
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular2-dribbble-pwa
2 |
3 | This is a POC of a [Dribbble](https://dribbble.com) API client built using Angular 2 and Angular Mobile Toolkit. [Live demo](https://berry-app.appspot.com).
4 |
5 | Note: Due to the early and changing nature of a lot of the tooling in this space (toolkit, universal and so forth) it is possible that building this app from source will not always work until we lock in our dependency versions. We hope to do so once toolkit and universal are a little more stable, but are sharing this source in case it is useful for learning purposes.
6 |
7 | ### Setup
8 |
9 | Clone or download the repos, then `cd` into the project directory and:
10 |
11 | ```
12 | $ npm install -g angular-cli && npm install && typings install
13 | ```
14 |
15 | Once this is done you should be able to `ng serve` to serve up the application or `ng serve --prod` to serve with Service Worker switched on. `ng build --prod` will build a version of the project. You can then serve out of the `dist` directory.
16 |
17 | The repo contains a brief setup using Angular Universal which did work around Google I/O and could be served with `node dist/server.js` once built, but no longer appears to work with more recent versions of the project. We're including a note here in case we get a chance to update the setup to latest.
18 |
--------------------------------------------------------------------------------
/src/main-app-shell.ts:
--------------------------------------------------------------------------------
1 | import {provide} from '@angular/core';
2 | import {APP_BASE_HREF} from '@angular/common';
3 | import {ProgressiveAppComponent} from './app/';
4 | import { NODE_LOCATION_PROVIDERS, NODE_ROUTER_PROVIDERS } from 'angular2-universal';
5 | import { Jsonp, JSONP_PROVIDERS } from '@angular/http';
6 |
7 | import {
8 | REQUEST_URL,
9 | ORIGIN_URL,
10 | NODE_HTTP_PROVIDERS
11 | } from 'angular2-universal';
12 | import {APP_SHELL_BUILD_PROVIDERS} from '@angular/app-shell';
13 | import { DribbbleService } from './app/dribbble.service';
14 |
15 | export const options = {
16 | directives: [
17 | // The component that will become the main App Shell
18 | ProgressiveAppComponent
19 | ],
20 | platformProviders: [
21 | provide(ORIGIN_URL, {
22 | useValue: ''
23 | }),
24 | NODE_LOCATION_PROVIDERS
25 |
26 | ],
27 | providers: [
28 | APP_SHELL_BUILD_PROVIDERS,
29 | // What URL should Angular be treating the app as if navigating
30 | provide(APP_BASE_HREF, {useValue: '/'}),
31 | provide(REQUEST_URL, {useValue: '/'}),
32 | NODE_ROUTER_PROVIDERS,
33 | NODE_HTTP_PROVIDERS,
34 | JSONP_PROVIDERS,
35 | provide(Jsonp, {
36 | // No-op
37 | useValue: {}
38 | }),
39 | DribbbleService
40 | ],
41 | async: true,
42 | preboot: false
43 | };
44 |
45 |
--------------------------------------------------------------------------------
/src/app/+snaps/+list/list.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {
2 | beforeEach,
3 | beforeEachProviders,
4 | describe,
5 | expect,
6 | it,
7 | inject,
8 | } from '@angular/core/testing';
9 | import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
10 | import { Component } from '@angular/core';
11 | import { By } from '@angular/platform-browser';
12 | import { ListComponent } from './list.component';
13 |
14 | describe('Component: List', () => {
15 | let builder: TestComponentBuilder;
16 |
17 | beforeEachProviders(() => [ListComponent]);
18 | beforeEach(inject([TestComponentBuilder], function (tcb: TestComponentBuilder) {
19 | builder = tcb;
20 | }));
21 |
22 | it('should inject the component', inject([ListComponent],
23 | (component: ListComponent) => {
24 | expect(component).toBeTruthy();
25 | }));
26 |
27 | it('should create the component', inject([], () => {
28 | return builder.createAsync(ListComponentTestController)
29 | .then((fixture: ComponentFixture) => {
30 | let query = fixture.debugElement.query(By.directive(ListComponent));
31 | expect(query).toBeTruthy();
32 | expect(query.componentInstance).toBeTruthy();
33 | });
34 | }));
35 | });
36 |
37 | @Component({
38 | selector: 'test',
39 | template: `
40 |
41 | `,
42 | directives: [ListComponent]
43 | })
44 | class ListComponentTestController {
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/app/+snaps/+post/post.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {
2 | beforeEach,
3 | beforeEachProviders,
4 | describe,
5 | expect,
6 | it,
7 | inject,
8 | } from '@angular/core/testing';
9 | import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
10 | import { Component } from '@angular/core';
11 | import { By } from '@angular/platform-browser';
12 | import { PostComponent } from './post.component';
13 |
14 | describe('Component: Post', () => {
15 | let builder: TestComponentBuilder;
16 |
17 | beforeEachProviders(() => [PostComponent]);
18 | beforeEach(inject([TestComponentBuilder], function (tcb: TestComponentBuilder) {
19 | builder = tcb;
20 | }));
21 |
22 | it('should inject the component', inject([PostComponent],
23 | (component: PostComponent) => {
24 | expect(component).toBeTruthy();
25 | }));
26 |
27 | it('should create the component', inject([], () => {
28 | return builder.createAsync(PostComponentTestController)
29 | .then((fixture: ComponentFixture) => {
30 | let query = fixture.debugElement.query(By.directive(PostComponent));
31 | expect(query).toBeTruthy();
32 | expect(query.componentInstance).toBeTruthy();
33 | });
34 | }));
35 | });
36 |
37 | @Component({
38 | selector: 'test',
39 | template: `
40 |
41 | `,
42 | directives: [PostComponent]
43 | })
44 | class PostComponentTestController {
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/app/+snaps/snaps.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {
2 | beforeEach,
3 | beforeEachProviders,
4 | describe,
5 | expect,
6 | it,
7 | inject,
8 | } from '@angular/core/testing';
9 | import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
10 | import { Component } from '@angular/core';
11 | import { By } from '@angular/platform-browser';
12 | import { SnapsComponent } from './snaps.component';
13 |
14 | describe('Component: Snaps', () => {
15 | let builder: TestComponentBuilder;
16 |
17 | beforeEachProviders(() => [SnapsComponent]);
18 | beforeEach(inject([TestComponentBuilder], function (tcb: TestComponentBuilder) {
19 | builder = tcb;
20 | }));
21 |
22 | it('should inject the component', inject([SnapsComponent],
23 | (component: SnapsComponent) => {
24 | expect(component).toBeTruthy();
25 | }));
26 |
27 | it('should create the component', inject([], () => {
28 | return builder.createAsync(SnapsComponentTestController)
29 | .then((fixture: ComponentFixture) => {
30 | let query = fixture.debugElement.query(By.directive(SnapsComponent));
31 | expect(query).toBeTruthy();
32 | expect(query.componentInstance).toBeTruthy();
33 | });
34 | }));
35 | });
36 |
37 | @Component({
38 | selector: 'test',
39 | template: `
40 |
41 | `,
42 | directives: [SnapsComponent]
43 | })
44 | class SnapsComponentTestController {
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
26 |
--------------------------------------------------------------------------------
/src/app/+snaps/+list/list.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
2 | import { ROUTER_DIRECTIVES, RouteConfig, CanDeactivate, ComponentInstruction } from '@angular/router-deprecated';
3 | import { DribbbleService } from '../../dribbble.service';
4 |
5 | import {BehaviorSubject} from 'rxjs/BehaviorSubject';
6 | import 'rxjs/add/operator/mergeMap';
7 | import 'rxjs/add/operator/scan';
8 |
9 | @Component({
10 | moduleId: module.id,
11 | selector: 'app-list',
12 | templateUrl: 'list.component.html',
13 | styleUrls: ['list.component.css'],
14 | directives: [ROUTER_DIRECTIVES],
15 | // Since using async pipe in template, only run changeDetection
16 | // when a new value is emitted from posts observable
17 | changeDetection: ChangeDetectionStrategy.OnPush
18 | })
19 | export class ListComponent implements OnInit {
20 | posts;
21 | page = new BehaviorSubject(0).scan((prev:number) => {
22 | // Automatically incremement page whenever next() is called
23 | return prev + 1;
24 | }, 0);
25 | constructor(public dl: DribbbleService) {}
26 |
27 | ngOnInit() {
28 | this.posts = this.page
29 | // Automatically fetch more data when page changes
30 | .mergeMap(page => this.dl.getPosts(page))
31 | // Merge all pages of data into single list
32 | .scan((acc:any[], res) => acc.concat(res.json().data), []);
33 | }
34 |
35 | routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
36 | window.scrollTo(0, 0);
37 | return true;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/config/karma-test-shim.js:
--------------------------------------------------------------------------------
1 | /*global jasmine, __karma__, window*/
2 | Error.stackTraceLimit = Infinity;
3 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
4 |
5 | __karma__.loaded = function () {
6 | };
7 |
8 | var distPath = '/base/dist/';
9 | var appPath = distPath + 'app/';
10 |
11 | function isJsFile(path) {
12 | return path.slice(-3) == '.js';
13 | }
14 |
15 | function isSpecFile(path) {
16 | return path.slice(-8) == '.spec.js';
17 | }
18 |
19 | function isAppFile(path) {
20 | return isJsFile(path) && (path.substr(0, appPath.length) == appPath);
21 | }
22 |
23 | var allSpecFiles = Object.keys(window.__karma__.files)
24 | .filter(isSpecFile)
25 | .filter(isAppFile);
26 |
27 | // Load our SystemJS configuration.
28 | System.config({
29 | baseURL: distPath
30 | });
31 |
32 | System.import('system-config.js').then(function() {
33 | // Load and configure the TestComponentBuilder.
34 | return Promise.all([
35 | System.import('@angular/core/testing'),
36 | System.import('@angular/platform-browser-dynamic/testing')
37 | ]).then(function (providers) {
38 | var testing = providers[0];
39 | var testingBrowser = providers[1];
40 |
41 | testing.setBaseTestProviders(testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
42 | testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
43 | });
44 | }).then(function() {
45 | // Finally, load all spec files.
46 | // This will run the tests directly.
47 | return Promise.all(
48 | allSpecFiles.map(function (moduleName) {
49 | return System.import(moduleName);
50 | }));
51 | }).then(__karma__.start, __karma__.error);
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Progressive
6 |
7 |
8 | {{#unless environment.production}}
9 |
10 | {{/unless}}
11 |
12 |
13 |
14 |
15 |
16 | {{#each mobile.icons}}
17 |
18 | {{/each}}
19 |
20 |
21 |
22 | {{#if environment.production}}
23 |
30 | {{/if}}
31 |
32 |
33 |
34 | Loading...
35 |
36 | {{#if environment.production}}
37 |
38 | {{else}}
39 | {{#each scripts.polyfills}}{{/each}}
40 |
45 | {{/if}}
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/config/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function (config) {
2 | config.set({
3 | basePath: '..',
4 | frameworks: ['jasmine'],
5 | plugins: [
6 | require('karma-jasmine'),
7 | require('karma-chrome-launcher')
8 | ],
9 | customLaunchers: {
10 | // chrome setup for travis CI using chromium
11 | Chrome_travis_ci: {
12 | base: 'Chrome',
13 | flags: ['--no-sandbox']
14 | }
15 | },
16 | files: [
17 | { pattern: 'dist/vendor/es6-shim/es6-shim.js', included: true, watched: false },
18 | { pattern: 'dist/vendor/zone.js/dist/zone.js', included: true, watched: false },
19 | { pattern: 'dist/vendor/reflect-metadata/Reflect.js', included: true, watched: false },
20 | { pattern: 'dist/vendor/systemjs/dist/system-polyfills.js', included: true, watched: false },
21 | { pattern: 'dist/vendor/systemjs/dist/system.src.js', included: true, watched: false },
22 | { pattern: 'dist/vendor/zone.js/dist/async-test.js', included: true, watched: false },
23 |
24 | { pattern: 'config/karma-test-shim.js', included: true, watched: true },
25 |
26 | // Distribution folder.
27 | { pattern: 'dist/**/*', included: false, watched: true }
28 | ],
29 | exclude: [
30 | // Vendor packages might include spec files. We don't want to use those.
31 | 'dist/vendor/**/*.spec.js'
32 | ],
33 | preprocessors: {},
34 | reporters: ['progress'],
35 | port: 9876,
36 | colors: true,
37 | logLevel: config.LOG_INFO,
38 | autoWatch: true,
39 | browsers: ['Chrome'],
40 | singleRun: false
41 | });
42 | };
43 |
--------------------------------------------------------------------------------
/src/app/progressive.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { MdToolbar } from '@angular2-material/toolbar';
3 | import { MdProgressCircle } from '@angular2-material/progress-circle';
4 | import { APP_SHELL_DIRECTIVES } from '@angular/app-shell';
5 | import { SnapsComponent } from './+snaps';
6 | import { RouteConfig , ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from '@angular/router-deprecated';
7 |
8 | @Component({
9 | moduleId: module.id,
10 | selector: 'progressive-app',
11 | styles: [`
12 | md-toolbar[color=primary] {
13 | background: #673AB7;
14 | margin-top: -70px;
15 | will-change: transform;
16 | position: fixed;
17 | z-index: 5;
18 | box-shadow: 0 4px 5px 0 rgba(0,0,0,.14),0 2px 9px 1px rgba(0,0,0,.12),0 4px 2px -2px rgba(0,0,0,.2);
19 | }
20 |
21 | md-toolbar a {
22 | color: white;
23 | }
24 |
25 | md-progress-circle[mode="indeterminate"] {
26 | width: 64px;
27 | height: 64px;
28 | margin: 0 8px;
29 | }
30 |
31 | .indicator-container {
32 | height: 0;
33 | margin-top: 50%;
34 | }
35 | .indicator-container md-progress-circle {
36 | margin: -50px auto 0;
37 | }
38 | .indicator-container md-progress-circle[mode="indeterminate"] /deep/ circle {
39 | stroke: #512DA8 !important;
40 | }
41 |
42 | `],
43 | template: `
44 |
45 | Berry
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | `,
54 | directives: [MdToolbar, MdProgressCircle, APP_SHELL_DIRECTIVES, ROUTER_DIRECTIVES]
55 | })
56 | @RouteConfig([
57 | {path: '/snaps/...', component: SnapsComponent, as: 'Home', useAsDefault: true}
58 | ])
59 | export class ProgressiveAppComponent {
60 |
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": ["node_modules/codelyzer"],
3 | "rules": {
4 | "max-line-length": [true, 100],
5 | "no-inferrable-types": true,
6 | "class-name": true,
7 | "comment-format": [
8 | true,
9 | "check-space"
10 | ],
11 | "indent": [
12 | true,
13 | "spaces"
14 | ],
15 | "eofline": true,
16 | "no-duplicate-variable": true,
17 | "no-eval": true,
18 | "no-arg": true,
19 | "no-internal-module": true,
20 | "no-trailing-whitespace": true,
21 | "no-bitwise": true,
22 | "no-shadowed-variable": true,
23 | "no-unused-expression": true,
24 | "no-unused-variable": true,
25 | "one-line": [
26 | true,
27 | "check-catch",
28 | "check-else",
29 | "check-open-brace",
30 | "check-whitespace"
31 | ],
32 | "quotemark": [
33 | true,
34 | "single",
35 | "avoid-escape"
36 | ],
37 | "semicolon": [true, "always"],
38 | "typedef-whitespace": [
39 | true,
40 | {
41 | "call-signature": "nospace",
42 | "index-signature": "nospace",
43 | "parameter": "nospace",
44 | "property-declaration": "nospace",
45 | "variable-declaration": "nospace"
46 | }
47 | ],
48 | "curly": true,
49 | "variable-name": [
50 | true,
51 | "ban-keywords",
52 | "check-format",
53 | "allow-trailing-underscore"
54 | ],
55 | "whitespace": [
56 | true,
57 | "check-branch",
58 | "check-decl",
59 | "check-operator",
60 | "check-separator",
61 | "check-type"
62 | ],
63 | "component-selector-name": [true, "kebab-case"],
64 | "component-selector-type": [true, "element"],
65 | "host-parameter-decorator": true,
66 | "input-parameter-decorator": true,
67 | "output-parameter-decorator": true,
68 | "attribute-parameter-decorator": true,
69 | "input-property-directive": true,
70 | "output-property-directive": true
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "progressive",
3 | "version": "0.0.0",
4 | "license": "MIT",
5 | "angular-cli": {},
6 | "scripts": {
7 | "start": "ng server",
8 | "postinstall": "typings install",
9 | "lint": "tslint \"src/**/*.ts\"",
10 | "format": "clang-format -i -style=file --glob=src/**/*.ts",
11 | "test": "ng test",
12 | "pree2e": "webdriver-manager update",
13 | "e2e": "protractor"
14 | },
15 | "private": true,
16 | "dependencies": {
17 | "@angular/app-shell": "0.0.0",
18 | "@angular/common": "2.0.0-rc.1",
19 | "@angular/compiler": "2.0.0-rc.1",
20 | "@angular/core": "2.0.0-rc.1",
21 | "@angular/http": "2.0.0-rc.1",
22 | "@angular/platform-browser": "2.0.0-rc.1",
23 | "@angular/platform-browser-dynamic": "2.0.0-rc.1",
24 | "@angular/router": "2.0.0-rc.1",
25 | "@angular/router-deprecated": "^2.0.0-rc.1",
26 | "@angular2-material/progress-circle": "^2.0.0-alpha.4",
27 | "@angular2-material/toolbar": "^2.0.0-alpha.4",
28 | "angular2-universal": "^0.100.4",
29 | "es6-shim": "^0.35.0",
30 | "reflect-metadata": "0.1.3",
31 | "rxjs": "5.0.0-beta.6",
32 | "systemjs": "0.19.26",
33 | "vinyl": "^1.1.1",
34 | "zone.js": "^0.6.12"
35 | },
36 | "devDependencies": {
37 | "@angular/platform-server": "2.0.0-rc.1",
38 | "angular2-broccoli-prerender": "^0.11.0",
39 | "angular2-service-worker": "0.1.11",
40 | "angular2-universal": "^0.100.3",
41 | "angular2-universal-polyfills": "^0.4.1",
42 | "preboot": "^2.0.10",
43 | "angular-cli": "^1.0.0-beta.2-mobile",
44 | "clang-format": "^1.0.35",
45 | "codelyzer": "0.0.14",
46 | "ember-cli-inject-live-reload": "^1.4.0",
47 | "jasmine-core": "^2.4.1",
48 | "jasmine-spec-reporter": "^2.4.0",
49 | "karma": "^0.13.15",
50 | "karma-chrome-launcher": "^0.2.3",
51 | "karma-jasmine": "^0.3.8",
52 | "protractor": "^3.3.0",
53 | "ts-node": "^0.5.5",
54 | "tslint": "^3.6.0",
55 | "typescript": "^1.8.10",
56 | "typings": "^0.8.1"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/app/+snaps/+post/post.component.html:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
25 |

26 |
27 |
28 |
29 |
30 |
31 |
32 | -
33 |
34 | {{post.likes_count}}
35 | Likes
36 |
37 | -
38 |
39 | {{post.views_count}}
40 | Views
41 |
42 | -
43 |
44 | {{post.rebounds_count}}
45 | Rebounds
46 |
47 | -
48 |
49 | {{post.comments_count}}
50 | Comments
51 |
52 | -
53 |
54 |
55 | Link to Dribbble
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/system-config.ts:
--------------------------------------------------------------------------------
1 | /***********************************************************************************************
2 | * User Configuration.
3 | **********************************************************************************************/
4 | /** Map relative paths to URLs. */
5 | const map: any = {}
6 |
7 | /** User packages configuration. */
8 | const packages: any = {}
9 |
10 | ////////////////////////////////////////////////////////////////////////////////////////////////
11 | /***********************************************************************************************
12 | * Everything underneath this line is managed by the CLI.
13 | **********************************************************************************************/
14 | const barrels: string[] = [
15 | // Angular specific barrels.
16 | '@angular/app-shell',
17 | '@angular/core',
18 | '@angular/common',
19 | '@angular/compiler',
20 | '@angular/http',
21 | '@angular/router',
22 | '@angular/platform-browser',
23 | '@angular/platform-browser-dynamic',
24 | '@angular2-material/core',
25 | '@angular2-material/toolbar',
26 | '@angular2-material/progress-circle',
27 | '@angular/router-deprecated',
28 | '@angular/upgrade',
29 | '@angular/testing',
30 | // Thirdparty barrels.
31 | 'rxjs',
32 |
33 | // App specific barrels.
34 | 'app',
35 | 'app/shared',
36 | 'app/+snaps',
37 | 'app/+snaps/+post',
38 | 'app/+snaps/+list',
39 | /** @cli-barrel */
40 | ];
41 |
42 | const cliSystemConfigPackages: any = {};
43 | barrels.forEach((barrelName: string) => {
44 | cliSystemConfigPackages[barrelName] = { main: 'index' };
45 | });
46 |
47 | /** Type declaration for ambient System. */
48 | declare var System: any;
49 |
50 | // Apply the CLI SystemJS configuration.
51 | System.config({
52 | map: {
53 | '@angular': 'vendor/@angular',
54 | '@angular2-material': 'vendor/@angular2-material',
55 | 'rxjs': 'vendor/rxjs',
56 | 'main': 'main.js',
57 | 'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api'
58 | },
59 | packages: Object.assign({}, cliSystemConfigPackages, {
60 | '@angular2-material/toolbar': {
61 | defaultExtension: 'js',
62 | main: 'toolbar.js'
63 | },
64 | '@angular2-material/progress-circle': {
65 | defaultExtension: 'js',
66 | main: 'progress-circle.js'
67 | },
68 | 'angular2-in-memory-web-api': {
69 | defaultExtension: 'js'
70 | }
71 | })
72 | });
73 |
74 | // Apply the user's configuration.
75 | System.config({ map, packages });
76 |
--------------------------------------------------------------------------------
/src/styles/app.css:
--------------------------------------------------------------------------------
1 |
2 | html {
3 | -webkit-box-sizing: border-box;
4 | box-sizing: border-box;
5 | }
6 |
7 | .album {
8 | margin-top: 20px;
9 | }
10 |
11 | body {
12 | font-family: Roboto,Helvetica,Arial,sans-serif;
13 | font-size: 14px;
14 | line-height: 1.42857143;
15 | color: #333;
16 | background-color: #FAFAFA;
17 | margin: 0;
18 | padding-top: 70px;
19 | }
20 |
21 | .btn-block {
22 | display: block;
23 | width: 100%;
24 | }
25 |
26 | .container {
27 | padding-right: 15px;
28 | padding-left: 15px;
29 | margin-right: auto;
30 | margin-left: auto;
31 | }
32 |
33 | .container::after {
34 | display: table;
35 | clear: both;
36 | content: "";
37 | }
38 |
39 | .container-fluid>.navbar-collapse, .container-fluid>.navbar-header, .container>.navbar-collapse, .container>.navbar-header {
40 | margin-right: -15px;
41 | margin-left: -15px;
42 | }
43 |
44 | @media (min-width: 1200px) {
45 | .container {
46 | max-width: 1140px;
47 | }
48 | }
49 |
50 | @media (min-width: 992px) {
51 | .container {
52 | max-width: 940px;
53 | }
54 | }
55 |
56 | a {
57 | color: #337ab7;
58 | text-decoration: none;
59 | }
60 |
61 | .md-thumbnail {
62 | display: block;
63 | padding: 4px;
64 | margin-bottom: 20px;
65 | line-height: 1.42857143;
66 | background-color: #fff;
67 | border: 1px solid #ddd;
68 | /*border-radius: 4px;*/
69 | -webkit-transition: border .2s ease-in-out;
70 | -o-transition: border .2s ease-in-out;
71 | transition: border .2s ease-in-out;
72 |
73 | box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
74 | border-radius: 2px;
75 | }
76 |
77 | .md-thumbnail img {
78 | min-width: 100%;
79 | }
80 |
81 | .md-thumbnail a>img, .md-thumbnail>img {
82 | margin-right: auto;
83 | margin-left: auto;
84 | }
85 |
86 | .md-thumbnail a>img, .md-thumbnail>img {
87 | display: block;
88 | max-width: 100%;
89 | height: auto;
90 | }
91 |
92 | img {
93 | vertical-align: middle;
94 | }
95 |
96 | .md-thumbnail .caption {
97 | padding-left: 8px;
98 | padding-bottom: 24px;
99 | color: #aaa;
100 | font-size: 11px;
101 | padding-top: 15px;
102 | }
103 |
104 | .card {
105 | float: left;
106 | width: 31.333%;
107 | min-width: 190px;
108 | /*padding: .75rem;*/
109 | margin-right: 10px;
110 | border: 0;
111 | box-shadow: 1px 1px 6px 0 #C6C4C4;
112 | cursor: pointer;
113 | }
114 |
115 | .card img {
116 | max-width: 100%;
117 | }
118 |
119 | .card-text {
120 | font-size: 85%;
121 | }
122 |
123 | @media (max-width: 600px)
124 | {
125 | .card {
126 | width: 90%;
127 | margin: 0 auto 15px;
128 | float: none;
129 | }
130 | }
131 |
132 | .row {
133 | margin-right: -.9375rem;
134 | margin-left: -.9375rem;
135 | }
136 |
137 | .mdl-button {
138 | background: 0 0;
139 | border: none;
140 | border-radius: 2px;
141 | color: #000;
142 | position: relative;
143 | height: 36px;
144 | /*margin: 0;*/
145 | min-width: 64px;
146 | padding: 0 16px;
147 | /*display: inline-block;*/
148 | font-family: "Roboto","Helvetica","Arial",sans-serif;
149 | font-size: 14px;
150 | font-weight: 500;
151 | text-transform: uppercase;
152 | letter-spacing: 0;
153 | overflow: hidden;
154 | will-change: box-shadow;
155 | transition: box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);
156 | outline: none;
157 | cursor: pointer;
158 | text-decoration: none;
159 | text-align: center;
160 | line-height: 36px;
161 | vertical-align: middle;
162 | background: rgba(158,158,158,.2);
163 | box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
164 | color: #fff;
165 | background-color: #ff4081;
166 | width: 95%;
167 | margin: 0px 10px 10px 10px;
168 | }
169 |
170 | *, ::after, ::before {
171 | -webkit-box-sizing: inherit;
172 | box-sizing: inherit;
173 | }
174 |
175 | .caption .trophy {
176 | float: left;
177 | width: 54px;
178 | }
179 |
180 | .caption .trophy img {
181 | width: 15px;
182 | max-width: 15px;
183 | min-width: 15px;
184 | margin-bottom: 0px;
185 | }
186 |
--------------------------------------------------------------------------------
/app.yaml:
--------------------------------------------------------------------------------
1 | application: berry-app
2 | version: 8
3 | runtime: python27
4 | api_version: 1
5 | threadsafe: true
6 |
7 | default_expiration: "30d"
8 |
9 | handlers:
10 | # web files
11 | - url: /(.*\.(appcache|manifest))
12 | mime_type: text/cache-manifest
13 | static_files: dist/\1
14 | upload: dist/(.*\.(appcache|manifest))
15 | expiration: "0m"
16 |
17 | - url: /(.*\.html)
18 | mime_type: text/html
19 | static_files: dist/\1
20 | upload: dist/(.*\.html)
21 | expiration: "1h"
22 |
23 | - url: /(.*\.css)
24 | mime_type: text/css
25 | static_files: dist/\1
26 | upload: dist/(.*\.css)
27 |
28 | - url: /(.*\.js)
29 | mime_type: text/javascript
30 | static_files: dist/\1
31 | upload: dist/(.*\.js)
32 |
33 | - url: /(.*\.json)
34 | mime_type: application/json
35 | static_files: dist/\1
36 | upload: dist/(.*\.json)
37 | expiration: "1h"
38 |
39 | - url: /(.*\.webapp)
40 | mime_type: application/json
41 | static_files: dist/\1
42 | upload: dist/(.*\.webapp)
43 | expiration: "1h"
44 |
45 | - url: /(.*\.xml)
46 | mime_type: application/xml
47 | static_files: dist/\1
48 | upload: dist/(.*\.xml)
49 | expiration: "1h"
50 |
51 | - url: /(.*\.htc)
52 | mime_type: text/x-component
53 | static_files: dist/\1
54 | upload: dist/(.*\.htc)
55 |
56 | - url: /(.*\.txt)
57 | mime_type: text/plain
58 | static_files: dist/\1
59 | upload: dist/(.*\.txt)
60 |
61 | - url: /(.*\.rss)
62 | mime_type: application/rss+xml
63 | static_files: dist/\1
64 | upload: dist/(.*\.rss)
65 | expiration: "1h"
66 |
67 | - url: /(.*\.atom)
68 | mime_type: application/atom+xml
69 | static_files: dist/\1
70 | upload: dist/(.*\.atom)
71 | expiration: "1h"
72 |
73 | - url: /(.*\.crx)
74 | mime_type: application/x-chrome-extension
75 | static_files: dist/\1
76 | upload: dist/(.*\.crx)
77 |
78 | - url: /(.*\.xpi)
79 | mime_type: application/x-xpinstall
80 | static_files: dist/\1
81 | upload: dist/(.*\.xpi)
82 |
83 | - url: /(.*\.safariextz)
84 | mime_type: application/octet-stream
85 | static_files: dist/\1
86 | upload: dist/(.*\.safariextz)
87 |
88 | # font files
89 | - url: /(.*\.eot)
90 | mime_type: application/vnd.ms-fontobject
91 | static_files: dist/\1
92 | upload: dist/(.*\.eot)
93 |
94 | - url: /(.*\.otf)
95 | mime_type: font/opentype
96 | static_files: dist/\1
97 | upload: dist/(.*\.otf)
98 |
99 | - url: /(.*\.ttf)
100 | mime_type: font/truetype
101 | static_files: dist/\1
102 | upload: dist/(.*\.ttf)
103 |
104 | - url: /(.*\.woff)
105 | mime_type: application/x-font-woff
106 | static_files: dist/\1
107 | upload: dist/(.*\.woff)
108 |
109 | # image files
110 | - url: /(.*\.ico)
111 | mime_type: image/x-icon
112 | static_files: dist/\1
113 | upload: dist/(.*\.ico)
114 | expiration: "7d"
115 |
116 | - url: /(.*\.(bmp|gif|ico|jpeg|jpg|png))
117 | static_files: dist/\1
118 | upload: dist/(.*\.(bmp|gif|ico|jpeg|jpg|png))
119 |
120 | - url: /(.*\.webp)
121 | mime_type: image/webp
122 | static_files: dist/\1
123 | upload: dist/(.*\.webp)
124 |
125 | - url: /(.*\.(svg|svgz))
126 | mime_type: image/svg+xml
127 | static_files: dist/\1
128 | upload: dist/(.*\.(svg|svgz))
129 |
130 | # audio files
131 | - url: /(.*\.(mid|midi|mp3|wav))
132 | static_files: dist/\1
133 | upload: dist/(.*\.(mid|midi|mp3|wav))
134 |
135 | - url: /(.*\.(ogg|oga))
136 | mime_type: audio/ogg
137 | static_files: dist/\1
138 | upload: dist/(.*\.(ogg|oga))
139 |
140 | # video/media files
141 | - url: /(.*\.m4v)
142 | mime_type: video/m4v
143 | static_files: dist/\1
144 | upload: dist/(.*\.m4v)
145 |
146 | - url: /(.*\.mp4)
147 | mime_type: video/mp4
148 | static_files: dist/\1
149 | upload: dist/(.*\.mp4)
150 |
151 | - url: /(.*\.ogv)
152 | mime_type: video/ogg
153 | static_files: dist/\1
154 | upload: dist/(.*\.ogv)
155 |
156 | - url: /(.*\.webm)
157 | mime_type: video/webm
158 | static_files: dist/\1
159 | upload: dist/(.*\.webm)
160 |
161 | - url: /(.*\.swf)
162 | mime_type: application/x-shockwave-flash
163 | static_files: dist/\1
164 | upload: dist/(.*\.swf)
165 |
166 | - url: /(.*\.unity3d)
167 | mime_type: application/vnd.unity
168 | static_files: dist/\1
169 | upload: dist/(.*\.unity3d)
170 |
171 | # windows files
172 | - url: /(.*\.(doc|exe|ppt|rtf|xls))
173 | static_files: dist/\1
174 | upload: dist/(.*\.(doc|exe|ppt|rtf|xls))
175 |
176 | # compressed files
177 | - url: /(.*\.(bz2|gz|rar|tar|tgz|zip))
178 | static_files: dist/\1
179 | upload: dist/(.*\.(bz2|gz|rar|tar|tgz|zip))
180 |
181 | # index files
182 | - url: /(.*)/
183 | static_files: dist/\1/index.html
184 | upload: dist/(.*)/index.html
185 | expiration: "15m"
186 |
187 | # site root
188 | - url: /
189 | static_files: dist/index.html
190 | upload: dist/index.html
191 | expiration: "15m"
192 |
193 | skip_files:
194 | - ^node_modules$
195 | - node_modules
196 |
--------------------------------------------------------------------------------