chore(conf-app): making progress

This commit is contained in:
Dan Bucholtz
2017-12-22 23:58:28 -06:00
parent c3598ab69a
commit b2374b4796
13 changed files with 488 additions and 19 deletions

View File

@ -284,9 +284,9 @@
"integrity": "sha512-i2j2J9KIobCqyX6LlrlYhaHgd7qmP1pzHs4XAthHgth8m6c4gsHsh+Pl3fqknD7AX18ghpqo3tVtv0EFhSFU3w=="
},
"@ionic/angular": {
"version": "0.0.2-12",
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-0.0.2-12.tgz",
"integrity": "sha512-JagxmwuGf0FAUfRMLadZIy4MWa6NqlBiWJgy4GcSGhVFK6xw2LBFKxAXP+g0RvmFP2P0KXlCht/AS2c2L7liuA==",
"version": "0.0.2-13",
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-0.0.2-13.tgz",
"integrity": "sha512-PdV5ITq4oCFKNKCUg2/6GneRrCUQEWgfZeukcyIx0V+LbalZ1DUKtn94M74Bfjz/4rFk86G21aIlrq5PCVWZMg==",
"requires": {
"@stencil/core": "0.1.1-0"
},
@ -9527,13 +9527,13 @@
"resolve": "1.5.0",
"semver": "5.4.1",
"tslib": "1.8.1",
"tsutils": "2.13.1"
"tsutils": "2.14.0"
}
},
"tsutils": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.1.tgz",
"integrity": "sha512-XMOEvc2TiYesVSOJMI7OYPnBMSgcvERuGW5Li/J+2A0TuH607BPQnOLQ82oSPZCssB8c9+QGi6qhTBa/f1xQRA==",
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.14.0.tgz",
"integrity": "sha512-f6axSMV0RoUufiKiRQgmRlN1c+Ag+mDaZjcd6bHdvplT/zyhuMCGqw3pJS8s3+0x4EVkdoQajs9PchdDZlguvw==",
"dev": true,
"requires": {
"tslib": "1.8.1"

View File

@ -12,6 +12,10 @@ import { AppComponent } from './app.component';
import { AboutPage } from '../pages/about/about';
import { PopoverPage } from '../pages/about-popover/about-popover';
import { MapPage } from '../pages/map/map';
import { SchedulePage } from '../pages/schedule/schedule';
import { ScheduleFilterPage } from '../pages/schedule-filter/schedule-filter';
import { SessionDetailPage } from '../pages/session-detail/session-detail';
import { SpeakerDetailPage } from '../pages/speaker-detail/speaker-detail';
import { SpeakerListPage } from '../pages/speaker-list/speaker-list';
import { TabsPage } from '../pages/tabs-page/tabs-page';
@ -24,6 +28,10 @@ import { UserData } from '../providers/user-data';
AppComponent,
MapPage,
PopoverPage,
SchedulePage,
ScheduleFilterPage,
SessionDetailPage,
SpeakerDetailPage,
SpeakerListPage,
TabsPage
],
@ -31,6 +39,10 @@ import { UserData } from '../providers/user-data';
AboutPage,
MapPage,
PopoverPage,
SchedulePage,
ScheduleFilterPage,
SessionDetailPage,
SpeakerDetailPage,
SpeakerListPage,
TabsPage
],

View File

@ -0,0 +1,36 @@
<ion-header>
<ion-toolbar>
<ion-buttons start>
<button ion-button (click)="dismiss()">Cancel</button>
</ion-buttons>
<ion-title>
Filter Sessions
</ion-title>
<ion-buttons end>
<button ion-button (click)="applyFilters()" strong>Done</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="outer-content">
<ion-list>
<ion-list-header>Tracks</ion-list-header>
<ion-item *ngFor="let track of tracks" [attr.track]="track.name | lowercase">
<span item-start class="dot"></span>
<ion-label>{{track.name}}</ion-label>
<ion-toggle [(ngModel)]="track.isChecked" color="secondary"></ion-toggle>
</ion-item>
</ion-list>
<ion-list>
<button ion-item (click)="resetFilters()" detail-none class="reset-filters">
Reset All Filters
</button>
</ion-list>
</ion-content>

View File

