From 39c8a1b9ae565d9c2b67ad57cec34140a2e85f44 Mon Sep 17 00:00:00 2001 From: Luis Nunez Date: Mon, 23 Jan 2017 16:59:24 -0200 Subject: [PATCH 1/2] adding want services --- src/app/app.component.ts | 2 + src/app/app.module.ts | 11 +++ src/app/app.scss | 20 +++--- src/app/app.settings.ts | 2 +- src/components/fieldBuilder/fieldBuilder.html | 17 ++++- src/components/fieldBuilder/fieldBuilder.ts | 62 ++++++++++++++-- src/domain/Want.ts | 10 +++ src/pages/addOffer/addOffer.ts | 2 +- src/pages/addWant/addWant.html | 15 ++++ src/pages/addWant/addWant.scss | 3 + src/pages/addWant/addWant.ts | 45 ++++++++++++ src/pages/home/home.ts | 3 +- src/pages/memberDetail/memberDetail.html | 2 +- src/pages/memberDetail/memberDetail.ts | 26 ++++--- src/pages/members/members.ts | 19 +++-- src/pages/offer/offer.html | 48 ++++++------- src/pages/offer/offer.ts | 14 +++- src/pages/offerDetail/offerDetail.html | 47 +++++++------ src/pages/offerDetail/offerDetail.ts | 11 ++- src/pages/page2/page2.html | 23 ------ src/pages/page2/page2.scss | 3 - src/pages/page2/page2.ts | 37 ---------- src/pages/want/want.html | 48 +++++++++++++ src/pages/want/want.scss | 3 + src/pages/want/want.ts | 66 +++++++++++++++++ src/pages/wantDetail/wantDetail.html | 43 ++++++++++++ src/pages/wantDetail/wantDetail.scss | 3 + src/pages/wantDetail/wantDetail.ts | 45 ++++++++++++ src/services/AuthService.ts | 21 +++--- src/services/ConfigService.ts | 2 +- src/services/HttpBasicAuth.ts | 56 +++++++++++++-- src/services/MemberService.ts | 4 ++ src/services/OfferService.ts | 29 ++------ src/services/WantService.ts | 35 ++++++++++ src/test/mock-offers.ts | 70 ------------------- 35 files changed, 579 insertions(+), 268 deletions(-) create mode 100644 src/domain/Want.ts create mode 100644 src/pages/addWant/addWant.html create mode 100644 src/pages/addWant/addWant.scss create mode 100644 src/pages/addWant/addWant.ts delete mode 100644 src/pages/page2/page2.html delete mode 100644 src/pages/page2/page2.scss delete mode 100644 src/pages/page2/page2.ts create mode 100644 src/pages/want/want.html create mode 100644 src/pages/want/want.scss create mode 100644 src/pages/want/want.ts create mode 100644 src/pages/wantDetail/wantDetail.html create mode 100644 src/pages/wantDetail/wantDetail.scss create mode 100644 src/pages/wantDetail/wantDetail.ts create mode 100644 src/services/WantService.ts diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f9694e5..50ea1b1 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -7,6 +7,7 @@ import { AuthService } from '../services/AuthService'; import { LoginPage } from '../pages/login/login'; import { HomePage } from '../pages/home/home'; import { OfferPage } from '../pages/offer/offer'; +import { WantPage } from '../pages/want/want'; import { MembersPage } from '../pages/members/members'; @Component({ @@ -27,6 +28,7 @@ export class LetsApp { this.pages = [ { title: 'Home', component: HomePage }, { title: 'Offers', component: OfferPage }, + { title: 'Wants', component: WantPage }, { title: 'Members', component: MembersPage } ]; this.initializeApp(); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 4a4ae5c..1f5fe09 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -8,6 +8,7 @@ import { AuthService } from '../services/AuthService'; import { ConfigService } from '../services/ConfigService'; import { TransactionService } from '../services/TransactionService'; import { OfferService } from '../services/OfferService'; +import { WantService } from '../services/WantService'; import { AlertService } from '../services/AlertService'; import { MemberService } from '../services/MemberService'; import { CategoriesService } from '../services/CategoriesService'; @@ -20,6 +21,9 @@ import { HomePage } from '../pages/home/home'; import { OfferPage } from '../pages/offer/offer'; import { OfferDetailPage } from '../pages/offerDetail/offerDetail'; import { AddOfferPage } from '../pages/addOffer/addOffer'; +import { WantPage } from '../pages/want/want'; +import { WantDetailPage } from '../pages/wantDetail/wantDetail'; +import { AddWantPage } from '../pages/addWant/addWant'; import { UnixTimeToMoment } from '../pipes/UnixTimeToMoment'; import { ObjectKeys } from '../pipes/ObjectKeys'; import { MembersPage } from '../pages/members/members'; @@ -34,6 +38,9 @@ import { MemberDetailModal } from '../pages/memberDetail/memberDetail'; OfferPage, OfferDetailPage, AddOfferPage, + WantPage, + WantDetailPage, + AddWantPage, UnixTimeToMoment, ObjectKeys, MembersPage, @@ -55,6 +62,9 @@ import { MemberDetailModal } from '../pages/memberDetail/memberDetail'; OfferPage, OfferDetailPage, AddOfferPage, + WantPage, + WantDetailPage, + AddWantPage, MembersPage, MemberDetailModal ], @@ -64,6 +74,7 @@ import { MemberDetailModal } from '../pages/memberDetail/memberDetail'; ConfigService, TransactionService, OfferService, + WantService, AlertService, CategoriesService, FieldTypesService, diff --git a/src/app/app.scss b/src/app/app.scss index 4e73aaa..67ad6ef 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -15,6 +15,10 @@ // for the .md, .ios, or .wp mode classes. The mode class is // automatically applied to the element in the app. +html { + font-size: 1em; +} + ion-header { text-align: center; .toolbar-background { @@ -34,17 +38,9 @@ ion-menu { } } -.ui.cards { - .ui.card { - .description { - max-height: 55px; - overflow-y: hidden; - } - } -} - -.ui.card { +.ui.card>.content{ .author { + text-align: right; padding-top: 10px; } } @@ -62,4 +58,8 @@ ion-menu { position: fixed; right: 15px; bottom: 15px; +} + +.ui.dropdown.button { + text-align: center; } \ No newline at end of file diff --git a/src/app/app.settings.ts b/src/app/app.settings.ts index a717176..a807d4f 100644 --- a/src/app/app.settings.ts +++ b/src/app/app.settings.ts @@ -12,7 +12,7 @@ export class AppSettings { transactions: `${this.SERVER_URL}/transaction`, offers: `${this.SERVER_URL}/offer`, wants: `${this.SERVER_URL}/want`, - members: '${this.SERVER_URL}/member' + members: `${this.SERVER_URL}/member` }; } diff --git a/src/components/fieldBuilder/fieldBuilder.html b/src/components/fieldBuilder/fieldBuilder.html index 02e1d75..bded1b0 100644 --- a/src/components/fieldBuilder/fieldBuilder.html +++ b/src/components/fieldBuilder/fieldBuilder.html @@ -10,7 +10,7 @@ - + +
- +
+ + +
diff --git a/src/components/fieldBuilder/fieldBuilder.ts b/src/components/fieldBuilder/fieldBuilder.ts index c3869d9..27175bd 100644 --- a/src/components/fieldBuilder/fieldBuilder.ts +++ b/src/components/fieldBuilder/fieldBuilder.ts @@ -1,7 +1,12 @@ import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { AppSettings } from '../../app/app.settings'; +import { HttpBasicAuth } from '../../services/HttpBasicAuth'; import { CategoriesService } from '../../services/CategoriesService'; +import { FieldTypesService } from '../../services/FieldTypesService'; +import { AlertService } from '../../services/AlertService'; import * as moment from 'moment'; +import * as lodash from 'lodash'; declare var $: any; @Component({ @@ -14,13 +19,24 @@ export class FieldBuilderComponent implements OnInit, AfterViewInit { @Output() changed = new EventEmitter(); validationMessages: any = {}; private categories; + private fieldTypes; + private autocompleteService; + private autocompleteFragment; - constructor(private formBuilder: FormBuilder, - private categoriesService: CategoriesService) { + constructor(private settings: AppSettings, + private httpBasicAuth: HttpBasicAuth, + private formBuilder: FormBuilder, + private alertService: AlertService, + private categoriesService: CategoriesService, + private fieldTypesService: FieldTypesService) { this.categoriesService.categories.subscribe( response => { this.categories = response; }); + this.fieldTypesService.fieldTypes.subscribe( + response => { + this.fieldTypes = response; + }); } ngOnInit(): void { @@ -101,6 +117,17 @@ export class FieldBuilderComponent implements OnInit, AfterViewInit { } }); break; + case 'member': + this.autocompleteService = this.fieldTypes[this.field.type].autocomplete; + this.autocompleteSearch(); + $field.parents('.ui.dropdown').dropdown({ + onChange: (value) => { + let fieldValue = {}; + fieldValue[this.field.name] = value; + this.fieldForm.setValue(fieldValue); + } + }); + break; } } @@ -124,9 +151,34 @@ export class FieldBuilderComponent implements OnInit, AfterViewInit { } addImage() { - (navigator).camera.getPicture((image) => { - this.field.imgSrc = image; - }); + (navigator).camera.getPicture(image => { + this.field.imgSrc = `data:image/jpeg;base64,${image}`; + }, null, { + sourceType: 0 // PHOTOLIBRARY + }); + } + + takePhoto() { + (navigator).camera.getPicture(image => { + this.field.imgSrc = `data:image/jpeg;base64,${image}`; + }, null, { + sourceType: 1 // CAMERA + }); + } + + autocompleteSearch(event?) { + let target = event && (event.target || event.srcElement); + this.autocompleteFragment = (target && target.value) || ''; + this.httpBasicAuth.getAutocomplete(this.autocompleteService, this.autocompleteFragment) + .subscribe( + (response: any) => { + this.field._options = lodash.map(response, (option: any, key) => { + option.id = key; + return option; + }); + }, + error => this.alertService.showError('Connection problem!') + ); } } \ No newline at end of file diff --git a/src/domain/Want.ts b/src/domain/Want.ts new file mode 100644 index 0000000..f93b164 --- /dev/null +++ b/src/domain/Want.ts @@ -0,0 +1,10 @@ +export class Want { + [property: string]: any; + id?: string; + title: string; + description: string; + user_id: string; + name: string; + expires: string; + uri?: string; +} \ No newline at end of file diff --git a/src/pages/addOffer/addOffer.ts b/src/pages/addOffer/addOffer.ts index 0190052..9304cc3 100644 --- a/src/pages/addOffer/addOffer.ts +++ b/src/pages/addOffer/addOffer.ts @@ -35,7 +35,7 @@ export class AddOfferPage implements OnInit { response => this.viewCtrl.dismiss({ success: true }), - error => this.alertService.showError('Connection problem!') + error => this.alertService.showError(error) ); } diff --git a/src/pages/addWant/addWant.html b/src/pages/addWant/addWant.html new file mode 100644 index 0000000..5080b61 --- /dev/null +++ b/src/pages/addWant/addWant.html @@ -0,0 +1,15 @@ + + +

New Want

+ + + +
+
+ + + + \ No newline at end of file diff --git a/src/pages/addWant/addWant.scss b/src/pages/addWant/addWant.scss new file mode 100644 index 0000000..507c872 --- /dev/null +++ b/src/pages/addWant/addWant.scss @@ -0,0 +1,3 @@ +page-add-want { + +} \ No newline at end of file diff --git a/src/pages/addWant/addWant.ts b/src/pages/addWant/addWant.ts new file mode 100644 index 0000000..fd9423a --- /dev/null +++ b/src/pages/addWant/addWant.ts @@ -0,0 +1,45 @@ +import { Component, OnInit } from '@angular/core'; +import { ViewController } from 'ionic-angular'; +import { WantService } from '../../services/WantService'; +import { AlertService } from '../../services/AlertService'; +import { Want } from '../../domain/Want'; + +@Component({ + selector: 'page-add-want', + templateUrl: 'addWant.html' +}) +export class AddWantPage implements OnInit { + private definitionWant: any; + private fields: Array; + private want: Want; + + constructor(private viewCtrl: ViewController, + private wantService: WantService, + private alertService: AlertService) { } + + ngOnInit(): void { + this.wantService.describe() + .subscribe( + response => { + this.definitionWant = response; + this.fields = this.definitionWant.POST; + }, + error => this.alertService.showError('Connection problem!') + ); + } + + onCreated(want: Want) { + this.want = want; + this.wantService.post(this.want) + .subscribe( + response => this.viewCtrl.dismiss({ + success: true + }), + error => this.alertService.showError(error) + ); + } + + dismiss() { + this.viewCtrl.dismiss(); + } +} diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index 49d5c14..33939d2 100644 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -18,11 +18,10 @@ export class HomePage implements OnInit { private transactionService: TransactionService, private alertService: AlertService) { this.menuCtrl.enable(true, 'app-menu'); - this.authService.getUserInfo.subscribe( + this.authService.userInfo.subscribe( userInfo => { this.username = userInfo.name; }); - this.authService.loadToken(); } ngOnInit(): void { diff --git a/src/pages/memberDetail/memberDetail.html b/src/pages/memberDetail/memberDetail.html index 395c505..37ef2ff 100644 --- a/src/pages/memberDetail/memberDetail.html +++ b/src/pages/memberDetail/memberDetail.html @@ -1,6 +1,6 @@ -

{{member.name}}

+

{{ (member && member.name) || '' }}

- +
+ +
diff --git a/src/pages/offer/offer.ts b/src/pages/offer/offer.ts index f6013e8..a2d237b 100644 --- a/src/pages/offer/offer.ts +++ b/src/pages/offer/offer.ts @@ -1,9 +1,10 @@ import { Component, OnInit } from '@angular/core'; -import { NavParams, ModalController } from 'ionic-angular'; +import { ModalController } from 'ionic-angular'; import { OfferService } from '../../services/OfferService'; import { AlertService } from '../../services/AlertService'; import { Offer } from '../../domain/Offer'; import { OfferDetailPage } from '../offerDetail/offerDetail'; +import { MemberDetailModal } from '../memberDetail/memberDetail'; import { AddOfferPage } from '../addOffer/addOffer'; @Component({ @@ -40,14 +41,21 @@ export class OfferPage implements OnInit { ); } - showDetails(id): void { + showDetails(id) { let modal = this.modalCtrl.create(OfferDetailPage, { id: id }); modal.present(); } - addOffer(): void { + showMember(userId) { + let modal = this.modalCtrl.create(MemberDetailModal, { + memberId: userId + }); + modal.present(); + } + + addOffer() { let modal = this.modalCtrl.create(AddOfferPage); modal.onDidDismiss((data: any = {}) => { this.success = data.success; diff --git a/src/pages/offerDetail/offerDetail.html b/src/pages/offerDetail/offerDetail.html index 14cb19a..05cf9f2 100644 --- a/src/pages/offerDetail/offerDetail.html +++ b/src/pages/offerDetail/offerDetail.html @@ -11,31 +11,32 @@

Offer Detail

-
-
- -
-
- {{ offer.title }} -
- - expires in - {{ offer.expires | unixTimeToMoment | amDifference : today : 'days' }} - days - -
-
- {{ offer.description }} +
+
+
+
-
- - {{ offer.name }} - +
+ {{ offer.title }} +
+ + expires in {{ offer.expires | unixTimeToMoment | amDifference : today : 'days' }} days + + + expired {{ -1 * (offer.expires | unixTimeToMoment | amDifference : today : 'days') }} days ago + +
+
+ {{ offer.description }} +
+
+ + {{ offer.name }} + +
-
-
-
- +
+
diff --git a/src/pages/offerDetail/offerDetail.ts b/src/pages/offerDetail/offerDetail.ts index 2c6789b..eb3ad3c 100644 --- a/src/pages/offerDetail/offerDetail.ts +++ b/src/pages/offerDetail/offerDetail.ts @@ -1,7 +1,8 @@ import { Component, OnInit } from '@angular/core'; -import { NavParams, ViewController } from 'ionic-angular'; +import { NavParams, ViewController, ModalController } from 'ionic-angular'; import { OfferService } from '../../services/OfferService'; import { AlertService } from '../../services/AlertService'; +import { MemberDetailModal } from '../memberDetail/memberDetail'; import { Offer } from '../../domain/Offer'; @Component({ @@ -14,6 +15,7 @@ export class OfferDetailPage implements OnInit { constructor(private params: NavParams, private viewCtrl: ViewController, + private modalCtrl: ModalController, private offerService: OfferService, private alertService: AlertService) { } @@ -30,6 +32,13 @@ export class OfferDetailPage implements OnInit { ); } + showMember(userId) { + let modal = this.modalCtrl.create(MemberDetailModal, { + memberId: userId + }); + modal.present(); + } + dismiss() { this.viewCtrl.dismiss(); } diff --git a/src/pages/page2/page2.html b/src/pages/page2/page2.html deleted file mode 100644 index a0e6e4b..0000000 --- a/src/pages/page2/page2.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - Page Two - - - - - - - -
- You navigated here from {{selectedItem.title}} -
-
diff --git a/src/pages/page2/page2.scss b/src/pages/page2/page2.scss deleted file mode 100644 index 5b966fd..0000000 --- a/src/pages/page2/page2.scss +++ /dev/null @@ -1,3 +0,0 @@ -page-page2 { - -} diff --git a/src/pages/page2/page2.ts b/src/pages/page2/page2.ts deleted file mode 100644 index 552b5a7..0000000 --- a/src/pages/page2/page2.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component } from '@angular/core'; -import { NavController, NavParams } from 'ionic-angular'; - -@Component({ - selector: 'page-page2', - templateUrl: 'page2.html' -}) -export class Page2 { - selectedItem: any; - icons: string[]; - items: Array<{title: string, note: string, icon: string}>; - - constructor(public navCtrl: NavController, public navParams: NavParams) { - // If we navigated to this page, we will have an item available as a nav param - this.selectedItem = navParams.get('item'); - - // Let's populate this page with some filler content for funzies - this.icons = ['flask', 'wifi', 'beer', 'football', 'basketball', 'paper-plane', - 'american-football', 'boat', 'bluetooth', 'build']; - - this.items = []; - for (let i = 1; i < 11; i++) { - this.items.push({ - title: 'Item ' + i, - note: 'This is item #' + i, - icon: this.icons[Math.floor(Math.random() * this.icons.length)] - }); - } - } - - itemTapped(event, item) { - // That's right, we're pushing to ourselves! - this.navCtrl.push(Page2, { - item: item - }); - } -} diff --git a/src/pages/want/want.html b/src/pages/want/want.html new file mode 100644 index 0000000..8f553c2 --- /dev/null +++ b/src/pages/want/want.html @@ -0,0 +1,48 @@ + + + +

Wants

+
+
+ + +
+ +
Success!
+

New want created.

+
+
+
+
+
+ +
+
+

{{ want.title }}

+
+ + expires in {{ want.expires | unixTimeToMoment | amDifference : today : 'days' }} days + + + expired {{ -1 * (want.expires | unixTimeToMoment | amDifference : today : 'days') }} days ago + +
+
+ + {{ want.name }} + +
+
+
+ + +
+
+
+
+ +
diff --git a/src/pages/want/want.scss b/src/pages/want/want.scss new file mode 100644 index 0000000..071e0e4 --- /dev/null +++ b/src/pages/want/want.scss @@ -0,0 +1,3 @@ +page-want { + +} diff --git a/src/pages/want/want.ts b/src/pages/want/want.ts new file mode 100644 index 0000000..5d772f0 --- /dev/null +++ b/src/pages/want/want.ts @@ -0,0 +1,66 @@ +import { Component, OnInit } from '@angular/core'; +import { ModalController } from 'ionic-angular'; +import { WantService } from '../../services/WantService'; +import { AlertService } from '../../services/AlertService'; +import { Want } from '../../domain/Want'; +import { WantDetailPage } from '../wantDetail/wantDetail'; +import { MemberDetailModal } from '../memberDetail/memberDetail'; +import { AddWantPage } from '../addWant/addWant'; + +@Component({ + selector: 'page-want', + templateUrl: 'want.html' +}) +export class WantPage implements OnInit { + private canPost = false; + private success = false; + private definitionWant: any; + private wants: Array; + + constructor(private modalCtrl: ModalController, + private wantService: WantService, + private alertService: AlertService) { } + + ngOnInit(): void { + this.wantService.describe() + .subscribe( + response => { + this.definitionWant = response; + this.canPost = !!this.definitionWant.POST; + }, + error => this.alertService.showError('Connection problem!') + ); + this.loadWants(); + } + + loadWants() { + this.wantService.list() + .subscribe( + response => this.wants = response, + error => this.alertService.showError('Connection problem!') + ); + } + + showDetails(id): void { + let modal = this.modalCtrl.create(WantDetailPage, { + id: id + }); + modal.present(); + } + + showMember(userId) { + let modal = this.modalCtrl.create(MemberDetailModal, { + memberId: userId + }); + modal.present(); + } + + addWant(): void { + let modal = this.modalCtrl.create(AddWantPage); + modal.onDidDismiss((data: any = {}) => { + this.success = data.success; + this.loadWants(); + }); + modal.present(); + } +} diff --git a/src/pages/wantDetail/wantDetail.html b/src/pages/wantDetail/wantDetail.html new file mode 100644 index 0000000..b770374 --- /dev/null +++ b/src/pages/wantDetail/wantDetail.html @@ -0,0 +1,43 @@ + + +

Want Detail

+ + + +
+
+ + +
+
+
+ +
+
+ {{ want.title }} +
+ + expires in {{ want.expires | unixTimeToMoment | amDifference : today : 'days' }} days + + + expired {{ -1 * (want.expires | unixTimeToMoment | amDifference : today : 'days') }} days ago + +
+
+ {{ want.description }} +
+
+ + {{ want.name }} + +
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/pages/wantDetail/wantDetail.scss b/src/pages/wantDetail/wantDetail.scss new file mode 100644 index 0000000..e3da216 --- /dev/null +++ b/src/pages/wantDetail/wantDetail.scss @@ -0,0 +1,3 @@ +page-want-detail { + +} diff --git a/src/pages/wantDetail/wantDetail.ts b/src/pages/wantDetail/wantDetail.ts new file mode 100644 index 0000000..fa970e7 --- /dev/null +++ b/src/pages/wantDetail/wantDetail.ts @@ -0,0 +1,45 @@ +import { Component, OnInit } from '@angular/core'; +import { NavParams, ViewController, ModalController } from 'ionic-angular'; +import { WantService } from '../../services/WantService'; +import { AlertService } from '../../services/AlertService'; +import { MemberDetailModal } from '../memberDetail/memberDetail'; +import { Want } from '../../domain/Want'; + +@Component({ + selector: 'page-want-detail', + templateUrl: 'wantDetail.html' +}) +export class WantDetailPage implements OnInit { + private definitionWant: any; + private want: Want; + + constructor(private params: NavParams, + private viewCtrl: ViewController, + private modalCtrl: ModalController, + private wantService: WantService, + private alertService: AlertService) { } + + ngOnInit(): void { + this.wantService.describe() + .subscribe( + response => this.definitionWant = response, + error => this.alertService.showError('Connection problem!') + ); + this.wantService.get(this.params.get('id')) + .subscribe( + response => this.want = response, + error => this.alertService.showError('Connection problem!') + ); + } + + showMember(userId) { + let modal = this.modalCtrl.create(MemberDetailModal, { + memberId: userId + }); + modal.present(); + } + + dismiss() { + this.viewCtrl.dismiss(); + } +} diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index 81f8534..da997d0 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -1,22 +1,20 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; -import { Subject } from 'rxjs/Subject'; +import { ReplaySubject } from 'rxjs/ReplaySubject'; import { AppSettings } from '../app/app.settings'; import { HttpBasicAuth } from './HttpBasicAuth'; import { Member } from '../domain/Member'; -import { MEMBER } from '../test/mock-member'; @Injectable() export class AuthService { - private LOCAL_TOKEN_KEY: string; + private LOCAL_TOKEN_KEY: string = 'local_token'; private hasToken: boolean; - private userInfo = new Subject(); - getUserInfo = this.userInfo.asObservable(); + userInfo = new ReplaySubject(1); constructor(private settings: AppSettings, private httpBasicAuth: HttpBasicAuth) { - this.LOCAL_TOKEN_KEY = 'auth_token'; this.hasToken = false; + this.loadToken(); } loadToken() { @@ -46,12 +44,12 @@ export class AuthService { } private requestUserInfo(username): Observable { - // return this.httpBasicAuth - // .getWithAuth(`${this.settings.URL.members}?fragment=${username}&depth=1`) - return this.httpBasicAuth.get(this.settings.URL.config) + return this.httpBasicAuth + .getWithAuth(`${this.settings.URL.members}?fragment=${username}&depth=1`) .map(response => { - response = MEMBER; - this.storeToken(response); + for (let id in response) { + this.storeToken(response[id]); + } return response; }); } @@ -64,6 +62,7 @@ export class AuthService { logout() { return Observable.create(observer => { this.destroyToken(); + this.httpBasicAuth.logout(); observer.next(''); observer.complete(); }); diff --git a/src/services/ConfigService.ts b/src/services/ConfigService.ts index 71fe045..8bf82eb 100644 --- a/src/services/ConfigService.ts +++ b/src/services/ConfigService.ts @@ -26,7 +26,7 @@ export class ConfigService { requestAppConfig(): Observable { return this.httpBasicAuth.get(this.settings.URL.config) - .map(response => { + .map((response: Config) => { this.categoriesService.setCategories( lodash.map(response.categories, (category: Category, id: string) => { category.id = id; diff --git a/src/services/HttpBasicAuth.ts b/src/services/HttpBasicAuth.ts index ca5c61d..d4c88e9 100644 --- a/src/services/HttpBasicAuth.ts +++ b/src/services/HttpBasicAuth.ts @@ -1,14 +1,41 @@ import { Injectable } from '@angular/core'; import { Http, Headers, Response } from '@angular/http'; +import { AppSettings } from '../app/app.settings'; @Injectable() export class HttpBasicAuth { private authorizationToken: string; + private AUTH_TOKEN_KEY: string; - constructor(private http: Http) { } + constructor(private http: Http, + private settings: AppSettings) { + this.AUTH_TOKEN_KEY = 'auth_token'; + this.loadToken(); + } + + loadToken() { + var token = window.localStorage.getItem(this.AUTH_TOKEN_KEY); + if (token) { + this.setToken(JSON.parse(token)); + } + } + + private storeToken(token) { + window.localStorage.setItem(this.AUTH_TOKEN_KEY, JSON.stringify(token)); + this.setToken(token); + } + + private destroyToken() { + window.localStorage.removeItem(this.AUTH_TOKEN_KEY); + } + + private setToken(token) { + this.authorizationToken = token; + } setAuthorizationToken(username, password) { - this.authorizationToken = `Basic ${btoa(`${username}:${password}`)}` + this.authorizationToken = `Basic ${btoa(`${username}:${password}`)}`; + this.storeToken(this.authorizationToken); } private createAuthorizationHeader(headers: Headers) { @@ -20,16 +47,27 @@ export class HttpBasicAuth { return body || {}; } + private extractError(error): any { + throw JSON.stringify(error.json()); + } + getWithAuth(url) { let headers = new Headers(); this.createAuthorizationHeader(headers); - return this.get(url,headers); + return this.get(url, headers); } get(url, headers?) { return this.http.get(url, { headers: headers - }).map(this.extractData); + }).map(this.extractData) + .catch(this.extractError); + } + + getAutocomplete(autocompleteURL?, fragment?) { + let headers = new Headers(); + this.createAuthorizationHeader(headers); + return this.get(`${this.settings.SERVER_URL}${autocompleteURL || ''}${fragment || ''}`, headers); } postWithAuth(url, data) { @@ -41,13 +79,19 @@ export class HttpBasicAuth { post(url, data, headers?) { return this.http.post(url, data, { headers: headers - }).map(this.extractData); + }).map(this.extractData) + .catch(this.extractError); } options(url) { let headers = new Headers(); return this.http.options(url, { headers: headers - }).map(this.extractData); + }).map(this.extractData) + .catch(this.extractError); + } + + logout() { + this.destroyToken(); } } \ No newline at end of file diff --git a/src/services/MemberService.ts b/src/services/MemberService.ts index 5779d6a..9e8ae55 100644 --- a/src/services/MemberService.ts +++ b/src/services/MemberService.ts @@ -26,4 +26,8 @@ export class MemberService{ getMemberWithId(id): Member { return this.membersArray.filter(member => member.id === id)[0]; } + + get(id): Observable { + return this.httpBasicAuth.getWithAuth(`${this.settings.URL.members}/${id}?depth=1`); + } } \ No newline at end of file diff --git a/src/services/OfferService.ts b/src/services/OfferService.ts index e36ea0f..1a0ee8b 100644 --- a/src/services/OfferService.ts +++ b/src/services/OfferService.ts @@ -3,8 +3,6 @@ import { Observable } from 'rxjs/Observable'; import { AppSettings } from '../app/app.settings'; import { HttpBasicAuth } from './HttpBasicAuth'; import { Offer } from '../domain/Offer'; -import { OFFERS } from '../test/mock-offers'; -import { OPTIONS_OFFER } from '../test/mock-options-offer'; import * as lodash from 'lodash'; @Injectable() @@ -14,10 +12,8 @@ export class OfferService { private httpBasicAuth: HttpBasicAuth) { } list(): Observable> { - return this.httpBasicAuth.get(this.settings.URL.config) - // return this.httpBasicAuth.getWithAuth(this.settings.URL.offers) - .map(response => { - response = OFFERS; + return this.httpBasicAuth.getWithAuth(`${this.settings.URL.offers}?depth=1`) + .map((response: Array) => { response = lodash.map(response, (offer: Offer) => { return offer; }); @@ -26,29 +22,14 @@ export class OfferService { } get(id): Observable { - return this.httpBasicAuth.get(this.settings.URL.config) - // return this.httpBasicAuth.getWithAuth(`${this.settings.URL.offers}/${id}`) - .map(response => { - response = OFFERS[id]; - return response; - }); + return this.httpBasicAuth.getWithAuth(`${this.settings.URL.offers}/${id}?depth=1`); } post(offer: Offer): Observable { - return this.httpBasicAuth.get(this.settings.URL.config) - // return this.httpBasicAuth.postWithAuth(this.settings.URL.offers) - .map(response => { - response = OFFERS[1]; - return response; - }); + return this.httpBasicAuth.postWithAuth(this.settings.URL.offers, offer); } describe(): Observable { - return this.httpBasicAuth.get(this.settings.URL.config) - // return this.httpBasicAuth.options(this.settings.URL.offers) - .map(response => { - response = OPTIONS_OFFER; - return response; - }); + return this.httpBasicAuth.options(this.settings.URL.offers); } } \ No newline at end of file diff --git a/src/services/WantService.ts b/src/services/WantService.ts new file mode 100644 index 0000000..71eec12 --- /dev/null +++ b/src/services/WantService.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs/Observable'; +import { AppSettings } from '../app/app.settings'; +import { HttpBasicAuth } from './HttpBasicAuth'; +import { Want } from '../domain/Want'; +import * as lodash from 'lodash'; + +@Injectable() +export class WantService { + + constructor(private settings: AppSettings, + private httpBasicAuth: HttpBasicAuth) { } + + list(): Observable> { + return this.httpBasicAuth.getWithAuth(`${this.settings.URL.wants}?depth=1`) + .map((response: Array) => { + response = lodash.map(response, (want: Want) => { + return want; + }); + return response; + }); + } + + get(id): Observable { + return this.httpBasicAuth.getWithAuth(`${this.settings.URL.wants}/${id}?depth=1`); + } + + post(want: Want): Observable { + return this.httpBasicAuth.postWithAuth(this.settings.URL.wants, want); + } + + describe(): Observable { + return this.httpBasicAuth.options(this.settings.URL.wants); + } +} \ No newline at end of file diff --git a/src/test/mock-offers.ts b/src/test/mock-offers.ts index cff974b..e881b42 100644 --- a/src/test/mock-offers.ts +++ b/src/test/mock-offers.ts @@ -28,75 +28,5 @@ export const OFFERS = { "id": "3", "uri": "commex/v1/offer/3", "created": "1479282277" - }, - "4": { - "title": "Antique green dolly from the orient.", - "description": "Abluo lobortis melior quis ulciscor vero. Facilisis odio paulatim suscipere tum ymo. Dignissim feugiat melior occuro roto tation utinam valde. Appellatio jugis mos neo veniam vicis. Abico odio saluto suscipere virtus wisi ymo. Abbas amet eros hendrerit iustum pala paratus quia tamen verto. Abico gravis immitto metuo ratis. Diam et utrum. Eligo hendrerit luctus nobis quis sudo ullamcorper.\n\nConsectetuer decet et neo praemitto sagaciter saluto tation. Aliquip capto genitus lobortis odio proprius secundum. Abico importunus tation verto virtus. Iaceo luctus praemitto. Dolore iusto meus nibh nobis olim patria plaga singularis vero.\n\n", - "user_id": "member/20", - "name": "Zoe Draper", - "expires": "1484203646", - "id": "4", - "uri": "commex/v1/offer/4", - "created": "1470683538" - }, - "5": { - "title": "High-powered porcelaine mp3 player from the orient.", - "description": "Appellatio bene consequat eum oppeto saepius tation ymo. Adipiscing causa decet erat gemino gravis os quae qui. Causa eros esse luptatum vicis. Capto defui gemino iaceo lucidus magna metuo quidne virtus. Caecus camur dolore facilisis ille luptatum quis refero uxor.\n\nAliquip laoreet sit ut vel veniam. Amet augue cogo ille immitto minim nutus singularis te. Duis feugiat importunus metuo velit vicis. Commodo eligo paulatim tamen. Aptent pneum ratis.\n\n", - "user_id": "member/22", - "name": "Larry Ingram", - "expires": "1484203646", - "id": "5", - "uri": "commex/v1/offer/5", - "created": "1483234291" - }, - "6": { - "title": "A very nice porcelaine widgets latest model!", - "description": "Dignissim fere gravis iaceo singularis turpis uxor. Antehabeo damnum fere jugis loquor luctus os quae sudo. Haero mos odio paulatim usitas. Pagus paratus suscipit vel verto. Abbas commodo euismod nulla pneum quae roto secundum vero. Bene brevitas probo valde. Abdo autem pertineo. Abluo aliquam caecus esca inhibeo jumentum pagus refoveo veniam.\n\nAppellatio bene dolus elit ibidem imputo neque persto te tincidunt. Blandit hos nisl odio probo valde. Immitto nutus scisco. Eros haero nisl premo quae secundum singularis vindico. Autem euismod gravis luptatum pecus populus quia. Antehabeo aptent enim letalis nimis nunc olim ut verto. Erat exerci ibidem minim nostrud patria qui torqueo volutpat.\n\n", - "user_id": "member/15", - "name": "Terry X", - "expires": "1484203646", - "id": "6", - "uri": "commex/v1/offer/6", - "created": "1475350968" - }, - "7": { - "title": "Hand-crafted gelatinous donkey ", - "description": "Ad adipiscing brevitas capto utrum. Cogo quadrum roto si vereor. Antehabeo cui dolore in modo pertineo quidem ulciscor ullamcorper vindico. Decet duis euismod genitus hos immitto nulla nunc obruo pecus.\n\nBrevitas incassum iriure pagus sed typicus validus volutpat. Abbas cui esca eum gemino gilvus meus nimis utrum voco. Aliquam aliquip capto exputo haero incassum lobortis molior pecus roto. Jumentum macto modo paratus proprius valetudo volutpat wisi. Bene causa commoveo esca euismod hendrerit obruo pertineo quadrum usitas. Abigo duis iriure luptatum neque populus tation.\n\n", - "user_id": "member/23", - "name": "Ebeneezer Archer", - "expires": "1484203646", - "id": "7", - "uri": "commex/v1/offer/7", - "created": "1468643709" - }, - "8": { - "title": "Antique gelatinous armistice unwanted gift.", - "description": "At cogo damnum ut uxor. Lobortis luptatum metuo pneum quidne sino. Inhibeo lenis melior minim refoveo velit zelus. Defui erat exerci jus secundum venio vero vulpes. Defui oppeto pecus turpis vulpes. Abigo dignissim facilisi ibidem immitto inhibeo modo nibh quae.\n\nCommoveo cui dignissim mauris te vulputate. Aliquam jus nutus oppeto. Abdo dolor erat et hos mos natu pertineo valetudo virtus. Aliquam aliquip minim neo quis roto ut utrum ymo.\n\n", - "user_id": "member/6", - "name": "Quentin Baker", - "expires": "1484203646", - "id": "8", - "uri": "commex/v1/offer/8", - "created": "1475452848" - }, - "9": { - "title": "Refurbished stress-tested ladder for hire.", - "description": "Aliquam haero ludus neque persto qui vereor. Abdo esse gravis luctus paratus proprius rusticus sed suscipit torqueo. Fere magna minim molior refero singularis tum. Facilisis feugiat ratis. Eros ex laoreet nibh praemitto torqueo valde validus.\n\nAdipiscing neque quidne valetudo vindico. Adipiscing camur consequat damnum humo lucidus suscipit vel vicis. At consectetuer gemino ideo iusto jugis lenis macto pecus volutpat. Cogo cui mauris rusticus similis suscipere vicis. Eligo imputo quidne secundum ulciscor vel.\n\n", - "user_id": "member/16", - "name": "Kerry Usher", - "expires": "1484203647", - "id": "9", - "uri": "commex/v1/offer/9", - "created": "1480648858" - }, - "10": { - "title": "Hand-crafted fried widgets ", - "description": "Enim natu nobis nutus patria pertineo quis turpis valetudo zelus. Esse euismod gemino jus paulatim quidem scisco valetudo. Consequat ea inhibeo letalis tation ut. Commoveo fere humo iaceo ideo mos obruo sino. Feugiat hos iusto lucidus macto neo quadrum refero typicus verto. Accumsan exputo minim. Paratus praemitto sed usitas. Consequat decet defui duis luptatum proprius quidem rusticus.\n\nAbdo esse haero iaceo lobortis macto similis verto vulputate. Causa quibus saluto tincidunt turpis. Blandit consectetuer ibidem persto populus qui quis suscipit. Aliquip damnum importunus in jugis pertineo. Conventio damnum voco. Commoveo fere letalis obruo oppeto pagus vicis. Abbas abigo adipiscing aliquam commodo humo mos paratus ymo.\n\n", - "user_id": "member/15", - "name": "Terry X", - "expires": "1484203647", - "id": "10", - "uri": "commex/v1/offer/10", - "created": "1480610657" } }; \ No newline at end of file From 4d0f643d5abb81cdbe9576d8239a7745413ef356 Mon Sep 17 00:00:00 2001 From: Luis Nunez Date: Mon, 23 Jan 2017 17:34:59 -0200 Subject: [PATCH 2/2] adding image handlers to fieldBuilder --- src/components/fieldBuilder/fieldBuilder.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/components/fieldBuilder/fieldBuilder.ts b/src/components/fieldBuilder/fieldBuilder.ts index 27175bd..4a6f3f4 100644 --- a/src/components/fieldBuilder/fieldBuilder.ts +++ b/src/components/fieldBuilder/fieldBuilder.ts @@ -151,18 +151,22 @@ export class FieldBuilderComponent implements OnInit, AfterViewInit { } addImage() { - (navigator).camera.getPicture(image => { - this.field.imgSrc = `data:image/jpeg;base64,${image}`; - }, null, { - sourceType: 0 // PHOTOLIBRARY - }); + this.addImageToField(0); // PHOTOLIBRARY } takePhoto() { + this.addImageToField(1); // CAMERA + } + + addImageToField(sourceType) { (navigator).camera.getPicture(image => { this.field.imgSrc = `data:image/jpeg;base64,${image}`; + let fieldValue = {}; + fieldValue[this.field.name] = this.field.imgSrc; + this.fieldForm.setValue(fieldValue); }, null, { - sourceType: 1 // CAMERA + destinationType: 0, // DATA_URL + sourceType: sourceType }); }