32 Commits

Author SHA1 Message Date
6686f6d9e2 - Add location back to profiles
- Escape HTML in messages
2018-06-03 23:29:08 -04:00
b313bc02b7 no message 2018-06-03 21:04:04 -04:00
dc511c0a71 Linting 2018-06-03 16:49:54 -04:00
b436d3b8e9 - Hooked up profile submission
- Fixed swipe actions (between profiles / detail toggle)
2018-06-03 16:39:51 -04:00
e02b540bb0 - MOre fixes per Nick 2018-05-31 21:19:38 -04:00
b11052fd23 - Fixes per Nick 2018-05-31 20:36:47 -04:00
51e133cf8d - alignment 2018-05-29 22:58:27 -04:00
680fcef12f - more placeholder styling 2018-05-29 22:55:27 -04:00
12bd61a665 - Fixes 2018-05-29 22:47:23 -04:00
f85eeed861 - Styling the form 2018-05-29 22:43:25 -04:00
6b1142daca -fixes 2018-05-29 22:30:52 -04:00
a46cadb568 - More styling 2018-05-29 22:28:39 -04:00
73539c6d06 - The fuckery is real 2018-05-29 21:14:48 -04:00
f6f4e2a0a9 Styling 2018-05-29 21:11:02 -04:00
2b6e1668d4 Styling 2018-05-29 21:08:08 -04:00
93441f2b29 - Form style fixes 2018-05-29 20:13:47 -04:00
701cb560b7 - Form fixes 2018-05-29 20:05:41 -04:00
d70b597e4d no message 2018-05-29 20:03:23 -04:00
b124b1b1e3 - Form roughed in 2018-05-29 19:59:53 -04:00
d3fe1e3a6d - Removed unused code 2018-05-29 19:27:48 -04:00
54dd243ce4 - profile storage fixes 2018-05-29 19:27:21 -04:00
64f53271cd - fixes 2018-05-29 19:16:34 -04:00
5f0f54bf8c Merge tag '2.0.5' into develop
no message
2018-05-29 19:13:49 -04:00
fcb35f1e40 Merge branch 'release/2.0.5' 2018-05-29 19:13:49 -04:00
048c2edb9b - Grid fixes 2018-05-29 19:13:26 -04:00
f7096108f0 Merge branch 'release/2.0.4' 2018-05-29 01:32:36 -04:00
de8aa503ba Merge tag '2.0.4' into develop
no message
2018-05-29 01:32:36 -04:00
d5ca679865 - More profile fixes 2018-05-29 01:31:59 -04:00
9362d110a5 Merge branch 'release/2.0.3' 2018-05-29 01:11:46 -04:00
2e94702ec2 Merge tag '2.0.3' into develop
no message
2018-05-29 01:11:46 -04:00
709caf208a - Profiles service mapping 2018-05-29 01:11:27 -04:00
73f456ed00 Merge tag '2.0.2' into develop
no message
2018-05-29 01:08:07 -04:00
26 changed files with 320 additions and 113 deletions

View File