@ -0,0 +1,17 @@
.reset-filters {
color: color($colors, danger);
}
@each $track, $value in auxiliary-categories() {
ion-item[track=#{$track}] .dot {
height: 10px;
display: inline-block;
width: 10px;
background-color: $value;
border-radius: 5px;
margin-right: 10px;
}
}

View File

@ -0,0 +1,53 @@
import { Component } from '@angular/core';
import { NavParams } from '@ionic/angular';
import { ConferenceData } from '../../providers/conference-data';
@Component({
selector: 'page-schedule-filter',
templateUrl: 'schedule-filter.html'
})
export class ScheduleFilterPage {
tracks: Array<{name: string, isChecked: boolean}> = [];
constructor(
public confData: ConferenceData,
public navParams: NavParams,
) {
// passed in array of track names that should be excluded (unchecked)
const excludedTrackNames = this.navParams.data;
this.confData.getTracks().subscribe((trackNames: string[]) => {
trackNames.forEach(trackName => {
this.tracks.push({
name: trackName,
isChecked: (excludedTrackNames.indexOf(trackName) === -1)
});
});
});
}
resetFilters() {
// reset all of the toggles to be checked
this.tracks.forEach(track => {
track.isChecked = true;
});
}
applyFilters() {
// Pass back a new array of track names to exclude
const excludedTrackNames = this.tracks.filter(c => !c.isChecked).map(c => c.name);
this.dismiss(excludedTrackNames);
}
dismiss(data?: any) {
// using the injected ViewController this page
// can "dismiss" itself and pass back data
// this.viewCtrl.dismiss(data);
alert('todo');
}
}

View File

@ -0,0 +1,87 @@
<ion-header>
<ion-toolbar no-border-bottom>
<ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</ion-button>
<ion-segment [(ngModel)]="segment" (ionChange)="updateSchedule()">
<ion-segment-button value="all">
All
</ion-segment-button>
<ion-segment-button value="favorites">
Favorites
</ion-segment-button>
</ion-segment>
<ion-buttons end>
<ion-button icon-only (click)="presentFilter()">
<ion-icon ios="ios-options-outline" md="md-options"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar no-border-top>
<ion-searchbar color="primary"
[(ngModel)]="queryText"
(ionInput)="updateSchedule()"
placeholder="Search">
</ion-searchbar>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-refresher (ionRefresh)="doRefresh($event)">
<ion-refresher-content></ion-refresher-content>
</ion-refresher>
<ion-list #scheduleList [hidden]="shownSessions === 0">
<ion-item-group *ngFor="let group of groups" [hidden]="group.hide">
<ion-item-divider sticky>
<ion-label>
{{group.time}}
</ion-label>
</ion-item-divider>
<ion-item-sliding *ngFor="let session of group.sessions" #slidingItem [attr.track]="session.tracks[0] | lowercase" [hidden]="session.hide">
<ion-item (click)="goToSessionDetail(session)">
<h3>{{session.name}}</h3>
<p>
{{session.timeStart}} &mdash;
{{session.timeEnd}}:
{{session.location}}
</p>
</ion-item>
<ion-item-options>
<ion-button color="favorite" (click)="addFavorite(slidingItem, session)" *ngIf="segment === 'all'">
Favorite
</ion-button>
<ion-button color="danger" (click)="removeFavorite(slidingItem, session, 'Remove Favorite')" *ngIf="segment === 'favorites'">
Remove
</ion-button>
</ion-item-options>
</ion-item-sliding>
</ion-item-group>
</ion-list>
<ion-list-header [hidden]="shownSessions > 0">
No Sessions Found
</ion-list-header>
<ion-fab bottom right #fab>
<ion-fab><ion-icon name="share"></ion-icon></ion-fab>
<ion-fab-list side="top">
<ion-fab color="vimeo" (click)="openSocial('Vimeo', fab)"><ion-icon name="logo-vimeo"></ion-icon></ion-fab>
<ion-fab color="google" (click)="openSocial('Google+', fab)"><ion-icon name="logo-googleplus"></ion-icon></ion-fab>
<ion-fab ion-fab color="twitter" (click)="openSocial('Twitter', fab)"><ion-icon name="logo-twitter"></ion-icon></ion-fab>
<ion-fab ion-fab color="facebook" (click)="openSocial('Facebook', fab)"><ion-icon name="logo-facebook"></ion-icon></ion-fab>
</ion-fab-list>
</ion-fab>
</ion-content>

