+Aurelia +Paket +FAKE
Interim commit; there may still be leftover files from the Aurelia tutorial
This commit is contained in:
34
src/app/src/app.html
Normal file
34
src/app/src/app.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<require from="bootstrap/css/bootstrap.css"></require>
|
||||
<require from="./styles.css"></require>
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a route-href="route: home" class="navbar-brand">myPrayerJournal</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<loading-indicator loading.bind="router.isNavigating || api.isRequesting"></loading-indicator>
|
||||
<div class="container body-content">
|
||||
<div class="row">
|
||||
<h2 class.bind="'mpj-page-title' + ('' === pageTitle ? ' hidden' : '')" textcontent.bind="pageTitle"></h2>
|
||||
<router-view class="col-xs-12" swap-order="with"></router-view>
|
||||
</div>
|
||||
<div class="row">
|
||||
<footer class="mpj-footer">
|
||||
<p class="text-right">myPrayerJournal v0.8.1</p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
27
src/app/src/app.ts
Normal file
27
src/app/src/app.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import {Router, RouterConfiguration} from "aurelia-router"
|
||||
import {EventAggregator} from "aurelia-event-aggregator"
|
||||
import {inject} from "aurelia-framework"
|
||||
import {PageTitle} from "./messages"
|
||||
import {WebAPI} from "./web-api"
|
||||
|
||||
@inject(WebAPI, EventAggregator)
|
||||
export class App {
|
||||
router: Router;
|
||||
pageTitle: string;
|
||||
|
||||
constructor(public api: WebAPI, private ea: EventAggregator) {
|
||||
this.ea.subscribe(PageTitle, msg => this.pageTitle = msg.title)
|
||||
}
|
||||
|
||||
configureRouter(config: RouterConfiguration, router: Router){
|
||||
config.title = "myPrayerJournal"
|
||||
config.options.pushState = true
|
||||
config.options.root = "/"
|
||||
config.map([
|
||||
{ route: "", moduleId: "home", name: "home", title: "Welcome" },
|
||||
{ route: 'contacts/:id', moduleId: 'contact-detail', name:'contacts' }
|
||||
])
|
||||
|
||||
this.router = router
|
||||
}
|
||||
}
|
||||
42
src/app/src/contact-detail.html
Normal file
42
src/app/src/contact-detail.html
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Profile</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">First Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" placeholder="first name" class="form-control" value.bind="contact.firstName">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Last Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" placeholder="last name" class="form-control" value.bind="contact.lastName">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Email</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" placeholder="email" class="form-control" value.bind="contact.email">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Phone Number</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" placeholder="phone number" class="form-control" value.bind="contact.phoneNumber">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-bar">
|
||||
<button class="btn btn-success" click.delegate="save()" disabled.bind="!canSave">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
58
src/app/src/contact-detail.ts
Normal file
58
src/app/src/contact-detail.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {inject} from 'aurelia-framework';
|
||||
import {EventAggregator} from 'aurelia-event-aggregator';
|
||||
import {WebAPI} from './web-api';
|
||||
import {ContactUpdated,ContactViewed} from './messages';
|
||||
import {areEqual} from './utility';
|
||||
|
||||
interface Contact {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
@inject(WebAPI, EventAggregator)
|
||||
export class ContactDetail {
|
||||
routeConfig;
|
||||
contact: Contact;
|
||||
originalContact: Contact;
|
||||
|
||||
constructor(private api: WebAPI, private ea: EventAggregator) { }
|
||||
|
||||
activate(params, routeConfig) {
|
||||
this.routeConfig = routeConfig;
|
||||
|
||||
return this.api.getContactDetails(params.id).then(contact => {
|
||||
this.contact = <Contact>contact;
|
||||
this.routeConfig.navModel.setTitle(this.contact.firstName);
|
||||
this.originalContact = JSON.parse(JSON.stringify(this.contact));
|
||||
this.ea.publish(new ContactViewed(this.contact));
|
||||
});
|
||||
}
|
||||
|
||||
get canSave() {
|
||||
return this.contact.firstName && this.contact.lastName && !this.api.isRequesting;
|
||||
}
|
||||
|
||||
save() {
|
||||
this.api.saveContact(this.contact).then(contact => {
|
||||
this.contact = <Contact>contact;
|
||||
this.routeConfig.navModel.setTitle(this.contact.firstName);
|
||||
this.originalContact = JSON.parse(JSON.stringify(this.contact));
|
||||
this.ea.publish(new ContactUpdated(this.contact));
|
||||
});
|
||||
}
|
||||
|
||||
canDeactivate() {
|
||||
if(!areEqual(this.originalContact, this.contact)){
|
||||
let result = confirm('You have unsaved changes. Are you sure you wish to leave?');
|
||||
|
||||
if(!result) {
|
||||
this.ea.publish(new ContactViewed(this.contact));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
12
src/app/src/contact-list.html
Normal file
12
src/app/src/contact-list.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div class="contact-list">
|
||||
<ul class="list-group">
|
||||
<li repeat.for="contact of contacts" class="list-group-item ${contact.id === $parent.selectedId ? 'active' : ''}">
|
||||
<a route-href="route: contacts; params.bind: {id:contact.id}" click.delegate="$parent.select(contact)">
|
||||
<h4 class="list-group-item-heading">${contact.firstName} ${contact.lastName}</h4>
|
||||
<p class="list-group-item-text">${contact.email}</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
28
src/app/src/contact-list.ts
Normal file
28
src/app/src/contact-list.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import {EventAggregator} from 'aurelia-event-aggregator';
|
||||
import {WebAPI} from './web-api';
|
||||
import {ContactUpdated, ContactViewed} from './messages';
|
||||
import {inject} from 'aurelia-framework';
|
||||
|
||||
@inject(WebAPI, EventAggregator)
|
||||
export class ContactList {
|
||||
contacts;
|
||||
selectedId = 0;
|
||||
|
||||
constructor(private api: WebAPI, ea: EventAggregator) {
|
||||
ea.subscribe(ContactViewed, msg => this.select(msg.contact));
|
||||
ea.subscribe(ContactUpdated, msg => {
|
||||
let id = msg.contact.id;
|
||||
let found = this.contacts.find(x => x.id == id);
|
||||
Object.assign(found, msg.contact);
|
||||
});
|
||||
}
|
||||
|
||||
created() {
|
||||
this.api.getContactList().then(contacts => this.contacts = contacts);
|
||||
}
|
||||
|
||||
select(contact) {
|
||||
this.selectedId = contact.id;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
4
src/app/src/environment.ts
Normal file
4
src/app/src/environment.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
debug: true,
|
||||
testing: true
|
||||
};
|
||||
11
src/app/src/home.html
Normal file
11
src/app/src/home.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<p>
|
||||
myPrayerJournal is a place where individuals can record their prayer requests, record that they prayed for them,
|
||||
update them as God moves in the situation, and record a final answer received on that request. It will also allow
|
||||
individuals to review their answered prayers.
|
||||
</p>
|
||||
<p>
|
||||
This site is currently in very limited alpha, as it is being developed with a core group of test users. If this is
|
||||
something you are interested in using, check back around mid-June 2017 to check on the development progress.
|
||||
</p>
|
||||
</template>
|
||||
10
src/app/src/home.ts
Normal file
10
src/app/src/home.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import {inject} from 'aurelia-framework';
|
||||
import {EventAggregator} from "aurelia-event-aggregator"
|
||||
import {PageTitle} from "./messages"
|
||||
|
||||
@inject(EventAggregator)
|
||||
export class Home {
|
||||
constructor(private ea: EventAggregator) {
|
||||
this.ea.publish(new PageTitle("Welcome to myPrayerJournal"));
|
||||
}
|
||||
}
|
||||
18
src/app/src/main.ts
Normal file
18
src/app/src/main.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import {Aurelia} from 'aurelia-framework'
|
||||
import environment from './environment';
|
||||
|
||||
export function configure(aurelia: Aurelia) {
|
||||
aurelia.use
|
||||
.standardConfiguration()
|
||||
.feature('resources');
|
||||
|
||||
if (environment.debug) {
|
||||
aurelia.use.developmentLogging();
|
||||
}
|
||||
|
||||
if (environment.testing) {
|
||||
aurelia.use.plugin('aurelia-testing');
|
||||
}
|
||||
|
||||
aurelia.start().then(() => aurelia.setRoot());
|
||||
}
|
||||
11
src/app/src/messages.ts
Normal file
11
src/app/src/messages.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export class ContactUpdated {
|
||||
constructor(public contact) { }
|
||||
}
|
||||
|
||||
export class ContactViewed {
|
||||
constructor(public contact) { }
|
||||
}
|
||||
|
||||
export class PageTitle {
|
||||
constructor(public title: string) { }
|
||||
}
|
||||
15
src/app/src/resources/elements/loading-indicator.ts
Normal file
15
src/app/src/resources/elements/loading-indicator.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as nprogress from 'nprogress';
|
||||
import {bindable, noView} from 'aurelia-framework';
|
||||
|
||||
@noView(['nprogress/nprogress.css'])
|
||||
export class LoadingIndicator {
|
||||
@bindable loading = false;
|
||||
|
||||
loadingChanged(newValue) {
|
||||
if (newValue) {
|
||||
nprogress.start();
|
||||
} else {
|
||||
nprogress.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/app/src/resources/index.ts
Normal file
5
src/app/src/resources/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import {FrameworkConfiguration} from 'aurelia-framework';
|
||||
|
||||
export function configure(config: FrameworkConfiguration) {
|
||||
config.globalResources(['./elements/loading-indicator']);
|
||||
}
|
||||
35
src/app/src/styles.css
Normal file
35
src/app/src/styles.css
Normal file
@@ -0,0 +1,35 @@
|
||||
body {
|
||||
padding-top: 70px;
|
||||
padding-bottom: 20px;
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
|
||||
}
|
||||
|
||||
/* Wrapping element */
|
||||
/* Set some basic padding to keep content from hitting the edges */
|
||||
.body-content {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.material-icons.md-18 {
|
||||
font-size: 18px;
|
||||
}
|
||||
.material-icons.md-24 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.material-icons.md-36 {
|
||||
font-size: 36px;
|
||||
}
|
||||
.material-icons.md-48 {
|
||||
font-size: 48px;
|
||||
}
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.mpj-page-title {
|
||||
border-bottom: solid 1px lightgray;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.mpj-footer {
|
||||
border-top: solid 1px lightgray;
|
||||
margin-top: 20px;
|
||||
}
|
||||
3
src/app/src/utility.ts
Normal file
3
src/app/src/utility.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function areEqual(obj1, obj2) {
|
||||
return Object.keys(obj1).every((key) => obj2.hasOwnProperty(key) && (obj1[key] === obj2[key]));
|
||||
};
|
||||
96
src/app/src/web-api.ts
Normal file
96
src/app/src/web-api.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
let latency = 200;
|
||||
let id = 0;
|
||||
|
||||
function getId(){
|
||||
return ++id;
|
||||
}
|
||||
|
||||
let contacts = [
|
||||
{
|
||||
id:getId(),
|
||||
firstName:'John',
|
||||
lastName:'Tolkien',
|
||||
email:'tolkien@inklings.com',
|
||||
phoneNumber:'867-5309'
|
||||
},
|
||||
{
|
||||
id:getId(),
|
||||
firstName:'Clive',
|
||||
lastName:'Lewis',
|
||||
email:'lewis@inklings.com',
|
||||
phoneNumber:'867-5309'
|
||||
},
|
||||
{
|
||||
id:getId(),
|
||||
firstName:'Owen',
|
||||
lastName:'Barfield',
|
||||
email:'barfield@inklings.com',
|
||||
phoneNumber:'867-5309'
|
||||
},
|
||||
{
|
||||
id:getId(),
|
||||
firstName:'Charles',
|
||||
lastName:'Williams',
|
||||
email:'williams@inklings.com',
|
||||
phoneNumber:'867-5309'
|
||||
},
|
||||
{
|
||||
id:getId(),
|
||||
firstName:'Roger',
|
||||
lastName:'Green',
|
||||
email:'green@inklings.com',
|
||||
phoneNumber:'867-5309'
|
||||
}
|
||||
];
|
||||
|
||||
export class WebAPI {
|
||||
isRequesting = false;
|
||||
|
||||
getContactList(){
|
||||
this.isRequesting = true;
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
let results = contacts.map(x => { return {
|
||||
id:x.id,
|
||||
firstName:x.firstName,
|
||||
lastName:x.lastName,
|
||||
email:x.email
|
||||
}});
|
||||
resolve(results);
|
||||
this.isRequesting = false;
|
||||
}, latency);
|
||||
});
|
||||
}
|
||||
|
||||
getContactDetails(id){
|
||||
this.isRequesting = true;
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
let found = contacts.filter(x => x.id == id)[0];
|
||||
resolve(JSON.parse(JSON.stringify(found)));
|
||||
this.isRequesting = false;
|
||||
}, latency);
|
||||
});
|
||||
}
|
||||
|
||||
saveContact(contact){
|
||||
this.isRequesting = true;
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
let instance = JSON.parse(JSON.stringify(contact));
|
||||
let found = contacts.filter(x => x.id == contact.id)[0];
|
||||
|
||||
if(found){
|
||||
let index = contacts.indexOf(found);
|
||||
contacts[index] = instance;
|
||||
}else{
|
||||
instance.id = getId();
|
||||
contacts.push(instance);
|
||||
}
|
||||
|
||||
this.isRequesting = false;
|
||||
resolve(instance);
|
||||
}, latency);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user