Added cruising pages support

This commit is contained in:
2018-03-08 14:41:45 -05:00
parent 9fcaef1068
commit 0cf95d2cd4
18 changed files with 355 additions and 12 deletions

View File

@@ -8,7 +8,7 @@ import { TabsPage } from '../pages/tabs/tabs';
@Component({
templateUrl: 'app.html'
})
export class Groundr {
export class Urge {
rootPage:any = TabsPage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {

View File

@@ -3,9 +3,11 @@ import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { IonicSwipeAllModule } from 'ionic-swipe-all';
import { Groundr } from './app.component';
import { Urge } from './app.component';
import { ChatPage } from '../pages/chat/chat';
import { CruisePage } from '../pages/cruise/cruise';
import { CruisesPage } from '../pages/cruises/cruises';
import { GridPage } from '../pages/grid/grid';
import { LightboxPage } from '../pages/lightbox/lightbox';
import { MessagesPage } from '../pages/messages/messages';
@@ -17,8 +19,10 @@ import { SplashScreen } from '@ionic-native/splash-screen';
@NgModule({
declarations: [
Groundr,
Urge,
ChatPage,
CruisePage,
CruisesPage,
GridPage,
LightboxPage,
MessagesPage,
@@ -29,7 +33,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
BrowserModule,
HttpModule,
IonicSwipeAllModule,
IonicModule.forRoot(Groundr, {
IonicModule.forRoot(Urge, {
iconMode: 'ios',
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',
@@ -39,8 +43,10 @@ import { SplashScreen } from '@ionic-native/splash-screen';
],
bootstrap: [IonicApp],
entryComponents: [
Groundr,
Urge,
ChatPage,
CruisePage,
CruisesPage,
GridPage,
LightboxPage,
MessagesPage,

View File

@@ -0,0 +1,52 @@
[{
"order" : 0,
"location" : {
"address" : {
"street1" : "123 Boylston St",
"street2" : "12th Floor",
"locality" : "Boston",
"region" : "MA",
"postal" : "02110",
"country" : "United States"
},
"loc" : {
"type" : "Point",
"coordinates" : [
0,
0
]
}
},
"name" : "Dummy1",
"pic" : {
"detail" : "https://placehold.it/1920x1280",
"thumb" : "https://placehold.it/1920x1280"
},
"text" : "Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text!"
},
{
"order" : 1,
"location" : {
"address" : {
"street1" : "",
"street2" : "",
"locality" : "Abu Dhabi",
"region" : "",
"postal" : "",
"country" : "UAE"
},
"loc" : {
"type" : "Point",
"coordinates" : [
0,
0
]
}
},
"name" : "Dummy2",
"pic" : {
"detail" : "https://placehold.it/1920x1280",
"thumb" : "https://placehold.it/1920x1280"
},
"text" : "Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text, Some text!"
}]

View File

@@ -0,0 +1,26 @@
<ion-content no-padding [style.backgroundImage]="getBackground(this.cruise.pic)" (press)="showLightbox($event, this.cruise.pic.detail)">
<ion-toolbar>
<ion-buttons left>
<button ion-button icon-only (tap)="closeCruise($event)">
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
<div id="detail-overlay" class="details" swipeAll (swipedown)="closeCruiseDetails($event)" (swipeup)="openCruiseDetails($event)" (click)="toggleCruiseDetails($event)">
<ion-grid>
<ion-row nowrap align-items-center justify-content-between>
<ion-col col-8>
<h2 class="placename">{{this.cruise.name}}</h2>
</ion-col>
</ion-row>
<ion-row class="location" *ngIf="this.cruise.location">
<ion-col col-4>Location</ion-col>
<ion-col col-8 [innerHTML]="getFormattedCruiseAddress(this.cruise.location)"></ion-col>
</ion-row>
<ion-row class="text" *ngIf="this.cruise.text">
<ion-col col-12>{{this.cruise.text}}</ion-col>
</ion-row>
</ion-grid>
</div>
</ion-content>

View File

@@ -0,0 +1,47 @@
page-cruise {
ion-content {
background-position: center;
background-repeat: no-repeat;
background-size: contain;
}
.scroll-content {
overflow-y: hidden;
}
ion-toolbar {
.toolbar-background {
background-color: transparent;
}
.bar-button {
color: #ffffff;
}
}
.details {
background: rgba(0, 0, 0, 0.8);
bottom: 0;
height: 60px;
left: 0;
position: absolute;
right: 0;
transition: all 250ms 125ms ease-in-out;
h2 {
margin: 0;
}
.location {
margin-top: 1.5rem;
}
&.open {
height: 100%;
overflow-y: scroll;
padding-top: 35px;
}
}
}

View File

@@ -0,0 +1,81 @@
import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController, NavParams } from 'ionic-angular';
import { LightboxPage } from '../lightbox/lightbox';
@Component({
selector: 'page-cruise',
templateUrl: 'cruise.html'
})
export class CruisePage {
detailsOpen: boolean = false;
cruise: any;
tabNavEl: any;
constructor(public navCtrl: NavController, public navParams: NavParams, private _sanitizer: DomSanitizer) {
this.cruise = navParams.get('cruise');
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'none';
}
closeCruise(event) {
this.navCtrl.pop();
}
closeCruiseDetails(event) {
if (this.detailsOpen) {
this.detailsOpen = false;
document.getElementById('detail-overlay').classList.remove('open');
}
}
getBackground(images) {
// PROD: return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + images.detail + ')');
return this._sanitizer.bypassSecurityTrustStyle('url(' + images.detail + ')');
}
getFormattedCruiseAddress(location) {
var address = '';
if (location && location.address) {
address += location.address.street1 ? location.address.street1 + '<br>' : '';
address += location.address.street2 ? location.address.street2 + '<br>' : '';
address += location.address.locality ? location.address.locality + ', ' : '';
address += location.address.region ? location.address.region + ' ' : '';
address += location.address.postal ? location.address.postal + '<br>' : '';
address += location.address.country ? location.address.country : '';
}
return address;
}
markFavorite(event, cruise) {
console.debug('favorite cruise', { event: event, profile: cruise });
}
openCruiseDetails(event) {
if (!this.detailsOpen) {
this.detailsOpen = true;
document.getElementById('detail-overlay').classList.add('open');
}
}
showLightbox(event, image) {
if (event.target.classList.contains('scroll-content')) {
this.navCtrl.push(LightboxPage, {
image: image
});
}
}
toggleCruiseDetails(event) {
if (!this.detailsOpen) {
this.openCruiseDetails(event);
} else {
this.closeCruiseDetails(event);
}
}
}

View File

@@ -0,0 +1,9 @@
<ion-content no-padding>
<ion-grid no-padding>
<ion-row align-items-stretch>
<ion-col col-6 class="cruise" *ngFor="let current of cruises" (tap)="profileTapped($event, current)" [style.backgroundImage]="getBackgroundThumbnail(current.pic)">
<span class="placename" [ngClass]="{ 'online': (current.messages?.length > 0) }">{{current.name}}</span>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

View File

@@ -0,0 +1,27 @@
page-cruises {
ion-col {
&.cruise {
background-size: cover;
border: 1px solid #000000;
box-sizing: border-box;
padding: 0 0 37.5% !important;
position: relative;
.placename {
bottom: 0.25rem;
box-sizing: border-box;
color: #acacac;
display: inline-block;
left: 0.5rem;
overflow: hidden;
position: absolute;
right: 0.25rem;
text-overflow: ellipsis;
text-shadow: rgba(0, 0, 0, 1);
white-space: nowrap;
}
}
}
}

View File

@@ -0,0 +1,39 @@
import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController } from 'ionic-angular';
import { CruiseService } from '../../services/cruises';
import { CruisePage } from '../cruise/cruise';
@Component({
selector: 'page-cruises',
templateUrl: 'cruises.html',
providers: [ CruiseService ]
})
export class CruisesPage {
cruises: any;
tabNavEl: any;
constructor(public navCtrl: NavController, public cruiseService: CruiseService, private _sanitizer: DomSanitizer) {
cruiseService.load().then((data) => {
this.cruises = data;
});
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'flex';
}
getBackgroundThumbnail(images) {
// PROD: return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + images.thumb + ')');
return this._sanitizer.bypassSecurityTrustStyle('url(' + images.thumb + ')');
}
profileTapped(event, cruise) {
this.navCtrl.push(CruisePage, {
cruise: cruise
});
}
}

View File

@@ -1,7 +1,7 @@
<ion-content no-padding>
<ion-grid no-padding>
<ion-row align-items-stretch>
<ion-col col-4 class="profile" *ngFor="let current of profiles" (tap)="profileTapped($event, current)" [style.backgroundImage]="getBackgroundThumbnail(current.details.pic)">
<ion-col col-4 class="profile" *ngFor="let current of profiles" (tap)="profileTapped($event, current)" (press)="profilePressed($event, current)" [style.backgroundImage]="getBackgroundThumbnail(current.details.pic)">
<span class="username" [ngClass]="{ 'online': (current.messages?.length > 0) }">{{current.details.name}}</span>
</ion-col>
</ion-row>

View File

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NavController } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile';
@@ -30,6 +31,14 @@ export class GridPage {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + pics.thumb + ')');
}
profilePressed(event, profile) {
if (profile.messages && profile.messages.length) {
this.navCtrl.push(ChatPage, {
profile: profile
});
}
}
profileTapped(event, profile) {
this.navCtrl.push(ProfilePage, {
profile: profile

View File

@@ -1,4 +1,4 @@
<ion-content no-padding [style.backgroundImage]="getBackground(profile.details.pic)" (tap)="showLightbox($event, profile.details.pic.detail)">
<ion-content no-padding [style.backgroundImage]="getBackground(profile.details.pic)" (press)="showLightbox($event, profile.details.pic.detail)">
<ion-toolbar>
<ion-buttons left>
<button ion-button icon-only (tap)="closeProfile($event)">

View File

@@ -57,7 +57,7 @@ export class ProfilePage {
}
showLightbox(event, image) {
if (event.target.classList.contains('content')) {
if (event.target.classList.contains('scroll-content')) {
this.navCtrl.push(LightboxPage, {
image: image
});

View File

@@ -1,5 +1,5 @@
<ion-tabs id="tab-nav" selectedIndex="0">
<ion-tab [root]="tab1Root" tabIcon="contacts"></ion-tab>
<!--ion-tab [root]="tab1Root" tabIcon="star"></ion-tab-->
<ion-tab [root]="tab2Root" tabIcon="chatboxes"></ion-tab>
<ion-tab [root]="tab2Root" tabIcon="boat"></ion-tab>
<ion-tab [root]="tab3Root" tabIcon="chatboxes"></ion-tab>
</ion-tabs>

View File

@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { GridPage } from '../grid/grid';
import { CruisesPage } from '../cruises/cruises';
import { MessagesPage } from '../messages/messages';
@Component({
@@ -9,7 +10,8 @@ import { MessagesPage } from '../messages/messages';
export class TabsPage {
tab1Root = GridPage;
tab2Root = MessagesPage;
tab2Root = CruisesPage;
tab3Root = MessagesPage;
constructor() {

44
src/services/cruises.ts Normal file
View File

@@ -0,0 +1,44 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class CruiseService {
//endpoint: string = '/assets/data/cruises.json';
endpoint: string = 'https://api.fitz.guru/urge/cruises';
idMap: any;
cruises: any;
constructor(private http: Http) {
this.idMap = {};
this.cruises = null;
}
load() {
if (this.cruises) {
return Promise.resolve(this.cruises);
}
return new Promise(resolve => {
this.http.get(this.endpoint)
.map(res => res.json())
.subscribe(data => {
this.cruises = data;
this.cruises.reduce((map, cruise, i) => {
map[cruise._id] = i;
return map;
}, this.idMap);
resolve(this.cruises);
});
});
}
getCruises() {
return this.cruises;
}
getCruiseById(id) {
return this.cruises[this.idMap[id]];
}
}

View File

@@ -5,6 +5,7 @@ import 'rxjs/add/operator/map';
@Injectable()
export class ProfileService {
endpoint: string = 'https://api.fitz.guru/urge/profiles'; //'assets/data/profiles.json';
idMap: any;
profiles: any;
@@ -19,7 +20,7 @@ export class ProfileService {
}
return new Promise(resolve => {
this.http.get('https://api.fitz.guru/urge/profiles')
this.http.get(this.endpoint)
.map(res => res.json())
.subscribe(data => {
this.profiles = data;