View File

@ -0,0 +1,25 @@
$categories: (
// ionic: color($colors, primary),
angular: #AC282B,
communication: #8E8D93,
tooling: #FE4C52,
services: #FD8B2D,
design: #FED035,
workshop: #69BB7B,
food: #3BC7C4,
documentation: #B16BE3,
navigation: #6600CC,
);
@function auxiliary-categories() {
@return map-remove($categories);
}
page-schedule {
@each $track, $value in auxiliary-categories() {
ion-item-sliding[track=#{$track}] ion-label {
border-left: 2px solid $value;
padding-left: 10px;
}
}
}

View File

@ -0,0 +1,184 @@
import { Component, ViewChild } from '@angular/core';
import {
AlertController,
App,
LoadingController,
ModalController,
NavController,
ToastController
} from '@ionic/angular';
import { Fab, ItemSliding, List, /*Refresher*/ } from '@ionic/core';
/*
To learn how to use third party libs in an
Ionic app check out our docs here: http://ionicframework.com/docs/v2/resources/third-party-libs/
*/
// import moment from 'moment';
import { ConferenceData } from '../../providers/conference-data';
import { UserData } from '../../providers/user-data';
import { SessionDetailPage } from '../session-detail/session-detail';
import { ScheduleFilterPage } from '../schedule-filter/schedule-filter';
@Component({
selector: 'page-schedule',
templateUrl: 'schedule.html'
})
export class SchedulePage {
// the list is a child of the schedule page
// @ViewChild('scheduleList') gets a reference to the list
// with the variable #scheduleList, `read: List` tells it to return
// the List and not a reference to the element
@ViewChild('scheduleList', { read: List }) scheduleList: List;
dayIndex = 0;
queryText = '';
segment = 'all';
excludeTracks: any = [];
shownSessions: any = [];
groups: any = [];
confDate: string;
constructor(
public alertCtrl: AlertController,
public app: App,
public loadingCtrl: LoadingController,
public modalCtrl: ModalController,
public navCtrl: NavController,
public toastCtrl: ToastController,
public confData: ConferenceData,
public user: UserData,
) {}
ionViewDidLoad() {
this.app.setTitle('Schedule');
this.updateSchedule();
}
updateSchedule() {
// Close any open sliding items when the schedule updates
if (this.scheduleList) {
this.scheduleList.closeSlidingItems();
}
this.confData.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => {
this.shownSessions = data.shownSessions;
this.groups = data.groups;
});
}
presentFilter() {
const modal = this.modalCtrl.create({
component: ScheduleFilterPage,
data: this.excludeTracks
});
modal.present();
modal.onWillDismiss((data: any[]) => {
if (data) {
this.excludeTracks = data;
this.updateSchedule();
}
});
}
goToSessionDetail(sessionData: any) {
// go to the session detail page
// and pass in the session data
this.navCtrl.push(SessionDetailPage, { sessionId: sessionData.id, name: sessionData.name });
}
addFavorite(slidingItem: ItemSliding, sessionData: any) {
if (this.user.hasFavorite(sessionData.name)) {
// woops, they already favorited it! What shall we do!?
// prompt them to remove it
this.removeFavorite(slidingItem, sessionData, 'Favorite already added');
} else {
// remember this session as a user favorite
this.user.addFavorite(sessionData.name);
// create an alert instance
const alert = this.alertCtrl.create({
title: 'Favorite Added',
buttons: [{
text: 'OK',
handler: () => {
// close the sliding item
slidingItem.close();
}
}]
});
// now present the alert on top of all other content
alert.present();
}
}
removeFavorite(slidingItem: ItemSliding, sessionData: any, title: string) {
const alert = this.alertCtrl.create({
title: title,
message: 'Would you like to remove this session from your favorites?',
buttons: [
{
text: 'Cancel',
handler: () => {
// they clicked the cancel button, do not remove the session
// close the sliding item and hide the option buttons
slidingItem.close();
}
},
{
text: 'Remove',
handler: () => {
// they want to remove this session from their favorites
this.user.removeFavorite(sessionData.name);
this.updateSchedule();
// close the sliding item and hide the option buttons
slidingItem.close();
}
}
]
});
// now present the alert on top of all other content
alert.present();
}
openSocial(network: string, fab: Fab) {
const loading = this.loadingCtrl.create({
content: `Posting to ${network}`,
duration: (Math.random() * 1000) + 500
});
loading.onWillDismiss(() => {
fab.close();
});
loading.present();
}
/*doRefresh(refresher: Refresher) {
this.confData.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => {
this.shownSessions = data.shownSessions;
this.groups = data.groups;
// simulate a network request that would take longer
// than just pulling from out local json file
setTimeout(() => {
refresher.complete();
const toast = this.toastCtrl.create({
message: 'Sessions have been updated.',
duration: 3000
});
toast.present();
}, 1000);
});
}
*/
}

