├── .gitattributes ├── Ch21_ddip-ember ├── config │ ├── optional-features.json │ ├── targets.js │ └── environment.js ├── dist │ ├── robots.txt │ ├── ember-welcome-page │ │ └── images │ │ │ └── construction.png │ ├── testem.js │ ├── index.html │ ├── tests │ │ └── index.html │ └── assets │ │ ├── vendor.css │ │ ├── test-support.css │ │ ├── ddip-ember.js │ │ └── ddip-ember.map ├── public │ └── robots.txt ├── app │ ├── resolver.js │ ├── templates │ │ ├── pages.hbs │ │ ├── articles.hbs │ │ ├── application.hbs │ │ └── components │ │ │ └── entity-list.hbs │ ├── components │ │ └── entity-list.js │ ├── routes │ │ ├── pages.js │ │ └── articles.js │ ├── models │ │ ├── node--page.js │ │ └── node--article.js │ ├── router.js │ ├── app.js │ ├── adapters │ │ └── application.js │ └── index.html ├── tests │ ├── test-helper.js │ ├── unit │ │ ├── routes │ │ │ ├── pages-test.js │ │ │ └── articles-test.js │ │ ├── adapters │ │ │ └── application-test.js │ │ └── models │ │ │ ├── node--page-test.js │ │ │ └── node--article-test.js │ ├── integration │ │ └── components │ │ │ └── entity-list-test.js │ └── index.html ├── testem.js ├── ember-cli-build.js ├── package.json └── README.md ├── Ch20_ddip-vue ├── babel.config.js ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── assets │ │ └── logo.png │ ├── main.js │ ├── App.vue │ └── components │ │ └── Articles.vue ├── README.md └── package.json ├── 9781484240717.jpg ├── Ch17_ddip-react ├── src │ ├── index.css │ ├── index.js │ ├── App.test.js │ ├── App.css │ ├── Article.js │ ├── App.js │ ├── logo.svg │ └── registerServiceWorker.js ├── public │ ├── favicon.ico │ ├── manifest.json │ └── index.html └── package.json ├── Ch19_ddip-ng ├── src │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── styles.css │ ├── favicon.ico │ ├── app │ │ ├── app.component.html │ │ ├── articles │ │ │ ├── articles.component.css │ │ │ ├── articles.component.html │ │ │ ├── articles.component.spec.ts │ │ │ └── articles.component.ts │ │ ├── app.component.ts │ │ ├── article.service.spec.ts │ │ ├── app.module.ts │ │ ├── dummy-articles.ts │ │ ├── app.component.spec.ts │ │ └── article.service.ts │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ ├── index.html │ ├── tslint.json │ ├── main.ts │ ├── browserslist │ ├── test.ts │ ├── karma.conf.js │ └── polyfills.ts ├── e2e │ ├── src │ │ ├── app.po.ts │ │ └── app.e2e-spec.ts │ ├── tsconfig.e2e.json │ └── protractor.conf.js ├── tsconfig.json ├── README.md ├── package.json ├── tslint.json └── angular.json ├── Ch18_DdipReactNative ├── assets │ ├── icon.png │ └── splash.png ├── package.json ├── app.json ├── Article.js └── App.js ├── Ch22_extended_rest ├── extended_rest.info.yml └── src │ └── Plugin │ └── rest │ └── resource │ └── CustomResource.php ├── errata.md ├── README.md ├── Contributing.md └── LICENSE.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/config/optional-features.json: -------------------------------------------------------------------------------- 1 | { 2 | "jquery-integration": true 3 | } 4 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /9781484240717.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/9781484240717.jpg -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from 'ember-resolver'; 2 | 3 | export default Resolver; 4 | -------------------------------------------------------------------------------- /Ch17_ddip-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch19_ddip-ng/src/favicon.ico -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/templates/pages.hbs: -------------------------------------------------------------------------------- 1 | {{! app/templates/pages.hbs }} 2 | {{entity-list title="List of pages" entities=model}} 3 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch20_ddip-vue/public/favicon.ico -------------------------------------------------------------------------------- /Ch20_ddip-vue/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch20_ddip-vue/src/assets/logo.png -------------------------------------------------------------------------------- /Ch17_ddip-react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch17_ddip-react/public/favicon.ico -------------------------------------------------------------------------------- /Ch18_DdipReactNative/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch18_DdipReactNative/assets/icon.png -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/components/entity-list.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | 3 | export default Component.extend({ 4 | }); 5 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/templates/articles.hbs: -------------------------------------------------------------------------------- 1 | {{! app/templates/articles.hbs }} 2 | {{entity-list title="List of articles" entities=model}} 3 | -------------------------------------------------------------------------------- /Ch18_DdipReactNative/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch18_DdipReactNative/assets/splash.png -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{title}} 4 |

5 | 6 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/articles/articles.component.css: -------------------------------------------------------------------------------- 1 | /* src/app/articles.component.css */ 2 | .selected { 3 | font-weight: bold; 4 | color: green; 5 | } 6 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App) 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/ember-welcome-page/images/construction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/decoupled-drupal-in-practice/HEAD/Ch21_ddip-ember/dist/ember-welcome-page/images/construction.png -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/routes/pages.js: -------------------------------------------------------------------------------- 1 | // app/routes/pages.js 2 | import Route from '@ember/routing/route'; 3 | 4 | export default Route.extend({ 5 | model () { 6 | return this.get('store').findAll('node--page'); 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/routes/articles.js: -------------------------------------------------------------------------------- 1 | // app/routes/articles.js 2 | import Route from '@ember/routing/route'; 3 | 4 | export default Route.extend({ 5 | model () { 6 | return this.get('store').findAll('node--article'); 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /Ch22_extended_rest/extended_rest.info.yml: -------------------------------------------------------------------------------- 1 | name: Extended REST 2 | description: 'Adds custom resources to the Drupal core REST API.' 3 | package: Custom 4 | 5 | type: module 6 | core: 8.x 7 | 8 | dependencies: 9 | - drupal:rest 10 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "exclude": [ 8 | "test.ts", 9 | "**/*.spec.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/models/node--page.js: -------------------------------------------------------------------------------- 1 | // app/models/node--page.js 2 | import DS from 'ember-data'; 3 | 4 | export default DS.Model.extend({ 5 | uuid: DS.attr(), 6 | title: DS.attr(), 7 | created: DS.attr(), 8 | body: DS.attr() 9 | }); 10 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/models/node--article.js: -------------------------------------------------------------------------------- 1 | // app/models/node--article.js 2 | import DS from 'ember-data'; 3 | 4 | export default DS.Model.extend({ 5 | uuid: DS.attr(), 6 | title: DS.attr(), 7 | created: DS.attr(), 8 | body: DS.attr() 9 | }); 10 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/templates/application.hbs: -------------------------------------------------------------------------------- 1 | {{! app/templates/application.hbs }} 2 |