@@ -1,8 +1,8 @@
{
"name": "urge",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "http://ionicframework.com/",
"name": "looking",
"version": "2.0.0",
"author": "Mike Fitzpatrick",
"homepage": "http://fitz.guru/",
"private": true,
"scripts": {
"clean": "ionic-app-scripts clean",

View File

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

View File

@@ -3,7 +3,7 @@ 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 { Urnings } from './app.component';
import { Looking } from './app.component';
import { ChatPage } from '../pages/chat/chat';
import { GridPage } from '../pages/grid/grid';
@@ -20,7 +20,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
@NgModule({
declarations: [
Urnings,
Looking,
ChatPage,
InformationPage,
GridPage,
@@ -35,7 +35,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
BrowserModule,
HttpModule,
IonicSwipeAllModule,
IonicModule.forRoot(Urnings, {
IonicModule.forRoot(Looking, {
iconMode: 'ios',
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',
@@ -45,7 +45,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
],
bootstrap: [IonicApp],
entryComponents: [
Urnings,
Looking,
ChatPage,
InformationPage,
GridPage,

View File

@@ -16,14 +16,18 @@
// automatically applied to the <body> element in the app.
body {
font-family: 'PT Sans', sans-serif;
font-family: 'Lato', sans-serif;
}
h1, h2, h3, h4, h5, h6, .title, .title.toolbar-title {
font-family: 'Anonymous Pro', monospace;
}
ion-toolbar {
color: #fff;
.toolbar-background {
background-color: #000000;
background-color: #050505;
}
.bar-button,
@@ -57,7 +61,7 @@ ion-title {
.tabs {
.tabbar {
background-color: #090a0a;
background-color: #050505;
}
.tab-button {

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Urnings</title>
<title>Looking</title>
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
@@ -34,7 +34,7 @@
}
</script>-->
<link href="https://fonts.googleapis.com/css?family=PT+Sans" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Anonymous+Pro|Lato" rel="stylesheet">
<link href="build/main.css" rel="stylesheet">
</head>

View File

@@ -1,6 +1,6 @@
{
"name": "urge",
"short_name": "urge",
"name": "looking",
"short_name": "looking",
"start_url": "index.html",
"display": "standalone",
"icons": [{

View File

@@ -13,7 +13,7 @@
<ion-list>
<ion-item class="message-bubble" *ngFor="let message of this.profile.messages" [ngClass]="{ 'is-user': (message.isUser == true) }">
<img *ngIf="message.image" [src]="'https://appsby.fitz.guru/urge/' + message.image" (press)="showLightbox($event, message.image)">
<p *ngIf="message.text != ''">{{message.text}}</p>
<p *ngIf="message.text" [innerHTML]="message.text"></p>
</ion-item>
</ion-list>
</ion-content>

View File

@@ -1,5 +1,9 @@
page-chat {
.title {
text-align: left;
}
.toolbar-title {
.title-profile-avatar {
@@ -12,13 +16,16 @@ page-chat {
.message-bubble {
background-color: #fdb315;
border-radius: 0.5rem;
font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif;
line-height: 1.5;
line-height: 1.8;
margin: 1rem 1rem 2.5rem auto;
max-width: 75%;
min-height: 0;
min-width: none;
overflow: visible;
padding: 0.75rem;
position: relative;
width: -webkit-fit-content;
width: fit-content;
&.is-user {
background-color: #6fbedf;

View File

@@ -1,6 +1,6 @@
<ion-header>
<ion-toolbar>
<ion-title>Urnings</ion-title>
<ion-title>looking</ion-title>
</ion-toolbar>
</ion-header>
@@ -8,7 +8,7 @@
<ion-grid no-padding>
<ion-row align-items-stretch>
<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>
<span class="username">{{current.details.name}}</span>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -7,7 +7,6 @@ page-grid {
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
text-decoration: underline;
}
}
@@ -37,27 +36,6 @@ page-grid {
text-overflow: ellipsis;
text-shadow: 0 0 3px rgba(0, 0, 0, 1);
white-space: nowrap;
&::before {
border: 0.125rem solid #acacac;
border-radius: 1rem;
bottom: 0.125rem;
content: '';
display: inline-block;
height: 0.8rem;
margin-right: 0.5rem;
position: relative;
vertical-align: middle;
width: 0.8rem;
}
&.online {
&::before {
background-color: #00ff00;
border-color: #00ff00;
}
}
}
}
}

View File

@@ -5,7 +5,6 @@ import { NavController } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile';
import { TellYourStoryPage } from '../tell/tell';
@Component({
selector: 'page-grid',
@@ -20,6 +19,7 @@ export class GridPage {
constructor(public navCtrl: NavController, public profileService: ProfileService, private _sanitizer: DomSanitizer) {
profileService.loadVerified().then((data) => {
this.profiles = data;
console.debug('profiles: ', this.profiles);
});
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
@@ -28,10 +28,6 @@ export class GridPage {
this.tabNavEl.style.display = 'flex';
}
doTellStory() {
this.navCtrl.push(TellYourStoryPage);
}
getBackgroundThumbnail(pics) {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + pics.thumb + ')');
}
@@ -47,6 +43,7 @@ export class GridPage {
profileTapped(event, profile) {
this.navCtrl.push(ProfilePage, {
profile: profile,
profileService: this.profileService
});
}
}

View File

@@ -1,10 +1,6 @@
<ion-header>
<ion-toolbar>
<ion-buttons right>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
<ion-title>looking</ion-title>
</ion-toolbar>
</ion-header>
@@ -12,9 +8,9 @@
<div class="content-box" padding margin>
<h3>About this Project</h3>
<div class="info-blurb">
<p>The app was designed by Nicholas Pfosi and developed by Michael Fitzpatrick, modeled after the popular gay dating app Grindr.</p>
<p>Presenting these stories in this form, which is the conduit through which much participation in dating occurs, served multiple purposes. First, it educated the viewer who may not have used Grindr before, how it functions and how it is different from other apps such as Tinder, whereby matching with a person is a prerequisite for conversation. Second, it makes the scope of the project flexible, allowing for the submission of stories from the audience to be slotted into an expandable presentation.</p>
<p>Please direct any questions or concerns to Nicholas Pfosi at npfosi@gmail.com</p>
<p>The app was designed by myself and developed by Michael Fitzpatrick, modeled after the popular gay dating app Grindr. Presenting the stories in this form, which is the conduit through which much participation in dating now occurs, served multiple purposes.</p>
<p>First, it educated the viewer who may not have used Grindr before, how it functions and how it is different from other apps such as Tinder, whereby matching with a person is a prerequisite for conversation. Second, it makes the scope of the project flexible, allowing for the submission of stories from the audience to be slotted into an expandable presentation. The similarities to Grindr are deliberate and not intended to maliciously plagiarize their intellectual property or ideas.</p>
<p>The work aims to hold a mirror up to the “Grindr experience,” going beyond how the app is marketed or framed, and examine instead what its users think and feel about it and the experiences it mediates. Like any technology, it has no inherent moral orientation. I am not indicting Grindr, or even critiquing Grindr, but rather asking the question, what can we learn about ourselves and our community by looking at this app environment?</p>
</div>
</div>
</ion-content>

View File

@@ -1,5 +1,15 @@
page-information {
ion-toolbar {
.toolbar-title {
color: #ffffff;
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
}
}
.content-box {
background-color: #ffffff;
color: #000000;

View File

@@ -14,7 +14,7 @@ export class InformationPage {
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'none';
this.tabNavEl.style.display = 'flex';
}
close(event) {

View File

@@ -1,6 +1,6 @@
<ion-header>
<ion-toolbar>
<ion-title>Urnings</ion-title>
<ion-title>looking</ion-title>
</ion-toolbar>
</ion-header>

View File

@@ -7,7 +7,6 @@ page-messages {
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
text-decoration: underline;
}
}

View File

@@ -1,4 +1,4 @@
<ion-content no-padding [style.backgroundImage]="getBackground(profile.details.pic)" (press)="showLightbox($event, profile.details.pic.detail)" on-swipe-left="nextProfile($event)" on-swipe-right="previousProfile($event)">
<ion-content no-padding swipeAll [style.backgroundImage]="getBackground(profile.details.pic)" (press)="showLightbox($event, profile.details.pic.detail)" (swipeleft)="nextProfile($event)" (swiperight)="previousProfile($event)">
<ion-toolbar class="profile-toolbar">
<ion-buttons left>
<button ion-button icon-only (tap)="closeProfile($event)">
@@ -8,6 +8,14 @@
<ion-title>{{this.profile.details.name}}</ion-title>
</ion-toolbar>
<button ion-button icon-only clear large (tap)="previousProfile($event)" class="profile-nav profile-previous">
<ion-icon name="arrow-back"></ion-icon>
</button>
<button ion-button icon-only clear large (tap)="nextProfile($event)" class="profile-nav profile-next">
<ion-icon name="arrow-forward"></ion-icon>
</button>
<button ion-button icon-only clear large (tap)="openChat($event, this.profile)" class="button-chat">
<ion-icon name="ios-chatboxes"></ion-icon>
</button>
@@ -15,13 +23,16 @@
<div id="detail-overlay" class="details">
<ion-grid>
<ion-row nowrap align-items-center justify-content-between>
<ion-col col-12 text-center (click)="toggleProfileDetails($event)" class="detail-toggle">
<ion-col col-12 text-center swipeAll (click)="toggleProfileDetails($event)" (swipeup)="toggleProfileDetails($event)" (swipedown)="toggleProfileDetails($event)" class="detail-toggle">
<ion-icon name="arrow-down"></ion-icon>
</ion-col>
</ion-row>
<ion-row class="about" *ngIf="this.profile.details.about">
<ion-col col-12 [innerHTML]="this.profile.details.about"></ion-col>
</ion-row>
<ion-row class="location" *ngIf="this.profile.details.location">
<ion-col col-12><b>Location:</b> {{this.profile.details.location}}</ion-col>
</ion-row>
</ion-grid>
</div>
</ion-content>

View File

@@ -11,7 +11,6 @@ page-profile {
}
ion-toolbar {
border-bottom: 1px solid #ffffff;
transition: opacity 250ms 125ms ease-in-out;
&.hidden {
@@ -23,22 +22,62 @@ page-profile {
background-color: rgba(0, 0, 0, 1);
}
.title {
text-align: left;
}
.bar-button,
.toolbar-title {
color: #ffffff;
}
}
.profile-nav {
color: #ffffff;
display: none;
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 100;
@media screen and (min-width: 769px) {
display: block;
&.hidden {
display: none;
}
}
&.profile-next {
right: 0;
}
&.profile-previous {
left: 0;
}
}
.button-chat {
background-color: #050505;
border-radius: 50%;
box-shadow: 0 1px 3px rgba(0,0,0,.65);
bottom: 3rem;
color: #fdb315;
height: 7rem;
position: absolute;
right: 1.5rem;
width: 7rem;
z-index: 100;
.icon {
line-height: 1;
padding: 1.75rem 2.05rem;
}
}
.detail-toggle {
font-size: 2.5em;
transform: scaleX(2);
z-index: 100;
}

View File

@@ -4,22 +4,24 @@ import { NavController, NavParams } from 'ionic-angular';
import { ChatPage } from '../chat/chat';
import { LightboxPage } from '../lightbox/lightbox';
import { ProfileService } from '../../services/profiles';
@Component({
selector: 'page-profile',
templateUrl: 'profile.html',
providers: [ ProfileService ]
templateUrl: 'profile.html'
})
export class ProfilePage {
detailsOpen: boolean = false;
profile: any;
profileService: any;
profileType: string = 'all';
tabNavEl: any;
constructor(public navCtrl: NavController, public navParams: NavParams, public profileService: ProfileService, private _sanitizer: DomSanitizer) {
constructor(public navCtrl: NavController, public navParams: NavParams, private _sanitizer: DomSanitizer) {
this.profile = navParams.get('profile');
this.profileType = this.profile.submitted ? 'submitted' : 'verified';
this.profileService = navParams.get('profileService');
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
}
@@ -34,6 +36,8 @@ export class ProfilePage {
closeProfileDetails(event) {
if (this.detailsOpen) {
this.detailsOpen = false;
document.querySelector('.profile-nav.profile-next').classList.remove('hidden');
document.querySelector('.profile-nav.profile-previous').classList.remove('hidden');
document.querySelector('.profile-toolbar').classList.remove('hidden');
document.getElementById('detail-overlay').classList.remove('open');
}
@@ -48,8 +52,7 @@ export class ProfilePage {
}
nextProfile(event) {
this.profile = this.profileService.getNextProfile(this.profile._id);
this.navCtrl.setRoot(this.navCtrl.getActive().component);
this.profile = this.profileService.getNextProfile(this.profile._id, this.profileType);
}
openChat(event, profile) {
@@ -61,14 +64,15 @@ export class ProfilePage {
openProfileDetails(event) {
if (!this.detailsOpen) {
this.detailsOpen = true;
document.querySelector('.profile-nav.profile-next').classList.add('hidden');
document.querySelector('.profile-nav.profile-previous').classList.add('hidden');
document.querySelector('.profile-toolbar').classList.add('hidden');
document.getElementById('detail-overlay').classList.add('open');
}
}
previousProfile(event) {
this.profile = this.profileService.getPreviousProfile(this.profile._id);
this.navCtrl.setRoot(this.navCtrl.getActive().component);
this.profile = this.profileService.getPreviousProfile(this.profile._id, this.profileType);
}
showLightbox(event, image) {

View File

@@ -1,12 +1,46 @@
<ion-header>
<ion-toolbar>
<ion-buttons right>
<ion-buttons left>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="close"></ion-icon>
<ion-icon name="arrow-back"></ion-icon>
</button>
</ion-buttons>
<ion-title>Submit Your Story</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-content padding>
<p class="intro">Submit your story using the following form. Nicholas may be in touch to clarify what youve written and he reserves the right to vet stories for accuracy and appropriateness.</p>
<form [formGroup]="userSubmissionForm" novalidate>
<div class="item item-block item-input item-label-stacked file-upload-wrapper">
<div class="input-wrapper">
<label class="label">Upload a photo</label>
<label class="upload-trigger file-label" for="pic-upload" role="button">
<ion-icon name="person"></ion-icon>
</label>
<div class="input">
<input type="file" id="pic-upload" name="pic" class="file-input" />
</div>
</div>
</div>
<ion-item>
<ion-label stacked>Display name</ion-label>
<ion-input type="text" formControlName="name" name="name" placeholder="Please enter text here"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>Email Address</ion-label>
<ion-input type="email" formControlName="email" name="email" placeholder="Please enter text here"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>About you</ion-label>
<ion-textarea formControlName="about" name="about" placeholder="Please enter text here"></ion-textarea>
</ion-item>
<ion-item>
<ion-label stacked>What is your your experience dating in the LGBT community?</ion-label>
<ion-textarea formControlName="messages" name="messages" placeholder="Please enter text here"></ion-textarea>
</ion-item>
<div padding>
<button ion-button type="submit" block (click)="saveUserSubmission($event)">Submit</button>
</div>
</form>
</ion-content>

View File

@@ -1,27 +1,72 @@
page-tell-your-story {
ion-col {
.title {
text-align: left;
}
&.cruise {
background-size: cover;
border: 1px solid #000000;
box-sizing: border-box;
padding: 0 0 37.5% !important;
position: relative;
.item.item-block {
padding-left: 0;
}
.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;
.input-wrapper {
align-items: flex-start;
.label {
font-size: 0.9em;
font-weight: 700;
margin-bottom: 4px;
text-align: left;
}
}
ion-input, ion-textarea {
input, textarea {
&::placeholder,
&::-webkit-input-placeholder,
&::-moz-placeholder,
&:-ms-input-placeholder,
&:-moz-placeholder {
color: #94949D;
}
}
}
.file-upload-wrapper {
text-align: left;
.upload-trigger {
border: 0.2rem solid #94949D;
color: #94949D;
display: block;
font-size: 7.8rem;
height: 9.8rem;
text-align: center;
width: 9.8rem;
}
input {
display: none;
}
}
.button.button-block {
background-color: #fdb315;
.button-inner {
color: #191b1c;
}
}
.item-input-has-focus .label-md[stacked],
.input-has-focus .label-md[stacked] {
color: #fdb315;
}
.item-md.item-input.item-input-has-focus .item-inner,
.item-md.item-input.input-has-focus .item-inner {
border-bottom-color: #fdb315;
box-shadow: inset 0 -1px 0 0 #fdb315;
}
}

View File

@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ProfileService } from '../../services/profiles';
@@ -11,16 +12,69 @@ import { ProfileService } from '../../services/profiles';
export class TellYourStoryPage {
tabNavEl: any;
fileInput: any;
fileLabel: any;
userSubmissionForm: FormGroup;
constructor(public navCtrl: NavController) {
constructor(public navCtrl: NavController, public profileService: ProfileService, private formBuilder: FormBuilder) {
this.tabNavEl = document.querySelector('#tab-nav .tabbar');
this.userSubmissionForm = this.formBuilder.group({
name: [''],
about: [''],
email: [''],
messages: ['']
});
}
ionViewWillEnter() {
this.tabNavEl.style.display = 'none';
this.fileInput = document.querySelector('.file-input');
this.fileLabel = document.querySelector('.file-label');
this.fileInput.addEventListener('change', this.handleFileChange.bind(this), false);
}
close(event) {
this.navCtrl.pop();
}
handleFileChange(event) {
this.fileLabel.style.backgroundImage = this.fileInput.files[0];
//this.fileLabel.querySelector('ion-icon').style.display = none;
}
saveUserSubmission(event) {
// Setup submission for insert
var submission: any = {};
submission.image = this.fileInput.files[0];
submission.profile = JSON.stringify({
details: {
name: this.userSubmissionForm.value.name,
email: this.userSubmissionForm.value.email,
about: this.userSubmissionForm.value.about,
location: this.userSubmissionForm.value.location
},
messages: [
{
text: "What is your your experience dating in the LGBT community?",
isUser: false,
timestamp: (Date.now() - 900000)
},
{
text: this.userSubmissionForm.value.messages,
isUser: true,
timestamp: Date.now()
}
]
});
this.profileService.doProfileSubmission(submission,
function (data) {
console.debug('saveUserSubmission Success', data);
},
function (data, status) {
console.error('saveUserSubmission Error', data, status);
});
}
}

View File

@@ -1,6 +1,6 @@
<ion-header>
<ion-toolbar>
<ion-title>Urnings</ion-title>
<ion-title>looking</ion-title>
</ion-toolbar>
</ion-header>

View File

@@ -7,7 +7,6 @@ page-users {
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
text-decoration: underline;
}
}

View File

@@ -7,20 +7,21 @@ export class ProfileService {
endpoint: string = 'https://api.fitz.guru/urnings/profiles';
fallback: string = 'assets/data/profiles.json';
epSubmission: string = '/submission';
epSubmitted: string = '/submitted';
epVerified: string = '/verified';
idMap: any = { all: {}, submitted: {}, verified: {} };
idMap: any;
profiles: any;
constructor(private http: Http) {
this.idMap = {};
this.idMap = { all: {}, submitted: {}, verified: {} };
this.profiles = null;
}
load() {
if (this.profiles) {
return Promise.resolve(this.profiles);
if (this.profiles && this.profiles.all) {
return Promise.resolve(this.profiles.all);
}
return new Promise(resolve => {
@@ -29,8 +30,8 @@ export class ProfileService {
}
loadSubmitted() {
if (this.profiles) {
return Promise.resolve(this.profiles);
if (this.profiles && this.profiles.submitted) {
return Promise.resolve(this.profiles.submitted);
}
return new Promise(resolve => {
@@ -39,8 +40,8 @@ export class ProfileService {
}
loadVerified() {
if (this.profiles) {
return Promise.resolve(this.profiles);
if (this.profiles && this.profiles.verified) {
return Promise.resolve(this.profiles.verified);
}
return new Promise(resolve => {
@@ -53,18 +54,47 @@ export class ProfileService {
.map(res => res.json())
.subscribe(
data => {
this.profiles = {};
this.profiles = this.profiles || {};
this.profiles[type] = data;
this.profiles.reduce((map, profile, i) => {
this.profiles[type].reduce((map, profile, i) => {
map[profile._id] = i;
return map;
}, this.idMap[type]);
resolve(this.profiles[type]);
},
error => {
this.doGetRequest(this.fallback, resolve);
this.doGetRequest(this.fallback, resolve, type);
}
)
);
}
doProfileSubmission(submission, success: any = false, failure: any = false) {
success = success || function (data) {
console.debug('doProfileSubmission Success', data);
};
failure = failure || function (data, status) {
console.error('doProfileSubmission Error', data, status);
};
var httpOptions: any = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
var formData = new FormData();
for (let property in submission) {
formData.append(property, submission[property]);
}
this.http
.post(this.endpoint + this.epSubmission, formData, httpOptions)
.subscribe(data => {
success(data);
}, error => {
failure(error, false);
});
}
getNextProfile(id, type = 'all') {
@@ -80,18 +110,18 @@ export class ProfileService {
}
getProfiles() {
return this.profiles;
return this.profiles.all;
}
getProfileById(id) {
return this.profiles[this.idMap[id]];
getProfileById(id, type = 'all') {
return this.profiles[type][this.idMap[type][id]];
}
getSubmittedProfiles() {
return this.profiles.submitted;
}
getVerifiedProfiles() {
return this.profiles.verified;
}
}