View File

@ -0,0 +1,19 @@
<ion-header>
<ion-toolbar>
<ion-title *ngIf="session">{{session.name}}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<div *ngIf="session">
<h1>{{session.name}}</h1>
<h4 *ngFor="let speaker of session?.speakers">
{{speaker.name}}
</h4>
<p>
{{session.timeStart}} - {{session.timeEnd}}
</p>
<p>{{session.location}}</p>
<p>{{session.description}}</p>
</div>
</ion-content>

View File

@ -0,0 +1,39 @@
import { Component } from '@angular/core';
import { NavParams } from '@ionic/angular';
import { ConferenceData } from '../../providers/conference-data';
@Component({
selector: 'page-session-detail',
templateUrl: 'session-detail.html'
})
export class SessionDetailPage {
session: any;
constructor(
public dataProvider: ConferenceData,
public navParams: NavParams
) {}
ionViewWillEnter() {
this.dataProvider.load().subscribe((data: any) => {
if (
data &&
data.schedule &&
data.schedule[0] &&
data.schedule[0].groups
) {
for (const group of data.schedule[0].groups) {
if (group && group.sessions) {
for (const session of group.sessions) {
if (session && session.id === this.navParams.data.sessionId) {
this.session = session;
break;
}
}
}
}
}
});
}
}

View File

@ -12,7 +12,7 @@
<ion-grid fixed>
<ion-row align-items-stretch>
<ion-col col-12 col-md-6 align-self-stretch align-self-center *virtualItem="let speaker" approxItemHeight="457px">
<ion-col col-12 col-md-6 align-self-stretch align-self-center *ngFor="let speaker of speakers" approxItemHeight="457px">
<ion-card class="speaker-card">
<ion-card-header>

View File

@ -10,7 +10,7 @@ import { InAppBrowser } from '@ionic-native/in-app-browser';
import { ConferenceData } from '../../providers/conference-data';
// import { SessionDetailPage } from '../session-detail/session-detail';
import { SessionDetailPage } from '../session-detail/session-detail';
import { SpeakerDetailPage } from '../speaker-detail/speaker-detail';
@Component({
@ -34,11 +34,11 @@ export class SpeakerListPage {
}
goToSessionDetail(session: any) {
// this.navCtrl.push(SessionDetailPage, { sessionId: session.id });
this.navCtrl.push(SessionDetailPage, { sessionId: session.id });
}
goToSpeakerDetail(speaker: any) {
// this.navCtrl.push(SpeakerDetailPage, { speakerId: speaker.id });
this.navCtrl.push(SpeakerDetailPage, { speakerId: speaker.id });
}
goToSpeakerTwitter(speaker: any) {

View File

@ -1,8 +1,10 @@
import { Component } from '@angular/core';
import { NavParams } from '@ionic/angular';
import { AboutPage } from '../about/about';
import { MapPage } from '../map/map';
// import { SchedulePage } from '../schedule/schedule';
import { SchedulePage } from '../schedule/schedule';
import { SpeakerListPage } from '../speaker-list/speaker-list';
@Component({
@ -10,19 +12,14 @@ import { SpeakerListPage } from '../speaker-list/speaker-list';
})
export class TabsPage {
// set the root pages for each tab
tab1Root: any = AboutPage;
tab1Root: any = SchedulePage;
tab2Root: any = SpeakerListPage;
tab3Root: any = MapPage;
tab4Root: any = AboutPage;
mySelectedIndex: number;
/*constructor(navParams: NavParams) {
constructor(navParams: NavParams) {
this.mySelectedIndex = navParams.data.tabIndex || 0;
}
*/
constructor() {
this.mySelectedIndex = 0;
}
}