{{#link-to "index"}}Ember app{{/link-to}}

3 | 7 | {{outlet}} 8 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import Application from '../app'; 2 | import config from '../config/environment'; 3 | import { setApplication } from '@ember/test-helpers'; 4 | import { start } from 'ember-qunit'; 5 | 6 | setApplication(Application.create(config.APP)); 7 | 8 | start(); 9 | -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *Book Title* 2 | 3 | On **page xx** [Summary of error]: 4 | 5 | Details of error here. Highlight key pieces in **bold**. 6 | 7 | *** 8 | 9 | On **page xx** [Summary of error]: 10 | 11 | Details of error here. Highlight key pieces in **bold**. 12 | 13 | *** -------------------------------------------------------------------------------- /Ch19_ddip-ng/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } -------------------------------------------------------------------------------- /Ch17_ddip-react/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /Ch17_ddip-react/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | // src/app/app.component.ts 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | templateUrl: './app.component.html', 7 | styleUrls: ['./app.component.css'] 8 | }) 9 | 10 | export class AppComponent { 11 | title = 'ddip-ng'; 12 | } 13 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/README.md: -------------------------------------------------------------------------------- 1 | # ddip-vue 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn run lint 21 | ``` 22 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/unit/routes/pages-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('Unit | Route | pages', function(hooks) { 5 | setupTest(hooks); 6 | 7 | test('it exists', function(assert) { 8 | let route = this.owner.lookup('route:pages'); 9 | assert.ok(route); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "test.ts", 12 | "polyfills.ts" 13 | ], 14 | "include": [ 15 | "**/*.spec.ts", 16 | "**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/unit/routes/articles-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('Unit | Route | articles', function(hooks) { 5 | setupTest(hooks); 6 | 7 | test('it exists', function(assert) { 8 | let route = this.owner.lookup('route:articles'); 9 | assert.ok(route); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/templates/components/entity-list.hbs: -------------------------------------------------------------------------------- 1 | {{! app/templates/components/entity-list.hbs }} 2 |

{{title}}

3 | 14 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DdipNg 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/router.js: -------------------------------------------------------------------------------- 1 | import EmberRouter from '@ember/routing/router'; 2 | import config from './config/environment'; 3 | 4 | const Router = EmberRouter.extend({ 5 | location: config.locationType, 6 | rootURL: config.rootURL 7 | }); 8 | 9 | Router.map(function() { 10 | this.route('articles'); 11 | this.route('pages'); 12 | }); 13 | 14 | export default Router; 15 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('workspace-project App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to ddip-ng!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "app", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "app", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Ch17_ddip-react/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/config/targets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const browsers = [ 4 | 'last 1 Chrome versions', 5 | 'last 1 Firefox versions', 6 | 'last 1 Safari versions' 7 | ]; 8 | 9 | const isCI = !!process.env.CI; 10 | const isProduction = process.env.EMBER_ENV === 'production'; 11 | 12 | if (isCI || isProduction) { 13 | browsers.push('ie 11'); 14 | } 15 | 16 | module.exports = { 17 | browsers 18 | }; 19 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/article.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ArticleService } from './article.service'; 4 | 5 | describe('ArticleService', () => { 6 | beforeEach(() => TestBed.configureTestingModule({})); 7 | 8 | it('should be created', () => { 9 | const service: ArticleService = TestBed.get(ArticleService); 10 | expect(service).toBeTruthy(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/unit/adapters/application-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('Unit | Adapter | application', function(hooks) { 5 | setupTest(hooks); 6 | 7 | // Replace this with your real tests. 8 | test('it exists', function(assert) { 9 | let adapter = this.owner.lookup('adapter:application'); 10 | assert.ok(adapter); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | 14 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-11 -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/app.js: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from './resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | const App = Application.extend({ 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix, 9 | Resolver 10 | }); 11 | 12 | loadInitializers(App, config.modulePrefix); 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/unit/models/node--page-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('Unit | Model | node page', function(hooks) { 5 | setupTest(hooks); 6 | 7 | // Replace this with your real tests. 8 | test('it exists', function(assert) { 9 | let store = this.owner.lookup('service:store'); 10 | let model = store.createRecord('node--page', {}); 11 | assert.ok(model); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/unit/models/node--article-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('Unit | Model | node article', function(hooks) { 5 | setupTest(hooks); 6 | 7 | // Replace this with your real tests. 8 | test('it exists', function(assert) { 9 | let store = this.owner.lookup('service:store'); 10 | let model = store.createRecord('node--article', {}); 11 | assert.ok(model); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /Ch17_ddip-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddip-react", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "axios": "^0.18.0", 7 | "react": "^16.5.2", 8 | "react-dom": "^16.5.2", 9 | "react-router-dom": "^4.3.1", 10 | "react-scripts": "1.1.5" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Ch18_DdipReactNative/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "empty-project-template", 3 | "main": "node_modules/expo/AppEntry.js", 4 | "private": true, 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "eject": "expo eject" 10 | }, 11 | "dependencies": { 12 | "axios": "^0.18.0", 13 | "expo": "^30.0.1", 14 | "react": "16.3.1", 15 | "react-native": "https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "module": "es2015", 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "target": "es5", 13 | "typeRoots": [ 14 | "node_modules/@types" 15 | ], 16 | "lib": [ 17 | "es2017", 18 | "dom" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Ch17_ddip-react/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Decoupled Drupal in Practice*](http://www.apress.com/9781484240717) by Preston So (Apress, 2018). 4 | 5 | [comment]: #cover 6 | ![Cover image](9781484240717.jpg) 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/adapters/application.js: -------------------------------------------------------------------------------- 1 | // app/adapters/application.js 2 | import DS from 'ember-data'; 3 | 4 | export default DS.JSONAPIAdapter.extend({ 5 | host: 'http://jsonapi-test.dd:8083', 6 | namespace: 'jsonapi', 7 | 8 | pathForType(type) { 9 | let entityPath; 10 | switch(type) { 11 | case 'node--article': 12 | entityPath = 'node/article'; 13 | break; 14 | case 'node--page': 15 | entityPath = 'node/page'; 16 | break; 17 | } 18 | return entityPath; 19 | }, 20 | 21 | buildURL() { 22 | return this._super(...arguments); 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /Ch17_ddip-react/src/Article.js: -------------------------------------------------------------------------------- 1 | // src/Article.js 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | const Article = ({article}) => ( 6 |
7 | {article && ( 8 |
9 |

{article.attributes.title}

10 |
    11 |
  • {article.id}
  • 12 |
  • {article.attributes.created}
  • 13 |
14 |
{article.attributes.body.value}
15 |
16 | )} 17 |
18 | ); 19 | 20 | Article.propTypes = { 21 | article: PropTypes.object 22 | }; 23 | 24 | export default Article; 25 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ddip-vue 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/articles/articles.component.html: -------------------------------------------------------------------------------- 1 | 2 |

List of articles

3 | 10 | 11 |
12 |

{{selectedArticle.attributes.title}} details ({{selectedArticle.attributes.uuid}})

13 |
14 | 15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | // src/app/app.module.ts 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { NgModule } from '@angular/core'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { HttpClientModule } from '@angular/common/http'; 6 | 7 | import { AppComponent } from './app.component'; 8 | import { ArticlesComponent } from './articles/articles.component'; 9 | 10 | @NgModule({ 11 | declarations: [ 12 | AppComponent, 13 | ArticlesComponent 14 | ], 15 | imports: [ 16 | BrowserModule, 17 | FormsModule, 18 | HttpClientModule 19 | ], 20 | providers: [], 21 | bootstrap: [AppComponent] 22 | }) 23 | export class AppModule { } 24 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/testem.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test_page: 'tests/index.html?hidepassed', 3 | disable_watching: true, 4 | launch_in_ci: [ 5 | 'Chrome' 6 | ], 7 | launch_in_dev: [ 8 | 'Chrome' 9 | ], 10 | browser_args: { 11 | Chrome: { 12 | ci: [ 13 | // --no-sandbox is needed when running Chrome inside a container 14 | process.env.CI ? '--no-sandbox' : null, 15 | '--headless', 16 | '--disable-gpu', 17 | '--disable-dev-shm-usage', 18 | '--disable-software-rasterizer', 19 | '--mute-audio', 20 | '--remote-debugging-port=0', 21 | '--window-size=1440,900' 22 | ].filter(Boolean) 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /Ch18_DdipReactNative/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "DdipReactNative", 4 | "description": "This project is really great.", 5 | "slug": "DdipReactNative", 6 | "privacy": "public", 7 | "sdkVersion": "30.0.0", 8 | "platforms": ["ios", "android"], 9 | "version": "1.0.0", 10 | "orientation": "portrait", 11 | "icon": "./assets/icon.png", 12 | "splash": { 13 | "image": "./assets/splash.png", 14 | "resizeMode": "contain", 15 | "backgroundColor": "#ffffff" 16 | }, 17 | "updates": { 18 | "fallbackToCacheTimeout": 0 19 | }, 20 | "assetBundlePatterns": [ 21 | "**/*" 22 | ], 23 | "ios": { 24 | "supportsTablet": true 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/testem.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This is dummy file that exists for the sole purpose 3 | * of allowing tests to run directly in the browser as 4 | * well as by Testem. 5 | * 6 | * Testem is configured to run tests directly against 7 | * the test build of index.html, which requires a 8 | * snippet to load the testem.js file: 9 | * 10 | * This has to go before the qunit framework and app 11 | * tests are loaded. 12 | * 13 | * Testem internally supplies this file. However, if you 14 | * run the tests directly in the browser (localhost:8000/tests), 15 | * this file does not exist. 16 | * 17 | * Hence the purpose of this fake file. This file is served 18 | * directly from the express server to satisify the script load. 19 | */ 20 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/articles/articles.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ArticlesComponent } from './articles.component'; 4 | 5 | describe('ArticlesComponent', () => { 6 | let component: ArticlesComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ArticlesComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ArticlesComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /Ch22_extended_rest/src/Plugin/rest/resource/CustomResource.php: -------------------------------------------------------------------------------- 1 | 'Hello world!']; 27 | return new ResourceResponse($response); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DdipEmber 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | 12 | 13 | 14 | 15 | {{content-for "head-footer"}} 16 | 17 | 18 | {{content-for "body"}} 19 | 20 | 21 | 22 | 23 | {{content-for "body-footer"}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/dummy-articles.ts: -------------------------------------------------------------------------------- 1 | // src/app/dummy-articles.ts 2 | import { Article } from './articles/articles.component'; 3 | 4 | export const ARTICLES: Article[] = [ 5 | { 6 | attributes: { 7 | uuid: '7ac282af-81d1-4d88-925d-9a3a9f6d304f', 8 | title: 'Neque Nisl', 9 | body: { 10 | value: 'At interdico letalis modo qui.' 11 | } 12 | } 13 | }, 14 | { 15 | attributes: { 16 | uuid: 'dfca8a65-a214-470c-ae39-6e7c1ab9c87f', 17 | title: 'Aptent Immitto', 18 | body: { 19 | value: 'Exputo molior nobis patria quadrum saepius valde.' 20 | } 21 | } 22 | }, 23 | { 24 | attributes: { 25 | uuid: 'df334ec5-216f-487e-8aa5-29a9224acb8f', 26 | title: 'In Interdico Nibh Nisl Utinam', 27 | body: { 28 | value: 'Cui refoveo similis.' 29 | } 30 | } 31 | } 32 | ]; 33 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './src/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: require('path').join(__dirname, './tsconfig.e2e.json') 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; -------------------------------------------------------------------------------- /Ch21_ddip-ember/ember-cli-build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 4 | 5 | module.exports = function(defaults) { 6 | let app = new EmberApp(defaults, { 7 | // Add options here 8 | }); 9 | 10 | // Use `app.import` to add additional libraries to the generated 11 | // output files. 12 | // 13 | // If you need to use different assets in different 14 | // environments, specify an object as the first parameter. That 15 | // object's keys should be the environment name and the values 16 | // should be the asset to use in that environment. 17 | // 18 | // If the library that you are including contains AMD or ES6 19 | // modules that you would like to import into your application 20 | // please specify an object with the list of modules as keys 21 | // along with the exports of each module as its value. 22 | 23 | return app.toTree(); 24 | }; 25 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/integration/components/entity-list-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupRenderingTest } from 'ember-qunit'; 3 | import { render } from '@ember/test-helpers'; 4 | import hbs from 'htmlbars-inline-precompile'; 5 | 6 | module('Integration | Component | entity-list', function(hooks) { 7 | setupRenderingTest(hooks); 8 | 9 | test('it renders', async function(assert) { 10 | // Set any properties with this.set('myProperty', 'value'); 11 | // Handle any actions with this.set('myAction', function(val) { ... }); 12 | 13 | await render(hbs`{{entity-list}}`); 14 | 15 | assert.equal(this.element.textContent.trim(), ''); 16 | 17 | // Template block usage: 18 | await render(hbs` 19 | {{#entity-list}} 20 | template block text 21 | {{/entity-list}} 22 | `); 23 | 24 | assert.equal(this.element.textContent.trim(), 'template block text'); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/articles/articles.component.ts: -------------------------------------------------------------------------------- 1 | // src/app/articles/articles.component.ts 2 | import { Component, OnInit } from '@angular/core'; 3 | import { ArticleService } from '../article.service' 4 | 5 | export class Article { 6 | attributes: object; 7 | } 8 | 9 | @Component({ 10 | selector: 'app-articles', 11 | templateUrl: './articles.component.html', 12 | styleUrls: ['./articles.component.css'], 13 | providers: [ArticleService] 14 | }) 15 | 16 | export class ArticlesComponent implements OnInit { 17 | title = 'ddip-ng'; 18 | articles: Article[]; 19 | selectedArticle: Article; 20 | 21 | constructor(private articleService: ArticleService) { } 22 | 23 | getArticles(): void { 24 | this.articleService.getArticles() 25 | .subscribe(articles => this.articles = articles); 26 | } 27 | 28 | ngOnInit(): void { 29 | this.getArticles(); 30 | } 31 | 32 | onSelect(article: Article): void { 33 | this.selectedArticle = article; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddip-vue", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.18.0", 12 | "vue": "^2.5.17" 13 | }, 14 | "devDependencies": { 15 | "@vue/cli-plugin-babel": "^3.0.3", 16 | "@vue/cli-plugin-eslint": "^3.0.3", 17 | "@vue/cli-service": "^3.0.3", 18 | "vue-template-compiler": "^2.5.17" 19 | }, 20 | "eslintConfig": { 21 | "root": true, 22 | "env": { 23 | "node": true 24 | }, 25 | "extends": [ 26 | "plugin:vue/essential", 27 | "eslint:recommended" 28 | ], 29 | "rules": {}, 30 | "parserOptions": { 31 | "parser": "babel-eslint" 32 | } 33 | }, 34 | "postcss": { 35 | "plugins": { 36 | "autoprefixer": {} 37 | } 38 | }, 39 | "browserslist": [ 40 | "> 1%", 41 | "last 2 versions", 42 | "not ie <= 8" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /Ch18_DdipReactNative/Article.js: -------------------------------------------------------------------------------- 1 | // Article.js 2 | import React from 'react'; 3 | import { StyleSheet, Text, View } from 'react-native'; 4 | import PropTypes from 'prop-types'; 5 | 6 | const Article = ({article}) => ( 7 | 8 | {article.attributes.title} 9 | ID: {article.id} 10 | Created: {article.attributes.created} 11 | Body: {article.attributes.body.value} 12 | 13 | ); 14 | 15 | Article.propTypes = { 16 | article: PropTypes.object 17 | }; 18 | 19 | const styles = StyleSheet.create({ 20 | item: { 21 | padding: 10, 22 | backgroundColor: '#eee', 23 | borderBottomColor: '#ccc', 24 | borderBottomWidth: 5, 25 | }, 26 | itemHeading: { 27 | marginTop: 10, 28 | paddingTop: 10, 29 | paddingBottom: 10, 30 | fontSize: 24, 31 | }, 32 | itemAttribute: { 33 | paddingTop: 10, 34 | paddingBottom: 10, 35 | } 36 | }); 37 | 38 | export default Article; 39 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | describe('AppComponent', () => { 4 | beforeEach(async(() => { 5 | TestBed.configureTestingModule({ 6 | declarations: [ 7 | AppComponent 8 | ], 9 | }).compileComponents(); 10 | })); 11 | it('should create the app', async(() => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.debugElement.componentInstance; 14 | expect(app).toBeTruthy(); 15 | })); 16 | it(`should have as title 'ddip-ng'`, async(() => { 17 | const fixture = TestBed.createComponent(AppComponent); 18 | const app = fixture.debugElement.componentInstance; 19 | expect(app.title).toEqual('ddip-ng'); 20 | })); 21 | it('should render title in a h1 tag', async(() => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | fixture.detectChanges(); 24 | const compiled = fixture.debugElement.nativeElement; 25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to ddip-ng!'); 26 | })); 27 | }); 28 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/README.md: -------------------------------------------------------------------------------- 1 | # DdipNg 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.2.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | 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. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | 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). 28 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/app/article.service.ts: -------------------------------------------------------------------------------- 1 | // src/app/article.service.ts 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient, HttpHeaders } from '@angular/common/http'; 4 | 5 | import { Observable, of } from 'rxjs'; 6 | import { catchError, map } from 'rxjs/operators'; 7 | 8 | import { Article } from './articles/articles.component' 9 | 10 | const httpOptions = { 11 | headers: new HttpHeaders({ 'Content-Type': 'application/json' }) 12 | } 13 | 14 | @Injectable({ 15 | providedIn: 'root' 16 | }) 17 | 18 | export class ArticleService { 19 | 20 | private articlesUrl = 'http://jsonapi-test.dd:8083/jsonapi/node/article'; 21 | 22 | constructor(private http: HttpClient) {} 23 | 24 | getArticles(): Observable { 25 | return this.http.get(this.articlesUrl, httpOptions) 26 | .pipe( 27 | map(res => res['data']) 28 | ) 29 | .pipe( 30 | catchError(this.handleError([])) 31 | ); 32 | } 33 | 34 | private handleError (result?: T) { 35 | return (error: any): Observable => { 36 | console.error(error); 37 | return of(result as T); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DdipEmber Tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "head-footer"}} 18 | {{content-for "test-head-footer"}} 19 | 20 | 21 | {{content-for "body"}} 22 | {{content-for "test-body"}} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{content-for "body-footer"}} 31 | {{content-for "test-body-footer"}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DdipEmber 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Ch20_ddip-vue/src/components/Articles.vue: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 52 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Freeware License, some rights reserved 2 | 3 | Copyright (c) 2018 Preston So 4 | 5 | Permission is hereby granted, free of charge, to anyone obtaining a copy 6 | of this software and associated documentation files (the "Software"), 7 | to work with the Software within the limits of freeware distribution and fair use. 8 | This includes the rights to use, copy, and modify the Software for personal use. 9 | Users are also allowed and encouraged to submit corrections and modifications 10 | to the Software for the benefit of other users. 11 | 12 | It is not allowed to reuse, modify, or redistribute the Software for 13 | commercial use in any way, or for a user’s educational materials such as books 14 | or blog articles without prior permission from the copyright holder. 15 | 16 | The above copyright notice and this permission notice need to be included 17 | in all copies or substantial portions of the software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(environment) { 4 | let ENV = { 5 | modulePrefix: 'ddip-ember', 6 | environment, 7 | rootURL: '/', 8 | locationType: 'auto', 9 | EmberENV: { 10 | FEATURES: { 11 | // Here you can enable experimental features on an ember canary build 12 | // e.g. 'with-controller': true 13 | }, 14 | EXTEND_PROTOTYPES: { 15 | // Prevent Ember Data from overriding Date.parse. 16 | Date: false 17 | } 18 | }, 19 | 20 | APP: { 21 | // Here you can pass flags/options to your application instance 22 | // when it is created 23 | } 24 | }; 25 | 26 | if (environment === 'development') { 27 | // ENV.APP.LOG_RESOLVER = true; 28 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 29 | // ENV.APP.LOG_TRANSITIONS = true; 30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 31 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 32 | } 33 | 34 | if (environment === 'test') { 35 | // Testem prefers this... 36 | ENV.locationType = 'none'; 37 | 38 | // keep test console output quieter 39 | ENV.APP.LOG_ACTIVE_GENERATION = false; 40 | ENV.APP.LOG_VIEW_LOOKUPS = false; 41 | 42 | ENV.APP.rootElement = '#ember-testing'; 43 | ENV.APP.autoboot = false; 44 | } 45 | 46 | if (environment === 'production') { 47 | // here you can enable a production-specific feature 48 | } 49 | 50 | return ENV; 51 | }; 52 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddip-ng", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "^6.1.0", 15 | "@angular/common": "^6.1.0", 16 | "@angular/compiler": "^6.1.0", 17 | "@angular/core": "^6.1.0", 18 | "@angular/forms": "^6.1.0", 19 | "@angular/http": "^6.1.0", 20 | "@angular/platform-browser": "^6.1.0", 21 | "@angular/platform-browser-dynamic": "^6.1.0", 22 | "@angular/router": "^6.1.0", 23 | "core-js": "^2.5.4", 24 | "rxjs": "~6.2.0", 25 | "zone.js": "~0.8.26" 26 | }, 27 | "devDependencies": { 28 | "@angular-devkit/build-angular": "~0.8.0", 29 | "@angular/cli": "~6.2.2", 30 | "@angular/compiler-cli": "^6.1.0", 31 | "@angular/language-service": "^6.1.0", 32 | "@types/jasmine": "~2.8.8", 33 | "@types/jasminewd2": "~2.0.3", 34 | "@types/node": "~8.9.4", 35 | "codelyzer": "~4.3.0", 36 | "jasmine-core": "~2.99.1", 37 | "jasmine-spec-reporter": "~4.2.1", 38 | "karma": "~3.0.0", 39 | "karma-chrome-launcher": "~2.2.0", 40 | "karma-coverage-istanbul-reporter": "~2.0.1", 41 | "karma-jasmine": "~1.1.2", 42 | "karma-jasmine-html-reporter": "^0.2.2", 43 | "protractor": "~5.4.0", 44 | "ts-node": "~7.0.0", 45 | "tslint": "~5.11.0", 46 | "typescript": "~2.9.2" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Ch18_DdipReactNative/App.js: -------------------------------------------------------------------------------- 1 | // App.js 2 | import React from 'react'; 3 | import { FlatList, ScrollView, StyleSheet, Text, View } from 'react-native'; 4 | import axios from 'axios'; 5 | import Article from './Article.js'; 6 | 7 | export default class App extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | articles: [], 12 | errored: false, 13 | loading: true 14 | }; 15 | } 16 | componentWillMount() { 17 | axios.get('http://jsonapi-test.dd:8083/jsonapi/node/article') 18 | .then(res => this.setState({ articles: res.data.data })) 19 | .catch(err => { 20 | console.log(err); 21 | this.setState({ errored: true }); 22 | }) 23 | .finally(() => this.setState({ loading: false })); 24 | } 25 | render() { 26 | return ( 27 | 28 | {this.state.errored ? ( 29 | Sorry, {'this'} information is not available at the moment. 30 | ) : ( 31 | 32 | {this.state.loading ? ( 33 | Loading ... 34 | ) : ( 35 | item.id} 38 | renderItem={({item}) => ( 39 |
40 | )} 41 | /> 42 | )} 43 | 44 | )} 45 | 46 | ); 47 | } 48 | } 49 | 50 | const styles = StyleSheet.create({ 51 | container: { 52 | flex: 1, 53 | backgroundColor: '#fff', 54 | paddingTop: 22, 55 | }, 56 | }); 57 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddip-ember", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "Small description for ddip-ember goes here", 6 | "repository": "", 7 | "license": "MIT", 8 | "author": "", 9 | "directories": { 10 | "doc": "doc", 11 | "test": "tests" 12 | }, 13 | "scripts": { 14 | "build": "ember build", 15 | "lint:hbs": "ember-template-lint .", 16 | "lint:js": "eslint .", 17 | "start": "ember serve", 18 | "test": "ember test" 19 | }, 20 | "devDependencies": { 21 | "@ember/jquery": "^0.5.2", 22 | "@ember/optional-features": "^0.6.3", 23 | "broccoli-asset-rev": "^2.7.0", 24 | "ember-ajax": "^3.1.0", 25 | "ember-cli": "~3.4.2", 26 | "ember-cli-app-version": "^3.2.0", 27 | "ember-cli-babel": "^6.16.0", 28 | "ember-cli-dependency-checker": "^3.0.0", 29 | "ember-cli-eslint": "^4.2.3", 30 | "ember-cli-htmlbars": "^3.0.0", 31 | "ember-cli-htmlbars-inline-precompile": "^1.0.3", 32 | "ember-cli-inject-live-reload": "^1.8.2", 33 | "ember-cli-qunit": "^4.3.2", 34 | "ember-cli-sri": "^2.1.1", 35 | "ember-cli-template-lint": "^1.0.0-beta.1", 36 | "ember-cli-uglify": "^2.1.0", 37 | "ember-data": "~3.4.0", 38 | "ember-export-application-global": "^2.0.0", 39 | "ember-load-initializers": "^1.1.0", 40 | "ember-maybe-import-regenerator": "^0.1.6", 41 | "ember-resolver": "^5.0.1", 42 | "ember-source": "~3.4.0", 43 | "ember-welcome-page": "^3.2.0", 44 | "eslint-plugin-ember": "^5.2.0", 45 | "loader.js": "^4.7.0", 46 | "qunit-dom": "^0.7.1" 47 | }, 48 | "engines": { 49 | "node": "6.* || 8.* || >= 10.*" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/README.md: -------------------------------------------------------------------------------- 1 | # ddip-ember 2 | 3 | This README outlines the details of collaborating on this Ember application. 4 | A short introduction of this app could easily go here. 5 | 6 | ## Prerequisites 7 | 8 | You will need the following things properly installed on your computer. 9 | 10 | * [Git](https://git-scm.com/) 11 | * [Node.js](https://nodejs.org/) (with npm) 12 | * [Ember CLI](https://ember-cli.com/) 13 | * [Google Chrome](https://google.com/chrome/) 14 | 15 | ## Installation 16 | 17 | * `git clone ` this repository 18 | * `cd ddip-ember` 19 | * `npm install` 20 | 21 | ## Running / Development 22 | 23 | * `ember serve` 24 | * Visit your app at [http://localhost:4200](http://localhost:4200). 25 | * Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). 26 | 27 | ### Code Generators 28 | 29 | Make use of the many generators for code, try `ember help generate` for more details 30 | 31 | ### Running Tests 32 | 33 | * `ember test` 34 | * `ember test --server` 35 | 36 | ### Linting 37 | 38 | * `npm run lint:hbs` 39 | * `npm run lint:js` 40 | * `npm run lint:js -- --fix` 41 | 42 | ### Building 43 | 44 | * `ember build` (development) 45 | * `ember build --environment production` (production) 46 | 47 | ### Deploying 48 | 49 | Specify what it takes to deploy your app. 50 | 51 | ## Further Reading / Useful Links 52 | 53 | * [ember.js](https://emberjs.com/) 54 | * [ember-cli](https://ember-cli.com/) 55 | * Development Browser Extensions 56 | * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) 57 | * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) 58 | -------------------------------------------------------------------------------- /Ch17_ddip-react/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DdipEmber Tests 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 |
28 |
29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Ch17_ddip-react/src/App.js: -------------------------------------------------------------------------------- 1 | // src/App.js 2 | import React, { Component } from 'react'; 3 | import { 4 | BrowserRouter as Router, 5 | Route, 6 | Link 7 | } from 'react-router-dom'; 8 | import axios from 'axios'; 9 | import Article from './Article.js'; 10 | 11 | class App extends Component { 12 | constructor(props) { 13 | super(props); 14 | this.state = { 15 | articles: [], 16 | loading: true, 17 | errored: false 18 | }; 19 | } 20 | componentWillMount() { 21 | axios.get('http://jsonapi-test.dd:8083/jsonapi/node/article') 22 | .then(res => this.setState({ articles: res.data.data })) 23 | .catch(err => { 24 | console.log(err); 25 | this.setState({ errored: true }); 26 | }) 27 | .finally(() => this.setState({ loading: false })); 28 | } 29 | render() { 30 | return ( 31 |
32 |

React app

33 | {this.state.errored ? ( 34 |

Sorry, {'this'} information is not available at the moment.

35 | ) : ( 36 |
37 | {this.state.loading ? ( 38 |

Loading ...

39 | ) : ( 40 | 41 |
42 |
    43 | {this.state.articles && this.state.articles.map(article => ( 44 |
  • 45 | {article.attributes.title} 46 |
  • 47 | ))} 48 |
49 | {this.state.articles && 50 | { 52 | let article = this.state.articles.find(article => article.id === match.params.articleID); 53 | return (
); 54 | } 55 | }/> 56 | } 57 |
58 |
59 | )} 60 |
61 | )} 62 |
63 | ); 64 | } 65 | } 66 | 67 | export default App; 68 | -------------------------------------------------------------------------------- /Ch17_ddip-react/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/assets/vendor.css: -------------------------------------------------------------------------------- 1 | #ember-welcome-page-id-selector { 2 | padding: 2em; 3 | box-shadow: 0 0 0px 10px #FFFBF5; 4 | font-family: "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif; 5 | font-size: 16px; 6 | line-height: 1.35em; 7 | background: #FFFBF5; 8 | color: #865931; 9 | height: 100vh; 10 | } 11 | #ember-welcome-page-id-selector img { 12 | max-width: 100%; 13 | } 14 | #ember-welcome-page-id-selector p { 15 | margin: 0 0 .75em; 16 | } 17 | #ember-welcome-page-id-selector h2 { 18 | color: #dd6a58; 19 | margin-top: 1em; 20 | font-size: 1.75em; 21 | line-height: 1.2 22 | } 23 | #ember-welcome-page-id-selector a:link, 24 | #ember-welcome-page-id-selector a:visited { 25 | color: #dd6a58; 26 | text-decoration: none; 27 | } 28 | #ember-welcome-page-id-selector a:hover, 29 | #ember-welcome-page-id-selector a:active { 30 | color: #c13c27; 31 | } 32 | #ember-welcome-page-id-selector .tomster { 33 | flex: 2; 34 | } 35 | #ember-welcome-page-id-selector .welcome { 36 | flex: 3; 37 | } 38 | #ember-welcome-page-id-selector .columns { 39 | display: flex; 40 | max-width: 960px; 41 | margin: 0 auto; 42 | } 43 | #ember-welcome-page-id-selector .welcome ol { 44 | list-style: disc; 45 | padding-left: 2em; 46 | margin-bottom: .75em; 47 | } 48 | #ember-welcome-page-id-selector .welcome > ol > li { 49 | padding-bottom: .5em; 50 | } 51 | #ember-welcome-page-id-selector .postscript { 52 | clear: both; 53 | text-align: center; 54 | padding-top: 3em; 55 | font-size: 14px; 56 | color: #888; 57 | font-style: italic; 58 | line-height: 2; 59 | } 60 | #ember-welcome-page-id-selector .postscript code { 61 | background-color: #F8E7CF; 62 | border-radius: 3px; 63 | font-family: Menlo, Courier, monospace; 64 | font-size: 0.9em; 65 | padding: 0.2em 0.5em; 66 | margin: 0 0.1em; 67 | } 68 | @media (max-width: 700px) { 69 | #ember-welcome-page-id-selector { 70 | padding: 1em; 71 | } 72 | #ember-welcome-page-id-selector .columns { 73 | flex-direction: column; 74 | } 75 | #ember-welcome-page-id-selector .welcome, 76 | #ember-welcome-page-id-selector .tomster { 77 | } 78 | #ember-welcome-page-id-selector .tomster img { 79 | width: 50%; 80 | margin: auto; 81 | display: block; 82 | } 83 | #ember-welcome-page-id-selector h2 { 84 | text-align: center; 85 | } 86 | } 87 | @media (max-width: 400px) { 88 | #ember-welcome-page-id-selector .tomster img { 89 | width: 60%; 90 | } 91 | #ember-welcome-page-id-selector .welcome, 92 | #ember-welcome-page-id-selector .tomster { 93 | width: 100%; 94 | float: none; 95 | margin: auto; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following for the Reflect API. */ 41 | // import 'core-js/es6/reflect'; 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** 50 | * Web Animations `@angular/platform-browser/animations` 51 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 52 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 53 | **/ 54 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 55 | 56 | /** 57 | * By default, zone.js will patch all possible macroTask and DomEvents 58 | * user can disable parts of macroTask/DomEvents patch by setting following flags 59 | */ 60 | 61 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 62 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 63 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 64 | 65 | /* 66 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 67 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 68 | */ 69 | // (window as any).__Zone_enable_cross_context_check = true; 70 | 71 | /*************************************************************************************************** 72 | * Zone JS is required by default for Angular itself. 73 | */ 74 | import 'zone.js/dist/zone'; // Included with Angular CLI. 75 | 76 | 77 | 78 | /*************************************************************************************************** 79 | * APPLICATION IMPORTS 80 | */ 81 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs/Rx" 22 | ], 23 | "import-spacing": true, 24 | "indent": [ 25 | true, 26 | "spaces" 27 | ], 28 | "interface-over-type-literal": true, 29 | "label-position": true, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-arg": true, 47 | "no-bitwise": true, 48 | "no-console": [ 49 | true, 50 | "debug", 51 | "info", 52 | "time", 53 | "timeEnd", 54 | "trace" 55 | ], 56 | "no-construct": true, 57 | "no-debugger": true, 58 | "no-duplicate-super": true, 59 | "no-empty": false, 60 | "no-empty-interface": true, 61 | "no-eval": true, 62 | "no-inferrable-types": [ 63 | true, 64 | "ignore-params" 65 | ], 66 | "no-misused-new": true, 67 | "no-non-null-assertion": true, 68 | "no-redundant-jsdoc": true, 69 | "no-shadowed-variable": true, 70 | "no-string-literal": false, 71 | "no-string-throw": true, 72 | "no-switch-case-fall-through": true, 73 | "no-trailing-whitespace": true, 74 | "no-unnecessary-initializer": true, 75 | "no-unused-expression": true, 76 | "no-use-before-declare": true, 77 | "no-var-keyword": true, 78 | "object-literal-sort-keys": false, 79 | "one-line": [ 80 | true, 81 | "check-open-brace", 82 | "check-catch", 83 | "check-else", 84 | "check-whitespace" 85 | ], 86 | "prefer-const": true, 87 | "quotemark": [ 88 | true, 89 | "single" 90 | ], 91 | "radix": true, 92 | "semicolon": [ 93 | true, 94 | "always" 95 | ], 96 | "triple-equals": [ 97 | true, 98 | "allow-null-check" 99 | ], 100 | "typedef-whitespace": [ 101 | true, 102 | { 103 | "call-signature": "nospace", 104 | "index-signature": "nospace", 105 | "parameter": "nospace", 106 | "property-declaration": "nospace", 107 | "variable-declaration": "nospace" 108 | } 109 | ], 110 | "unified-signatures": true, 111 | "variable-name": false, 112 | "whitespace": [ 113 | true, 114 | "check-branch", 115 | "check-decl", 116 | "check-operator", 117 | "check-separator", 118 | "check-type" 119 | ], 120 | "no-output-on-prefix": true, 121 | "use-input-property-decorator": true, 122 | "use-output-property-decorator": true, 123 | "use-host-property-decorator": true, 124 | "no-input-rename": true, 125 | "no-output-rename": true, 126 | "use-life-cycle-interface": true, 127 | "use-pipe-transform-interface": true, 128 | "component-class-suffix": true, 129 | "directive-class-suffix": true 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Ch19_ddip-ng/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "ddip-ng": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "prefix": "app", 11 | "schematics": {}, 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "outputPath": "dist/ddip-ng", 17 | "index": "src/index.html", 18 | "main": "src/main.ts", 19 | "polyfills": "src/polyfills.ts", 20 | "tsConfig": "src/tsconfig.app.json", 21 | "assets": [ 22 | "src/favicon.ico", 23 | "src/assets" 24 | ], 25 | "styles": [ 26 | "src/styles.css" 27 | ], 28 | "scripts": [] 29 | }, 30 | "configurations": { 31 | "production": { 32 | "fileReplacements": [ 33 | { 34 | "replace": "src/environments/environment.ts", 35 | "with": "src/environments/environment.prod.ts" 36 | } 37 | ], 38 | "optimization": true, 39 | "outputHashing": "all", 40 | "sourceMap": false, 41 | "extractCss": true, 42 | "namedChunks": false, 43 | "aot": true, 44 | "extractLicenses": true, 45 | "vendorChunk": false, 46 | "buildOptimizer": true 47 | } 48 | } 49 | }, 50 | "serve": { 51 | "builder": "@angular-devkit/build-angular:dev-server", 52 | "options": { 53 | "browserTarget": "ddip-ng:build" 54 | }, 55 | "configurations": { 56 | "production": { 57 | "browserTarget": "ddip-ng:build:production" 58 | } 59 | } 60 | }, 61 | "extract-i18n": { 62 | "builder": "@angular-devkit/build-angular:extract-i18n", 63 | "options": { 64 | "browserTarget": "ddip-ng:build" 65 | } 66 | }, 67 | "test": { 68 | "builder": "@angular-devkit/build-angular:karma", 69 | "options": { 70 | "main": "src/test.ts", 71 | "polyfills": "src/polyfills.ts", 72 | "tsConfig": "src/tsconfig.spec.json", 73 | "karmaConfig": "src/karma.conf.js", 74 | "styles": [ 75 | "src/styles.css" 76 | ], 77 | "scripts": [], 78 | "assets": [ 79 | "src/favicon.ico", 80 | "src/assets" 81 | ] 82 | } 83 | }, 84 | "lint": { 85 | "builder": "@angular-devkit/build-angular:tslint", 86 | "options": { 87 | "tsConfig": [ 88 | "src/tsconfig.app.json", 89 | "src/tsconfig.spec.json" 90 | ], 91 | "exclude": [ 92 | "**/node_modules/**" 93 | ] 94 | } 95 | } 96 | } 97 | }, 98 | "ddip-ng-e2e": { 99 | "root": "e2e/", 100 | "projectType": "application", 101 | "architect": { 102 | "e2e": { 103 | "builder": "@angular-devkit/build-angular:protractor", 104 | "options": { 105 | "protractorConfig": "e2e/protractor.conf.js", 106 | "devServerTarget": "ddip-ng:serve" 107 | }, 108 | "configurations": { 109 | "production": { 110 | "devServerTarget": "ddip-ng:serve:production" 111 | } 112 | } 113 | }, 114 | "lint": { 115 | "builder": "@angular-devkit/build-angular:tslint", 116 | "options": { 117 | "tsConfig": "e2e/tsconfig.e2e.json", 118 | "exclude": [ 119 | "**/node_modules/**" 120 | ] 121 | } 122 | } 123 | } 124 | } 125 | }, 126 | "defaultProject": "ddip-ng" 127 | } -------------------------------------------------------------------------------- /Ch17_ddip-react/src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | const isLocalhost = Boolean( 12 | window.location.hostname === 'localhost' || 13 | // [::1] is the IPv6 localhost address. 14 | window.location.hostname === '[::1]' || 15 | // 127.0.0.1/8 is considered localhost for IPv4. 16 | window.location.hostname.match( 17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 18 | ) 19 | ); 20 | 21 | export default function register() { 22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 23 | // The URL constructor is available in all browsers that support SW. 24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 25 | if (publicUrl.origin !== window.location.origin) { 26 | // Our service worker won't work if PUBLIC_URL is on a different origin 27 | // from what our page is served on. This might happen if a CDN is used to 28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 29 | return; 30 | } 31 | 32 | window.addEventListener('load', () => { 33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 34 | 35 | if (isLocalhost) { 36 | // This is running on localhost. Lets check if a service worker still exists or not. 37 | checkValidServiceWorker(swUrl); 38 | 39 | // Add some additional logging to localhost, pointing developers to the 40 | // service worker/PWA documentation. 41 | navigator.serviceWorker.ready.then(() => { 42 | console.log( 43 | 'This web app is being served cache-first by a service ' + 44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ' 45 | ); 46 | }); 47 | } else { 48 | // Is not local host. Just register service worker 49 | registerValidSW(swUrl); 50 | } 51 | }); 52 | } 53 | } 54 | 55 | function registerValidSW(swUrl) { 56 | navigator.serviceWorker 57 | .register(swUrl) 58 | .then(registration => { 59 | registration.onupdatefound = () => { 60 | const installingWorker = registration.installing; 61 | installingWorker.onstatechange = () => { 62 | if (installingWorker.state === 'installed') { 63 | if (navigator.serviceWorker.controller) { 64 | // At this point, the old content will have been purged and 65 | // the fresh content will have been added to the cache. 66 | // It's the perfect time to display a "New content is 67 | // available; please refresh." message in your web app. 68 | console.log('New content is available; please refresh.'); 69 | } else { 70 | // At this point, everything has been precached. 71 | // It's the perfect time to display a 72 | // "Content is cached for offline use." message. 73 | console.log('Content is cached for offline use.'); 74 | } 75 | } 76 | }; 77 | }; 78 | }) 79 | .catch(error => { 80 | console.error('Error during service worker registration:', error); 81 | }); 82 | } 83 | 84 | function checkValidServiceWorker(swUrl) { 85 | // Check if the service worker can be found. If it can't reload the page. 86 | fetch(swUrl) 87 | .then(response => { 88 | // Ensure service worker exists, and that we really are getting a JS file. 89 | if ( 90 | response.status === 404 || 91 | response.headers.get('content-type').indexOf('javascript') === -1 92 | ) { 93 | // No service worker found. Probably a different app. Reload the page. 94 | navigator.serviceWorker.ready.then(registration => { 95 | registration.unregister().then(() => { 96 | window.location.reload(); 97 | }); 98 | }); 99 | } else { 100 | // Service worker found. Proceed as normal. 101 | registerValidSW(swUrl); 102 | } 103 | }) 104 | .catch(() => { 105 | console.log( 106 | 'No internet connection found. App is running in offline mode.' 107 | ); 108 | }); 109 | } 110 | 111 | export function unregister() { 112 | if ('serviceWorker' in navigator) { 113 | navigator.serviceWorker.ready.then(registration => { 114 | registration.unregister(); 115 | }); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/assets/test-support.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 2.6.2 3 | * https://qunitjs.com/ 4 | * 5 | * Copyright jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * https://jquery.org/license 8 | * 9 | * Date: 2018-08-19T19:37Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header (excluding toolbar) */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-banner { 56 | height: 5px; 57 | } 58 | 59 | #qunit-filteredTest { 60 | padding: 0.5em 1em 0.5em 1em; 61 | color: #366097; 62 | background-color: #F4FF77; 63 | } 64 | 65 | #qunit-userAgent { 66 | padding: 0.5em 1em 0.5em 1em; 67 | color: #FFF; 68 | background-color: #2B81AF; 69 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 70 | } 71 | 72 | 73 | /** Toolbar */ 74 | 75 | #qunit-testrunner-toolbar { 76 | padding: 0.5em 1em 0.5em 1em; 77 | color: #5E740B; 78 | background-color: #EEE; 79 | } 80 | 81 | #qunit-testrunner-toolbar .clearfix { 82 | height: 0; 83 | clear: both; 84 | } 85 | 86 | #qunit-testrunner-toolbar label { 87 | display: inline-block; 88 | } 89 | 90 | #qunit-testrunner-toolbar input[type=checkbox], 91 | #qunit-testrunner-toolbar input[type=radio] { 92 | margin: 3px; 93 | vertical-align: -2px; 94 | } 95 | 96 | #qunit-testrunner-toolbar input[type=text] { 97 | box-sizing: border-box; 98 | height: 1.6em; 99 | } 100 | 101 | .qunit-url-config, 102 | .qunit-filter, 103 | #qunit-modulefilter { 104 | display: inline-block; 105 | line-height: 2.1em; 106 | } 107 | 108 | .qunit-filter, 109 | #qunit-modulefilter { 110 | float: right; 111 | position: relative; 112 | margin-left: 1em; 113 | } 114 | 115 | .qunit-url-config label { 116 | margin-right: 0.5em; 117 | } 118 | 119 | #qunit-modulefilter-search { 120 | box-sizing: border-box; 121 | width: 400px; 122 | } 123 | 124 | #qunit-modulefilter-search-container:after { 125 | position: absolute; 126 | right: 0.3em; 127 | content: "\25bc"; 128 | color: black; 129 | } 130 | 131 | #qunit-modulefilter-dropdown { 132 | /* align with #qunit-modulefilter-search */ 133 | box-sizing: border-box; 134 | width: 400px; 135 | position: absolute; 136 | right: 0; 137 | top: 50%; 138 | margin-top: 0.8em; 139 | 140 | border: 1px solid #D3D3D3; 141 | border-top: none; 142 | border-radius: 0 0 .25em .25em; 143 | color: #000; 144 | background-color: #F5F5F5; 145 | z-index: 99; 146 | } 147 | 148 | #qunit-modulefilter-dropdown a { 149 | color: inherit; 150 | text-decoration: none; 151 | } 152 | 153 | #qunit-modulefilter-dropdown .clickable.checked { 154 | font-weight: bold; 155 | color: #000; 156 | background-color: #D2E0E6; 157 | } 158 | 159 | #qunit-modulefilter-dropdown .clickable:hover { 160 | color: #FFF; 161 | background-color: #0D3349; 162 | } 163 | 164 | #qunit-modulefilter-actions { 165 | display: block; 166 | overflow: auto; 167 | 168 | /* align with #qunit-modulefilter-dropdown-list */ 169 | font: smaller/1.5em sans-serif; 170 | } 171 | 172 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > * { 173 | box-sizing: border-box; 174 | max-height: 2.8em; 175 | display: block; 176 | padding: 0.4em; 177 | } 178 | 179 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > button { 180 | float: right; 181 | font: inherit; 182 | } 183 | 184 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child { 185 | /* insert padding to align with checkbox margins */ 186 | padding-left: 3px; 187 | } 188 | 189 | #qunit-modulefilter-dropdown-list { 190 | max-height: 200px; 191 | overflow-y: auto; 192 | margin: 0; 193 | border-top: 2px groove threedhighlight; 194 | padding: 0.4em 0 0; 195 | font: smaller/1.5em sans-serif; 196 | } 197 | 198 | #qunit-modulefilter-dropdown-list li { 199 | white-space: nowrap; 200 | overflow: hidden; 201 | text-overflow: ellipsis; 202 | } 203 | 204 | #qunit-modulefilter-dropdown-list .clickable { 205 | display: block; 206 | padding-left: 0.15em; 207 | } 208 | 209 | 210 | /** Tests: Pass/Fail */ 211 | 212 | #qunit-tests { 213 | list-style-position: inside; 214 | } 215 | 216 | #qunit-tests li { 217 | padding: 0.4em 1em 0.4em 1em; 218 | border-bottom: 1px solid #FFF; 219 | list-style-position: inside; 220 | } 221 | 222 | #qunit-tests > li { 223 | display: none; 224 | } 225 | 226 | #qunit-tests li.running, 227 | #qunit-tests li.pass, 228 | #qunit-tests li.fail, 229 | #qunit-tests li.skipped, 230 | #qunit-tests li.aborted { 231 | display: list-item; 232 | } 233 | 234 | #qunit-tests.hidepass { 235 | position: relative; 236 | } 237 | 238 | #qunit-tests.hidepass li.running, 239 | #qunit-tests.hidepass li.pass:not(.todo) { 240 | visibility: hidden; 241 | position: absolute; 242 | width: 0; 243 | height: 0; 244 | padding: 0; 245 | border: 0; 246 | margin: 0; 247 | } 248 | 249 | #qunit-tests li strong { 250 | cursor: pointer; 251 | } 252 | 253 | #qunit-tests li.skipped strong { 254 | cursor: default; 255 | } 256 | 257 | #qunit-tests li a { 258 | padding: 0.5em; 259 | color: #C2CCD1; 260 | text-decoration: none; 261 | } 262 | 263 | #qunit-tests li p a { 264 | padding: 0.25em; 265 | color: #6B6464; 266 | } 267 | #qunit-tests li a:hover, 268 | #qunit-tests li a:focus { 269 | color: #000; 270 | } 271 | 272 | #qunit-tests li .runtime { 273 | float: right; 274 | font-size: smaller; 275 | } 276 | 277 | .qunit-assert-list { 278 | margin-top: 0.5em; 279 | padding: 0.5em; 280 | 281 | background-color: #FFF; 282 | 283 | border-radius: 5px; 284 | } 285 | 286 | .qunit-source { 287 | margin: 0.6em 0 0.3em; 288 | } 289 | 290 | .qunit-collapsed { 291 | display: none; 292 | } 293 | 294 | #qunit-tests table { 295 | border-collapse: collapse; 296 | margin-top: 0.2em; 297 | } 298 | 299 | #qunit-tests th { 300 | text-align: right; 301 | vertical-align: top; 302 | padding: 0 0.5em 0 0; 303 | } 304 | 305 | #qunit-tests td { 306 | vertical-align: top; 307 | } 308 | 309 | #qunit-tests pre { 310 | margin: 0; 311 | white-space: pre-wrap; 312 | word-wrap: break-word; 313 | } 314 | 315 | #qunit-tests del { 316 | color: #374E0C; 317 | background-color: #E0F2BE; 318 | text-decoration: none; 319 | } 320 | 321 | #qunit-tests ins { 322 | color: #500; 323 | background-color: #FFCACA; 324 | text-decoration: none; 325 | } 326 | 327 | /*** Test Counts */ 328 | 329 | #qunit-tests b.counts { color: #000; } 330 | #qunit-tests b.passed { color: #5E740B; } 331 | #qunit-tests b.failed { color: #710909; } 332 | 333 | #qunit-tests li li { 334 | padding: 5px; 335 | background-color: #FFF; 336 | border-bottom: none; 337 | list-style-position: inside; 338 | } 339 | 340 | /*** Passing Styles */ 341 | 342 | #qunit-tests li li.pass { 343 | color: #3C510C; 344 | background-color: #FFF; 345 | border-left: 10px solid #C6E746; 346 | } 347 | 348 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 349 | #qunit-tests .pass .test-name { color: #366097; } 350 | 351 | #qunit-tests .pass .test-actual, 352 | #qunit-tests .pass .test-expected { color: #999; } 353 | 354 | #qunit-banner.qunit-pass { background-color: #C6E746; } 355 | 356 | /*** Failing Styles */ 357 | 358 | #qunit-tests li li.fail { 359 | color: #710909; 360 | background-color: #FFF; 361 | border-left: 10px solid #EE5757; 362 | white-space: pre; 363 | } 364 | 365 | #qunit-tests > li:last-child { 366 | border-radius: 0 0 5px 5px; 367 | } 368 | 369 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 370 | #qunit-tests .fail .test-name, 371 | #qunit-tests .fail .module-name { color: #000; } 372 | 373 | #qunit-tests .fail .test-actual { color: #EE5757; } 374 | #qunit-tests .fail .test-expected { color: #008000; } 375 | 376 | #qunit-banner.qunit-fail { background-color: #EE5757; } 377 | 378 | 379 | /*** Aborted tests */ 380 | #qunit-tests .aborted { color: #000; background-color: orange; } 381 | /*** Skipped tests */ 382 | 383 | #qunit-tests .skipped { 384 | background-color: #EBECE9; 385 | } 386 | 387 | #qunit-tests .qunit-todo-label, 388 | #qunit-tests .qunit-skipped-label { 389 | background-color: #F4FF77; 390 | display: inline-block; 391 | font-style: normal; 392 | color: #366097; 393 | line-height: 1.8em; 394 | padding: 0 0.5em; 395 | margin: -0.4em 0.4em -0.4em 0; 396 | } 397 | 398 | #qunit-tests .qunit-todo-label { 399 | background-color: #EEE; 400 | } 401 | 402 | /** Result */ 403 | 404 | #qunit-testresult { 405 | color: #2B81AF; 406 | background-color: #D2E0E6; 407 | 408 | border-bottom: 1px solid #FFF; 409 | } 410 | #qunit-testresult .clearfix { 411 | height: 0; 412 | clear: both; 413 | } 414 | #qunit-testresult .module-name { 415 | font-weight: 700; 416 | } 417 | #qunit-testresult-display { 418 | padding: 0.5em 1em 0.5em 1em; 419 | width: 85%; 420 | float:left; 421 | } 422 | #qunit-testresult-controls { 423 | padding: 0.5em 1em 0.5em 1em; 424 | width: 10%; 425 | float:left; 426 | } 427 | 428 | /** Fixture */ 429 | 430 | #qunit-fixture { 431 | position: absolute; 432 | top: -10000px; 433 | left: -10000px; 434 | width: 1000px; 435 | height: 1000px; 436 | } 437 | 438 | #ember-testing-container { 439 | position: relative; 440 | background: white; 441 | bottom: 0; 442 | right: 0; 443 | width: 640px; 444 | height: 384px; 445 | overflow: auto; 446 | z-index: 98; 447 | border: 1px solid #ccc; 448 | margin: 0 auto; 449 | } 450 | 451 | #ember-testing-container.full-screen { 452 | width: 100%; 453 | height: 100%; 454 | overflow: auto; 455 | z-index: 98; 456 | border: none; 457 | } 458 | 459 | #ember-testing { 460 | width: 200%; 461 | height: 200%; 462 | transform: scale(0.5); 463 | transform-origin: top left; 464 | } 465 | 466 | .full-screen #ember-testing { 467 | position: absolute; 468 | width: 100%; 469 | height: 100%; 470 | transform: scale(1); 471 | } 472 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/assets/ddip-ember.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | 5 | ;define('ddip-ember/adapters/application', ['exports', 'ember-data'], function (exports, _emberData) { 6 | 'use strict'; 7 | 8 | Object.defineProperty(exports, "__esModule", { 9 | value: true 10 | }); 11 | exports.default = _emberData.default.JSONAPIAdapter.extend({ 12 | host: 'http://jsonapi-test.dd:8083', 13 | namespace: 'jsonapi', 14 | 15 | pathForType(type) { 16 | let entityPath; 17 | switch (type) { 18 | case 'node--article': 19 | entityPath = 'node/article'; 20 | break; 21 | case 'node--page': 22 | entityPath = 'node/page'; 23 | break; 24 | } 25 | return entityPath; 26 | }, 27 | 28 | buildURL() { 29 | return this._super(...arguments); 30 | } 31 | }); 32 | }); 33 | ;define('ddip-ember/app', ['exports', 'ddip-ember/resolver', 'ember-load-initializers', 'ddip-ember/config/environment'], function (exports, _resolver, _emberLoadInitializers, _environment) { 34 | 'use strict'; 35 | 36 | Object.defineProperty(exports, "__esModule", { 37 | value: true 38 | }); 39 | 40 | 41 | const App = Ember.Application.extend({ 42 | modulePrefix: _environment.default.modulePrefix, 43 | podModulePrefix: _environment.default.podModulePrefix, 44 | Resolver: _resolver.default 45 | }); 46 | 47 | (0, _emberLoadInitializers.default)(App, _environment.default.modulePrefix); 48 | 49 | exports.default = App; 50 | }); 51 | ;define('ddip-ember/components/entity-list', ['exports'], function (exports) { 52 | 'use strict'; 53 | 54 | Object.defineProperty(exports, "__esModule", { 55 | value: true 56 | }); 57 | exports.default = Ember.Component.extend({}); 58 | }); 59 | ;define('ddip-ember/components/welcome-page', ['exports', 'ember-welcome-page/components/welcome-page'], function (exports, _welcomePage) { 60 | 'use strict'; 61 | 62 | Object.defineProperty(exports, "__esModule", { 63 | value: true 64 | }); 65 | Object.defineProperty(exports, 'default', { 66 | enumerable: true, 67 | get: function () { 68 | return _welcomePage.default; 69 | } 70 | }); 71 | }); 72 | ;define('ddip-ember/helpers/app-version', ['exports', 'ddip-ember/config/environment', 'ember-cli-app-version/utils/regexp'], function (exports, _environment, _regexp) { 73 | 'use strict'; 74 | 75 | Object.defineProperty(exports, "__esModule", { 76 | value: true 77 | }); 78 | exports.appVersion = appVersion; 79 | function appVersion(_, hash = {}) { 80 | const version = _environment.default.APP.version; 81 | // e.g. 1.0.0-alpha.1+4jds75hf 82 | 83 | // Allow use of 'hideSha' and 'hideVersion' For backwards compatibility 84 | let versionOnly = hash.versionOnly || hash.hideSha; 85 | let shaOnly = hash.shaOnly || hash.hideVersion; 86 | 87 | let match = null; 88 | 89 | if (versionOnly) { 90 | if (hash.showExtended) { 91 | match = version.match(_regexp.versionExtendedRegExp); // 1.0.0-alpha.1 92 | } 93 | // Fallback to just version 94 | if (!match) { 95 | match = version.match(_regexp.versionRegExp); // 1.0.0 96 | } 97 | } 98 | 99 | if (shaOnly) { 100 | match = version.match(_regexp.shaRegExp); // 4jds75hf 101 | } 102 | 103 | return match ? match[0] : version; 104 | } 105 | 106 | exports.default = Ember.Helper.helper(appVersion); 107 | }); 108 | ;define('ddip-ember/helpers/pluralize', ['exports', 'ember-inflector/lib/helpers/pluralize'], function (exports, _pluralize) { 109 | 'use strict'; 110 | 111 | Object.defineProperty(exports, "__esModule", { 112 | value: true 113 | }); 114 | exports.default = _pluralize.default; 115 | }); 116 | ;define('ddip-ember/helpers/singularize', ['exports', 'ember-inflector/lib/helpers/singularize'], function (exports, _singularize) { 117 | 'use strict'; 118 | 119 | Object.defineProperty(exports, "__esModule", { 120 | value: true 121 | }); 122 | exports.default = _singularize.default; 123 | }); 124 | ;define('ddip-ember/initializers/app-version', ['exports', 'ember-cli-app-version/initializer-factory', 'ddip-ember/config/environment'], function (exports, _initializerFactory, _environment) { 125 | 'use strict'; 126 | 127 | Object.defineProperty(exports, "__esModule", { 128 | value: true 129 | }); 130 | 131 | 132 | let name, version; 133 | if (_environment.default.APP) { 134 | name = _environment.default.APP.name; 135 | version = _environment.default.APP.version; 136 | } 137 | 138 | exports.default = { 139 | name: 'App Version', 140 | initialize: (0, _initializerFactory.default)(name, version) 141 | }; 142 | }); 143 | ;define('ddip-ember/initializers/container-debug-adapter', ['exports', 'ember-resolver/resolvers/classic/container-debug-adapter'], function (exports, _containerDebugAdapter) { 144 | 'use strict'; 145 | 146 | Object.defineProperty(exports, "__esModule", { 147 | value: true 148 | }); 149 | exports.default = { 150 | name: 'container-debug-adapter', 151 | 152 | initialize() { 153 | let app = arguments[1] || arguments[0]; 154 | 155 | app.register('container-debug-adapter:main', _containerDebugAdapter.default); 156 | app.inject('container-debug-adapter:main', 'namespace', 'application:main'); 157 | } 158 | }; 159 | }); 160 | ;define('ddip-ember/initializers/ember-data', ['exports', 'ember-data/setup-container', 'ember-data'], function (exports, _setupContainer) { 161 | 'use strict'; 162 | 163 | Object.defineProperty(exports, "__esModule", { 164 | value: true 165 | }); 166 | exports.default = { 167 | name: 'ember-data', 168 | initialize: _setupContainer.default 169 | }; 170 | }); 171 | ;define('ddip-ember/initializers/export-application-global', ['exports', 'ddip-ember/config/environment'], function (exports, _environment) { 172 | 'use strict'; 173 | 174 | Object.defineProperty(exports, "__esModule", { 175 | value: true 176 | }); 177 | exports.initialize = initialize; 178 | function initialize() { 179 | var application = arguments[1] || arguments[0]; 180 | if (_environment.default.exportApplicationGlobal !== false) { 181 | var theGlobal; 182 | if (typeof window !== 'undefined') { 183 | theGlobal = window; 184 | } else if (typeof global !== 'undefined') { 185 | theGlobal = global; 186 | } else if (typeof self !== 'undefined') { 187 | theGlobal = self; 188 | } else { 189 | // no reasonable global, just bail 190 | return; 191 | } 192 | 193 | var value = _environment.default.exportApplicationGlobal; 194 | var globalName; 195 | 196 | if (typeof value === 'string') { 197 | globalName = value; 198 | } else { 199 | globalName = Ember.String.classify(_environment.default.modulePrefix); 200 | } 201 | 202 | if (!theGlobal[globalName]) { 203 | theGlobal[globalName] = application; 204 | 205 | application.reopen({ 206 | willDestroy: function () { 207 | this._super.apply(this, arguments); 208 | delete theGlobal[globalName]; 209 | } 210 | }); 211 | } 212 | } 213 | } 214 | 215 | exports.default = { 216 | name: 'export-application-global', 217 | 218 | initialize: initialize 219 | }; 220 | }); 221 | ;define('ddip-ember/instance-initializers/ember-data', ['exports', 'ember-data/initialize-store-service'], function (exports, _initializeStoreService) { 222 | 'use strict'; 223 | 224 | Object.defineProperty(exports, "__esModule", { 225 | value: true 226 | }); 227 | exports.default = { 228 | name: 'ember-data', 229 | initialize: _initializeStoreService.default 230 | }; 231 | }); 232 | ;define('ddip-ember/models/node--article', ['exports', 'ember-data'], function (exports, _emberData) { 233 | 'use strict'; 234 | 235 | Object.defineProperty(exports, "__esModule", { 236 | value: true 237 | }); 238 | exports.default = _emberData.default.Model.extend({ 239 | uuid: _emberData.default.attr(), 240 | title: _emberData.default.attr(), 241 | created: _emberData.default.attr(), 242 | body: _emberData.default.attr() 243 | }); 244 | }); 245 | ;define('ddip-ember/models/node--page', ['exports', 'ember-data'], function (exports, _emberData) { 246 | 'use strict'; 247 | 248 | Object.defineProperty(exports, "__esModule", { 249 | value: true 250 | }); 251 | exports.default = _emberData.default.Model.extend({ 252 | uuid: _emberData.default.attr(), 253 | title: _emberData.default.attr(), 254 | created: _emberData.default.attr(), 255 | body: _emberData.default.attr() 256 | }); 257 | }); 258 | ;define('ddip-ember/resolver', ['exports', 'ember-resolver'], function (exports, _emberResolver) { 259 | 'use strict'; 260 | 261 | Object.defineProperty(exports, "__esModule", { 262 | value: true 263 | }); 264 | exports.default = _emberResolver.default; 265 | }); 266 | ;define('ddip-ember/router', ['exports', 'ddip-ember/config/environment'], function (exports, _environment) { 267 | 'use strict'; 268 | 269 | Object.defineProperty(exports, "__esModule", { 270 | value: true 271 | }); 272 | 273 | 274 | const Router = Ember.Router.extend({ 275 | location: _environment.default.locationType, 276 | rootURL: _environment.default.rootURL 277 | }); 278 | 279 | Router.map(function () { 280 | this.route('articles'); 281 | this.route('pages'); 282 | }); 283 | 284 | exports.default = Router; 285 | }); 286 | ;define('ddip-ember/routes/articles', ['exports'], function (exports) { 287 | 'use strict'; 288 | 289 | Object.defineProperty(exports, "__esModule", { 290 | value: true 291 | }); 292 | exports.default = Ember.Route.extend({ 293 | model() { 294 | return this.get('store').findAll('node--article'); 295 | } 296 | }); 297 | }); 298 | ;define('ddip-ember/routes/pages', ['exports'], function (exports) { 299 | 'use strict'; 300 | 301 | Object.defineProperty(exports, "__esModule", { 302 | value: true 303 | }); 304 | exports.default = Ember.Route.extend({ 305 | model() { 306 | return this.get('store').findAll('node--page'); 307 | } 308 | }); 309 | }); 310 | ;define('ddip-ember/services/ajax', ['exports', 'ember-ajax/services/ajax'], function (exports, _ajax) { 311 | 'use strict'; 312 | 313 | Object.defineProperty(exports, "__esModule", { 314 | value: true 315 | }); 316 | Object.defineProperty(exports, 'default', { 317 | enumerable: true, 318 | get: function () { 319 | return _ajax.default; 320 | } 321 | }); 322 | }); 323 | ;define("ddip-ember/templates/application", ["exports"], function (exports) { 324 | "use strict"; 325 | 326 | Object.defineProperty(exports, "__esModule", { 327 | value: true 328 | }); 329 | exports.default = Ember.HTMLBars.template({ "id": "24asPTZ4", "block": "{\"symbols\":[],\"statements\":[[7,\"h1\"],[9],[4,\"link-to\",[\"index\"],null,{\"statements\":[[0,\"Ember app\"]],\"parameters\":[]},null],[10],[0,\"\\n\"],[7,\"ul\"],[9],[0,\"\\n \"],[7,\"li\"],[9],[4,\"link-to\",[\"articles\"],null,{\"statements\":[[0,\"Articles\"]],\"parameters\":[]},null],[10],[0,\"\\n \"],[7,\"li\"],[9],[4,\"link-to\",[\"pages\"],null,{\"statements\":[[0,\"Pages\"]],\"parameters\":[]},null],[10],[0,\"\\n\"],[10],[0,\"\\n\"],[1,[21,\"outlet\"],false],[0,\"\\n\"]],\"hasEval\":false}", "meta": { "moduleName": "ddip-ember/templates/application.hbs" } }); 330 | }); 331 | ;define("ddip-ember/templates/articles", ["exports"], function (exports) { 332 | "use strict"; 333 | 334 | Object.defineProperty(exports, "__esModule", { 335 | value: true 336 | }); 337 | exports.default = Ember.HTMLBars.template({ "id": "YeU7awII", "block": "{\"symbols\":[],\"statements\":[[1,[27,\"entity-list\",null,[[\"title\",\"entities\"],[\"List of articles\",[23,[\"model\"]]]]],false],[0,\"\\n\"]],\"hasEval\":false}", "meta": { "moduleName": "ddip-ember/templates/articles.hbs" } }); 338 | }); 339 | ;define("ddip-ember/templates/components/entity-list", ["exports"], function (exports) { 340 | "use strict"; 341 | 342 | Object.defineProperty(exports, "__esModule", { 343 | value: true 344 | }); 345 | exports.default = Ember.HTMLBars.template({ "id": "0k/+4MQ6", "block": "{\"symbols\":[\"entity\"],\"statements\":[[7,\"h2\"],[9],[1,[21,\"title\"],false],[10],[0,\"\\n\"],[7,\"ul\"],[9],[0,\"\\n\"],[4,\"each\",[[23,[\"entities\"]]],null,{\"statements\":[[0,\" \"],[7,\"li\"],[9],[0,\"\\n \"],[1,[22,1,[\"title\"]],false],[0,\"\\n \"],[7,\"ul\"],[9],[0,\"\\n \"],[7,\"li\"],[9],[1,[22,1,[\"created\"]],false],[10],[0,\"\\n \"],[7,\"li\"],[9],[1,[22,1,[\"body\",\"value\"]],false],[10],[0,\"\\n \"],[10],[0,\"\\n \"],[10],[0,\"\\n\"]],\"parameters\":[1]},null],[10],[0,\"\\n\"]],\"hasEval\":false}", "meta": { "moduleName": "ddip-ember/templates/components/entity-list.hbs" } }); 346 | }); 347 | ;define("ddip-ember/templates/pages", ["exports"], function (exports) { 348 | "use strict"; 349 | 350 | Object.defineProperty(exports, "__esModule", { 351 | value: true 352 | }); 353 | exports.default = Ember.HTMLBars.template({ "id": "PzVA1JGJ", "block": "{\"symbols\":[],\"statements\":[[1,[27,\"entity-list\",null,[[\"title\",\"entities\"],[\"List of pages\",[23,[\"model\"]]]]],false],[0,\"\\n\"]],\"hasEval\":false}", "meta": { "moduleName": "ddip-ember/templates/pages.hbs" } }); 354 | }); 355 | ; 356 | 357 | ;define('ddip-ember/config/environment', [], function() { 358 | var prefix = 'ddip-ember'; 359 | try { 360 | var metaName = prefix + '/config/environment'; 361 | var rawConfig = document.querySelector('meta[name="' + metaName + '"]').getAttribute('content'); 362 | var config = JSON.parse(unescape(rawConfig)); 363 | 364 | var exports = { 'default': config }; 365 | 366 | Object.defineProperty(exports, '__esModule', { value: true }); 367 | 368 | return exports; 369 | } 370 | catch(err) { 371 | throw new Error('Could not read config from meta tag with name "' + metaName + '".'); 372 | } 373 | 374 | }); 375 | 376 | ; 377 | if (!runningTests) { 378 | require("ddip-ember/app")["default"].create({"name":"ddip-ember","version":"0.0.0+1b5d6d48"}); 379 | } 380 | 381 | //# sourceMappingURL=ddip-ember.map 382 | -------------------------------------------------------------------------------- /Ch21_ddip-ember/dist/assets/ddip-ember.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["vendor/ember-cli/app-prefix.js","ddip-ember/adapters/application.js","ddip-ember/app.js","ddip-ember/components/entity-list.js","ddip-ember/components/welcome-page.js","ddip-ember/helpers/app-version.js","ddip-ember/helpers/pluralize.js","ddip-ember/helpers/singularize.js","ddip-ember/initializers/app-version.js","ddip-ember/initializers/container-debug-adapter.js","ddip-ember/initializers/ember-data.js","ddip-ember/initializers/export-application-global.js","ddip-ember/instance-initializers/ember-data.js","ddip-ember/models/node--article.js","ddip-ember/models/node--page.js","ddip-ember/resolver.js","ddip-ember/router.js","ddip-ember/routes/articles.js","ddip-ember/routes/pages.js","ddip-ember/services/ajax.js","ddip-ember/templates/application.js","ddip-ember/templates/articles.js","ddip-ember/templates/components/entity-list.js","ddip-ember/templates/pages.js","vendor/ember-cli/app-suffix.js","vendor/ember-cli/app-config.js","vendor/ember-cli/app-boot.js"],"sourcesContent":["'use strict';\n\n\n","define('ddip-ember/adapters/application', ['exports', 'ember-data'], function (exports, _emberData) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = _emberData.default.JSONAPIAdapter.extend({\n host: 'http://jsonapi-test.dd:8083',\n namespace: 'jsonapi',\n\n pathForType(type) {\n let entityPath;\n switch (type) {\n case 'node--article':\n entityPath = 'node/article';\n break;\n case 'node--page':\n entityPath = 'node/page';\n break;\n }\n return entityPath;\n },\n\n buildURL() {\n return this._super(...arguments);\n }\n });\n});","define('ddip-ember/app', ['exports', 'ddip-ember/resolver', 'ember-load-initializers', 'ddip-ember/config/environment'], function (exports, _resolver, _emberLoadInitializers, _environment) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n\n\n const App = Ember.Application.extend({\n modulePrefix: _environment.default.modulePrefix,\n podModulePrefix: _environment.default.podModulePrefix,\n Resolver: _resolver.default\n });\n\n (0, _emberLoadInitializers.default)(App, _environment.default.modulePrefix);\n\n exports.default = App;\n});","define('ddip-ember/components/entity-list', ['exports'], function (exports) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.Component.extend({});\n});","define('ddip-ember/components/welcome-page', ['exports', 'ember-welcome-page/components/welcome-page'], function (exports, _welcomePage) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(exports, 'default', {\n enumerable: true,\n get: function () {\n return _welcomePage.default;\n }\n });\n});","define('ddip-ember/helpers/app-version', ['exports', 'ddip-ember/config/environment', 'ember-cli-app-version/utils/regexp'], function (exports, _environment, _regexp) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.appVersion = appVersion;\n function appVersion(_, hash = {}) {\n const version = _environment.default.APP.version;\n // e.g. 1.0.0-alpha.1+4jds75hf\n\n // Allow use of 'hideSha' and 'hideVersion' For backwards compatibility\n let versionOnly = hash.versionOnly || hash.hideSha;\n let shaOnly = hash.shaOnly || hash.hideVersion;\n\n let match = null;\n\n if (versionOnly) {\n if (hash.showExtended) {\n match = version.match(_regexp.versionExtendedRegExp); // 1.0.0-alpha.1\n }\n // Fallback to just version\n if (!match) {\n match = version.match(_regexp.versionRegExp); // 1.0.0\n }\n }\n\n if (shaOnly) {\n match = version.match(_regexp.shaRegExp); // 4jds75hf\n }\n\n return match ? match[0] : version;\n }\n\n exports.default = Ember.Helper.helper(appVersion);\n});","define('ddip-ember/helpers/pluralize', ['exports', 'ember-inflector/lib/helpers/pluralize'], function (exports, _pluralize) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = _pluralize.default;\n});","define('ddip-ember/helpers/singularize', ['exports', 'ember-inflector/lib/helpers/singularize'], function (exports, _singularize) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = _singularize.default;\n});","define('ddip-ember/initializers/app-version', ['exports', 'ember-cli-app-version/initializer-factory', 'ddip-ember/config/environment'], function (exports, _initializerFactory, _environment) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n\n\n let name, version;\n if (_environment.default.APP) {\n name = _environment.default.APP.name;\n version = _environment.default.APP.version;\n }\n\n exports.default = {\n name: 'App Version',\n initialize: (0, _initializerFactory.default)(name, version)\n };\n});","define('ddip-ember/initializers/container-debug-adapter', ['exports', 'ember-resolver/resolvers/classic/container-debug-adapter'], function (exports, _containerDebugAdapter) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = {\n name: 'container-debug-adapter',\n\n initialize() {\n let app = arguments[1] || arguments[0];\n\n app.register('container-debug-adapter:main', _containerDebugAdapter.default);\n app.inject('container-debug-adapter:main', 'namespace', 'application:main');\n }\n };\n});","define('ddip-ember/initializers/ember-data', ['exports', 'ember-data/setup-container', 'ember-data'], function (exports, _setupContainer) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = {\n name: 'ember-data',\n initialize: _setupContainer.default\n };\n});","define('ddip-ember/initializers/export-application-global', ['exports', 'ddip-ember/config/environment'], function (exports, _environment) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.initialize = initialize;\n function initialize() {\n var application = arguments[1] || arguments[0];\n if (_environment.default.exportApplicationGlobal !== false) {\n var theGlobal;\n if (typeof window !== 'undefined') {\n theGlobal = window;\n } else if (typeof global !== 'undefined') {\n theGlobal = global;\n } else if (typeof self !== 'undefined') {\n theGlobal = self;\n } else {\n // no reasonable global, just bail\n return;\n }\n\n var value = _environment.default.exportApplicationGlobal;\n var globalName;\n\n if (typeof value === 'string') {\n globalName = value;\n } else {\n globalName = Ember.String.classify(_environment.default.modulePrefix);\n }\n\n if (!theGlobal[globalName]) {\n theGlobal[globalName] = application;\n\n application.reopen({\n willDestroy: function () {\n this._super.apply(this, arguments);\n delete theGlobal[globalName];\n }\n });\n }\n }\n }\n\n exports.default = {\n name: 'export-application-global',\n\n initialize: initialize\n };\n});","define('ddip-ember/instance-initializers/ember-data', ['exports', 'ember-data/initialize-store-service'], function (exports, _initializeStoreService) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = {\n name: 'ember-data',\n initialize: _initializeStoreService.default\n };\n});","define('ddip-ember/models/node--article', ['exports', 'ember-data'], function (exports, _emberData) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = _emberData.default.Model.extend({\n uuid: _emberData.default.attr(),\n title: _emberData.default.attr(),\n created: _emberData.default.attr(),\n body: _emberData.default.attr()\n });\n});","define('ddip-ember/models/node--page', ['exports', 'ember-data'], function (exports, _emberData) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = _emberData.default.Model.extend({\n uuid: _emberData.default.attr(),\n title: _emberData.default.attr(),\n created: _emberData.default.attr(),\n body: _emberData.default.attr()\n });\n});","define('ddip-ember/resolver', ['exports', 'ember-resolver'], function (exports, _emberResolver) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = _emberResolver.default;\n});","define('ddip-ember/router', ['exports', 'ddip-ember/config/environment'], function (exports, _environment) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n\n\n const Router = Ember.Router.extend({\n location: _environment.default.locationType,\n rootURL: _environment.default.rootURL\n });\n\n Router.map(function () {\n this.route('articles');\n this.route('pages');\n });\n\n exports.default = Router;\n});","define('ddip-ember/routes/articles', ['exports'], function (exports) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.Route.extend({\n model() {\n return this.get('store').findAll('node--article');\n }\n });\n});","define('ddip-ember/routes/pages', ['exports'], function (exports) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.Route.extend({\n model() {\n return this.get('store').findAll('node--page');\n }\n });\n});","define('ddip-ember/services/ajax', ['exports', 'ember-ajax/services/ajax'], function (exports, _ajax) {\n 'use strict';\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(exports, 'default', {\n enumerable: true,\n get: function () {\n return _ajax.default;\n }\n });\n});","define(\"ddip-ember/templates/application\", [\"exports\"], function (exports) {\n \"use strict\";\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.HTMLBars.template({ \"id\": \"24asPTZ4\", \"block\": \"{\\\"symbols\\\":[],\\\"statements\\\":[[7,\\\"h1\\\"],[9],[4,\\\"link-to\\\",[\\\"index\\\"],null,{\\\"statements\\\":[[0,\\\"Ember app\\\"]],\\\"parameters\\\":[]},null],[10],[0,\\\"\\\\n\\\"],[7,\\\"ul\\\"],[9],[0,\\\"\\\\n \\\"],[7,\\\"li\\\"],[9],[4,\\\"link-to\\\",[\\\"articles\\\"],null,{\\\"statements\\\":[[0,\\\"Articles\\\"]],\\\"parameters\\\":[]},null],[10],[0,\\\"\\\\n \\\"],[7,\\\"li\\\"],[9],[4,\\\"link-to\\\",[\\\"pages\\\"],null,{\\\"statements\\\":[[0,\\\"Pages\\\"]],\\\"parameters\\\":[]},null],[10],[0,\\\"\\\\n\\\"],[10],[0,\\\"\\\\n\\\"],[1,[21,\\\"outlet\\\"],false],[0,\\\"\\\\n\\\"]],\\\"hasEval\\\":false}\", \"meta\": { \"moduleName\": \"ddip-ember/templates/application.hbs\" } });\n});","define(\"ddip-ember/templates/articles\", [\"exports\"], function (exports) {\n \"use strict\";\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.HTMLBars.template({ \"id\": \"YeU7awII\", \"block\": \"{\\\"symbols\\\":[],\\\"statements\\\":[[1,[27,\\\"entity-list\\\",null,[[\\\"title\\\",\\\"entities\\\"],[\\\"List of articles\\\",[23,[\\\"model\\\"]]]]],false],[0,\\\"\\\\n\\\"]],\\\"hasEval\\\":false}\", \"meta\": { \"moduleName\": \"ddip-ember/templates/articles.hbs\" } });\n});","define(\"ddip-ember/templates/components/entity-list\", [\"exports\"], function (exports) {\n \"use strict\";\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.HTMLBars.template({ \"id\": \"0k/+4MQ6\", \"block\": \"{\\\"symbols\\\":[\\\"entity\\\"],\\\"statements\\\":[[7,\\\"h2\\\"],[9],[1,[21,\\\"title\\\"],false],[10],[0,\\\"\\\\n\\\"],[7,\\\"ul\\\"],[9],[0,\\\"\\\\n\\\"],[4,\\\"each\\\",[[23,[\\\"entities\\\"]]],null,{\\\"statements\\\":[[0,\\\" \\\"],[7,\\\"li\\\"],[9],[0,\\\"\\\\n \\\"],[1,[22,1,[\\\"title\\\"]],false],[0,\\\"\\\\n \\\"],[7,\\\"ul\\\"],[9],[0,\\\"\\\\n \\\"],[7,\\\"li\\\"],[9],[1,[22,1,[\\\"created\\\"]],false],[10],[0,\\\"\\\\n \\\"],[7,\\\"li\\\"],[9],[1,[22,1,[\\\"body\\\",\\\"value\\\"]],false],[10],[0,\\\"\\\\n \\\"],[10],[0,\\\"\\\\n \\\"],[10],[0,\\\"\\\\n\\\"]],\\\"parameters\\\":[1]},null],[10],[0,\\\"\\\\n\\\"]],\\\"hasEval\\\":false}\", \"meta\": { \"moduleName\": \"ddip-ember/templates/components/entity-list.hbs\" } });\n});","define(\"ddip-ember/templates/pages\", [\"exports\"], function (exports) {\n \"use strict\";\n\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.default = Ember.HTMLBars.template({ \"id\": \"PzVA1JGJ\", \"block\": \"{\\\"symbols\\\":[],\\\"statements\\\":[[1,[27,\\\"entity-list\\\",null,[[\\\"title\\\",\\\"entities\\\"],[\\\"List of pages\\\",[23,[\\\"model\\\"]]]]],false],[0,\\\"\\\\n\\\"]],\\\"hasEval\\\":false}\", \"meta\": { \"moduleName\": \"ddip-ember/templates/pages.hbs\" } });\n});","\n","define('ddip-ember/config/environment', [], function() {\n var prefix = 'ddip-ember';\ntry {\n var metaName = prefix + '/config/environment';\n var rawConfig = document.querySelector('meta[name=\"' + metaName + '\"]').getAttribute('content');\n var config = JSON.parse(unescape(rawConfig));\n\n var exports = { 'default': config };\n\n Object.defineProperty(exports, '__esModule', { value: true });\n\n return exports;\n}\ncatch(err) {\n throw new Error('Could not read config from meta tag with name \"' + metaName + '\".');\n}\n\n});\n","\n if (!runningTests) {\n require(\"ddip-ember/app\")[\"default\"].create({\"name\":\"ddip-ember\",\"version\":\"0.0.0+1b5d6d48\"});\n }\n \n"],"names":[],"mappings":"AAAA;AACA;AACA;;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;","file":"ddip-ember.js"} --------------------------------------------------------------------------------