38 Commits
Author SHA1 Message Date
mifi 6686f6d9e2 - Add location back to profiles
- Escape HTML in messages
2018-06-03 23:29:08 -04:00
mifi b313bc02b7 no message 2018-06-03 21:04:04 -04:00
mifi dc511c0a71 Linting 2018-06-03 16:49:54 -04:00
mifi b436d3b8e9 - Hooked up profile submission
- Fixed swipe actions (between profiles / detail toggle)
2018-06-03 16:39:51 -04:00
mifi e02b540bb0 - MOre fixes per Nick 2018-05-31 21:19:38 -04:00
mifi b11052fd23 - Fixes per Nick 2018-05-31 20:36:47 -04:00
mifi 51e133cf8d - alignment 2018-05-29 22:58:27 -04:00
mifi 680fcef12f - more placeholder styling 2018-05-29 22:55:27 -04:00
mifi 12bd61a665 - Fixes 2018-05-29 22:47:23 -04:00
mifi f85eeed861 - Styling the form 2018-05-29 22:43:25 -04:00
mifi 6b1142daca -fixes 2018-05-29 22:30:52 -04:00
mifi a46cadb568 - More styling 2018-05-29 22:28:39 -04:00
mifi 73539c6d06 - The fuckery is real 2018-05-29 21:14:48 -04:00
mifi f6f4e2a0a9 Styling 2018-05-29 21:11:02 -04:00
mifi 2b6e1668d4 Styling 2018-05-29 21:08:08 -04:00
mifi 93441f2b29 - Form style fixes 2018-05-29 20:13:47 -04:00
mifi 701cb560b7 - Form fixes 2018-05-29 20:05:41 -04:00
mifi d70b597e4d no message 2018-05-29 20:03:23 -04:00
mifi b124b1b1e3 - Form roughed in 2018-05-29 19:59:53 -04:00
mifi d3fe1e3a6d - Removed unused code 2018-05-29 19:27:48 -04:00
mifi 54dd243ce4 - profile storage fixes 2018-05-29 19:27:21 -04:00
mifi 64f53271cd - fixes 2018-05-29 19:16:34 -04:00
mifi 5f0f54bf8c Merge tag '2.0.5' into develop
no message
2018-05-29 19:13:49 -04:00
mifi fcb35f1e40 Merge branch 'release/2.0.5' 2018-05-29 19:13:49 -04:00
mifi 048c2edb9b - Grid fixes 2018-05-29 19:13:26 -04:00
mifi f7096108f0 Merge branch 'release/2.0.4' 2018-05-29 01:32:36 -04:00
mifi de8aa503ba Merge tag '2.0.4' into develop
no message
2018-05-29 01:32:36 -04:00
mifi d5ca679865 - More profile fixes 2018-05-29 01:31:59 -04:00
mifi 9362d110a5 Merge branch 'release/2.0.3' 2018-05-29 01:11:46 -04:00
mifi 2e94702ec2 Merge tag '2.0.3' into develop
no message
2018-05-29 01:11:46 -04:00
mifi 709caf208a - Profiles service mapping 2018-05-29 01:11:27 -04:00
mifi 70fe066cdd Merge branch 'release/2.0.2' 2018-05-29 01:08:07 -04:00
mifi 73f456ed00 Merge tag '2.0.2' into develop
no message
2018-05-29 01:08:07 -04:00
mifi c9431f62ef - profiles service fixes 2018-05-29 01:07:25 -04:00
mifi b91f7fcfba Merge branch 'release/2.0.1' 2018-05-29 00:37:55 -04:00
mifi 58b25b0a44 Merge tag '2.0.1' into develop
no message
2018-05-29 00:37:55 -04:00
mifi 01ed427b54 - Fix for verified profiles 2018-05-29 00:37:30 -04:00
mifi 8fd37ec556 Merge tag '2.0' into develop
UI Revisions
2018-05-29 00:31:52 -04:00
26 changed files with 329 additions and 122 deletions
+4 -4
View File
@@ -1,8 +1,8 @@
{ {
"name": "urge", "name": "looking",
"version": "0.0.1", "version": "2.0.0",
"author": "Ionic Framework", "author": "Mike Fitzpatrick",
"homepage": "http://ionicframework.com/", "homepage": "http://fitz.guru/",
"private": true, "private": true,
"scripts": { "scripts": {
"clean": "ionic-app-scripts clean", "clean": "ionic-app-scripts clean",
+1 -1
View File
@@ -8,7 +8,7 @@ import { TabsPage } from '../pages/tabs/tabs';
@Component({ @Component({
templateUrl: 'app.html' templateUrl: 'app.html'
}) })
export class Urnings { export class Looking {
rootPage: any = TabsPage; rootPage: any = TabsPage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) { constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
+4 -4
View File
@@ -3,7 +3,7 @@ import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http'; import { HttpModule } from '@angular/http';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular'; import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { IonicSwipeAllModule } from 'ionic-swipe-all'; import { IonicSwipeAllModule } from 'ionic-swipe-all';
import { Urnings } from './app.component'; import { Looking } from './app.component';
import { ChatPage } from '../pages/chat/chat'; import { ChatPage } from '../pages/chat/chat';
import { GridPage } from '../pages/grid/grid'; import { GridPage } from '../pages/grid/grid';
@@ -20,7 +20,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
@NgModule({ @NgModule({
declarations: [ declarations: [
Urnings, Looking,
ChatPage, ChatPage,
InformationPage, InformationPage,
GridPage, GridPage,
@@ -35,7 +35,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
BrowserModule, BrowserModule,
HttpModule, HttpModule,
IonicSwipeAllModule, IonicSwipeAllModule,
IonicModule.forRoot(Urnings, { IonicModule.forRoot(Looking, {
iconMode: 'ios', iconMode: 'ios',
modalEnter: 'modal-slide-in', modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out', modalLeave: 'modal-slide-out',
@@ -45,7 +45,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
], ],
bootstrap: [IonicApp], bootstrap: [IonicApp],
entryComponents: [ entryComponents: [
Urnings, Looking,
ChatPage, ChatPage,
InformationPage, InformationPage,
GridPage, GridPage,
+7 -3
View File
@@ -16,14 +16,18 @@
// automatically applied to the <body> element in the app. // automatically applied to the <body> element in the app.
body { 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 { ion-toolbar {
color: #fff; color: #fff;
.toolbar-background { .toolbar-background {
background-color: #000000; background-color: #050505;
} }
.bar-button, .bar-button,
@@ -57,7 +61,7 @@ ion-title {
.tabs { .tabs {
.tabbar { .tabbar {
background-color: #090a0a; background-color: #050505;
} }
.tab-button { .tab-button {
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -2,7 +2,7 @@
<html lang="en" dir="ltr"> <html lang="en" dir="ltr">
<head> <head>
<meta charset="UTF-8"> <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="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="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no"> <meta name="msapplication-tap-highlight" content="no">
@@ -34,7 +34,7 @@
} }
</script>--> </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"> <link href="build/main.css" rel="stylesheet">
</head> </head>
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "urge", "name": "looking",
"short_name": "urge", "short_name": "looking",
"start_url": "index.html", "start_url": "index.html",
"display": "standalone", "display": "standalone",
"icons": [{ "icons": [{
+1 -1
View File
@@ -13,7 +13,7 @@
<ion-list> <ion-list>
<ion-item class="message-bubble" *ngFor="let message of this.profile.messages" [ngClass]="{ 'is-user': (message.isUser == true) }"> <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)"> <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-item>
</ion-list> </ion-list>
</ion-content> </ion-content>
+9 -2
View File
@@ -1,5 +1,9 @@
page-chat { page-chat {
.title {
text-align: left;
}
.toolbar-title { .toolbar-title {
.title-profile-avatar { .title-profile-avatar {
@@ -12,13 +16,16 @@ page-chat {
.message-bubble { .message-bubble {
background-color: #fdb315; background-color: #fdb315;
border-radius: 0.5rem; border-radius: 0.5rem;
font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif; line-height: 1.8;
line-height: 1.5;
margin: 1rem 1rem 2.5rem auto; margin: 1rem 1rem 2.5rem auto;
max-width: 75%; max-width: 75%;
min-height: 0;
min-width: none;
overflow: visible; overflow: visible;
padding: 0.75rem; padding: 0.75rem;
position: relative; position: relative;
width: -webkit-fit-content;
width: fit-content;
&.is-user { &.is-user {
background-color: #6fbedf; background-color: #6fbedf;
+2 -2
View File
@@ -1,6 +1,6 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title>Urnings</ion-title> <ion-title>looking</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
@@ -8,7 +8,7 @@
<ion-grid no-padding> <ion-grid no-padding>
<ion-row align-items-stretch> <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)"> <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-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>
-22
View File
@@ -7,7 +7,6 @@ page-grid {
font-size: 2.42em; font-size: 2.42em;
font-weight: 700; font-weight: 700;
line-height: 1.29; line-height: 1.29;
text-decoration: underline;
} }
} }
@@ -37,27 +36,6 @@ page-grid {
text-overflow: ellipsis; text-overflow: ellipsis;
text-shadow: 0 0 3px rgba(0, 0, 0, 1); text-shadow: 0 0 3px rgba(0, 0, 0, 1);
white-space: nowrap; 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;
}
}
} }
} }
} }
+3 -6
View File
@@ -5,7 +5,6 @@ import { NavController } from 'ionic-angular';
import { ChatPage } from '../chat/chat'; import { ChatPage } from '../chat/chat';
import { ProfileService } from '../../services/profiles'; import { ProfileService } from '../../services/profiles';
import { ProfilePage } from '../profile/profile'; import { ProfilePage } from '../profile/profile';
import { TellYourStoryPage } from '../tell/tell';
@Component({ @Component({
selector: 'page-grid', selector: 'page-grid',
@@ -18,8 +17,9 @@ export class GridPage {
tabNavEl: any; tabNavEl: any;
constructor(public navCtrl: NavController, public profileService: ProfileService, private _sanitizer: DomSanitizer) { constructor(public navCtrl: NavController, public profileService: ProfileService, private _sanitizer: DomSanitizer) {
profileService.load().then((data) => { profileService.loadVerified().then((data) => {
this.profiles = data; this.profiles = data;
console.debug('profiles: ', this.profiles);
}); });
this.tabNavEl = document.querySelector('#tab-nav .tabbar'); this.tabNavEl = document.querySelector('#tab-nav .tabbar');
} }
@@ -28,10 +28,6 @@ export class GridPage {
this.tabNavEl.style.display = 'flex'; this.tabNavEl.style.display = 'flex';
} }
doTellStory() {
this.navCtrl.push(TellYourStoryPage);
}
getBackgroundThumbnail(pics) { getBackgroundThumbnail(pics) {
return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + pics.thumb + ')'); return this._sanitizer.bypassSecurityTrustStyle('url(https://appsby.fitz.guru/urge/' + pics.thumb + ')');
} }
@@ -47,6 +43,7 @@ export class GridPage {
profileTapped(event, profile) { profileTapped(event, profile) {
this.navCtrl.push(ProfilePage, { this.navCtrl.push(ProfilePage, {
profile: profile, profile: profile,
profileService: this.profileService
}); });
} }
} }
+4 -8
View File
@@ -1,10 +1,6 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-buttons right> <ion-title>looking</ion-title>
<button ion-button icon-only (tap)="close($event)">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
@@ -12,9 +8,9 @@
<div class="content-box" padding margin> <div class="content-box" padding margin>
<h3>About this Project</h3> <h3>About this Project</h3>
<div class="info-blurb"> <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>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>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>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>Please direct any questions or concerns to Nicholas Pfosi at npfosi@gmail.com</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>
</div> </div>
</ion-content> </ion-content>
+10
View File
@@ -1,5 +1,15 @@
page-information { page-information {
ion-toolbar {
.toolbar-title {
color: #ffffff;
font-size: 2.42em;
font-weight: 700;
line-height: 1.29;
}
}
.content-box { .content-box {
background-color: #ffffff; background-color: #ffffff;
color: #000000; color: #000000;
+1 -1
View File
@@ -14,7 +14,7 @@ export class InformationPage {
} }
ionViewWillEnter() { ionViewWillEnter() {
this.tabNavEl.style.display = 'none'; this.tabNavEl.style.display = 'flex';
} }
close(event) { close(event) {
+1 -1
View File
@@ -1,6 +1,6 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title>Urnings</ion-title> <ion-title>looking</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
-1
View File
@@ -7,7 +7,6 @@ page-messages {
font-size: 2.42em; font-size: 2.42em;
font-weight: 700; font-weight: 700;
line-height: 1.29; line-height: 1.29;
text-decoration: underline;
} }
} }
+13 -2
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-toolbar class="profile-toolbar">
<ion-buttons left> <ion-buttons left>
<button ion-button icon-only (tap)="closeProfile($event)"> <button ion-button icon-only (tap)="closeProfile($event)">
@@ -8,6 +8,14 @@
<ion-title>{{this.profile.details.name}}</ion-title> <ion-title>{{this.profile.details.name}}</ion-title>
</ion-toolbar> </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"> <button ion-button icon-only clear large (tap)="openChat($event, this.profile)" class="button-chat">
<ion-icon name="ios-chatboxes"></ion-icon> <ion-icon name="ios-chatboxes"></ion-icon>
</button> </button>
@@ -15,13 +23,16 @@
<div id="detail-overlay" class="details"> <div id="detail-overlay" class="details">
<ion-grid> <ion-grid>
<ion-row nowrap align-items-center justify-content-between> <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-icon name="arrow-down"></ion-icon>
</ion-col> </ion-col>
</ion-row> </ion-row>
<ion-row class="about" *ngIf="this.profile.details.about"> <ion-row class="about" *ngIf="this.profile.details.about">
<ion-col col-12 [innerHTML]="this.profile.details.about"></ion-col> <ion-col col-12 [innerHTML]="this.profile.details.about"></ion-col>
</ion-row> </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> </ion-grid>
</div> </div>
</ion-content> </ion-content>
+40 -1
View File
@@ -11,7 +11,6 @@ page-profile {
} }
ion-toolbar { ion-toolbar {
border-bottom: 1px solid #ffffff;
transition: opacity 250ms 125ms ease-in-out; transition: opacity 250ms 125ms ease-in-out;
&.hidden { &.hidden {
@@ -23,22 +22,62 @@ page-profile {
background-color: rgba(0, 0, 0, 1); background-color: rgba(0, 0, 0, 1);
} }
.title {
text-align: left;
}
.bar-button, .bar-button,
.toolbar-title { .toolbar-title {
color: #ffffff; 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 { .button-chat {
background-color: #050505;
border-radius: 50%;
box-shadow: 0 1px 3px rgba(0,0,0,.65);
bottom: 3rem; bottom: 3rem;
color: #fdb315; color: #fdb315;
height: 7rem;
position: absolute; position: absolute;
right: 1.5rem; right: 1.5rem;
width: 7rem;
z-index: 100; z-index: 100;
.icon {
line-height: 1;
padding: 1.75rem 2.05rem;
}
} }
.detail-toggle { .detail-toggle {
font-size: 2.5em; font-size: 2.5em;
transform: scaleX(2);
z-index: 100; z-index: 100;
} }
+12 -8
View File
@@ -4,22 +4,24 @@ import { NavController, NavParams } from 'ionic-angular';
import { ChatPage } from '../chat/chat'; import { ChatPage } from '../chat/chat';
import { LightboxPage } from '../lightbox/lightbox'; import { LightboxPage } from '../lightbox/lightbox';
import { ProfileService } from '../../services/profiles';
@Component({ @Component({
selector: 'page-profile', selector: 'page-profile',
templateUrl: 'profile.html', templateUrl: 'profile.html'
providers: [ ProfileService ]
}) })
export class ProfilePage { export class ProfilePage {
detailsOpen: boolean = false; detailsOpen: boolean = false;
profile: any; profile: any;
profileService: any;
profileType: string = 'all';
tabNavEl: any; 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.profile = navParams.get('profile');
this.profileType = this.profile.submitted ? 'submitted' : 'verified';
this.profileService = navParams.get('profileService');
this.tabNavEl = document.querySelector('#tab-nav .tabbar'); this.tabNavEl = document.querySelector('#tab-nav .tabbar');
} }
@@ -34,6 +36,8 @@ export class ProfilePage {
closeProfileDetails(event) { closeProfileDetails(event) {
if (this.detailsOpen) { if (this.detailsOpen) {
this.detailsOpen = false; 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.querySelector('.profile-toolbar').classList.remove('hidden');
document.getElementById('detail-overlay').classList.remove('open'); document.getElementById('detail-overlay').classList.remove('open');
} }
@@ -48,8 +52,7 @@ export class ProfilePage {
} }
nextProfile(event) { nextProfile(event) {
this.profile = this.profileService.getNextProfile(this.profile._id); this.profile = this.profileService.getNextProfile(this.profile._id, this.profileType);
this.navCtrl.setRoot(this.navCtrl.getActive().component);
} }
openChat(event, profile) { openChat(event, profile) {
@@ -61,14 +64,15 @@ export class ProfilePage {
openProfileDetails(event) { openProfileDetails(event) {
if (!this.detailsOpen) { if (!this.detailsOpen) {
this.detailsOpen = true; 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.querySelector('.profile-toolbar').classList.add('hidden');
document.getElementById('detail-overlay').classList.add('open'); document.getElementById('detail-overlay').classList.add('open');
} }
} }
previousProfile(event) { previousProfile(event) {
this.profile = this.profileService.getPreviousProfile(this.profile._id); this.profile = this.profileService.getPreviousProfile(this.profile._id, this.profileType);
this.navCtrl.setRoot(this.navCtrl.getActive().component);
} }
showLightbox(event, image) { showLightbox(event, image) {
+37 -3
View File
@@ -1,12 +1,46 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-buttons right> <ion-buttons left>
<button ion-button icon-only (tap)="close($event)"> <button ion-button icon-only (tap)="close($event)">
<ion-icon name="close"></ion-icon> <ion-icon name="arrow-back"></ion-icon>
</button> </button>
</ion-buttons> </ion-buttons>
<ion-title>Submit Your Story</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </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> </ion-content>
+64 -19
View File
@@ -1,27 +1,72 @@
page-tell-your-story { page-tell-your-story {
ion-col { .title {
text-align: left;
}
&.cruise { .item.item-block {
background-size: cover; padding-left: 0;
border: 1px solid #000000; }
box-sizing: border-box;
padding: 0 0 37.5% !important;
position: relative;
.placename { .input-wrapper {
bottom: 0.25rem; align-items: flex-start;
box-sizing: border-box;
color: #acacac; .label {
display: inline-block; font-size: 0.9em;
left: 0.5rem; font-weight: 700;
overflow: hidden; margin-bottom: 4px;
position: absolute; text-align: left;
right: 0.25rem; }
text-overflow: ellipsis; }
text-shadow: rgba(0, 0, 0, 1);
white-space: nowrap; 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;
}
} }
+55 -1
View File
@@ -1,5 +1,6 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { NavController } from 'ionic-angular'; import { NavController } from 'ionic-angular';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ProfileService } from '../../services/profiles'; import { ProfileService } from '../../services/profiles';
@@ -11,16 +12,69 @@ import { ProfileService } from '../../services/profiles';
export class TellYourStoryPage { export class TellYourStoryPage {
tabNavEl: any; 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.tabNavEl = document.querySelector('#tab-nav .tabbar');
this.userSubmissionForm = this.formBuilder.group({
name: [''],
about: [''],
email: [''],
messages: ['']
});
} }
ionViewWillEnter() { ionViewWillEnter() {
this.tabNavEl.style.display = 'none'; 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) { close(event) {
this.navCtrl.pop(); 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);
});
}
} }
+1 -1
View File
@@ -1,6 +1,6 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title>Urnings</ion-title> <ion-title>looking</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
-1
View File
@@ -7,7 +7,6 @@ page-users {
font-size: 2.42em; font-size: 2.42em;
font-weight: 700; font-weight: 700;
line-height: 1.29; line-height: 1.29;
text-decoration: underline;
} }
} }
+55 -25
View File
@@ -7,20 +7,21 @@ export class ProfileService {
endpoint: string = 'https://api.fitz.guru/urnings/profiles'; endpoint: string = 'https://api.fitz.guru/urnings/profiles';
fallback: string = 'assets/data/profiles.json'; fallback: string = 'assets/data/profiles.json';
epSubmission: string = '/submission';
epSubmitted: string = '/submitted'; epSubmitted: string = '/submitted';
epVerified: string = '/verified'; epVerified: string = '/verified';
idMap: any = { all: {}, submitted: {}, verified: {} }; idMap: any;
profiles: any; profiles: any;
constructor(private http: Http) { constructor(private http: Http) {
this.idMap = {}; this.idMap = { all: {}, submitted: {}, verified: {} };
this.profiles = null; this.profiles = null;
} }
load() { load() {
if (this.profiles) { if (this.profiles && this.profiles.all) {
return Promise.resolve(this.profiles); return Promise.resolve(this.profiles.all);
} }
return new Promise(resolve => { return new Promise(resolve => {
@@ -29,8 +30,8 @@ export class ProfileService {
} }
loadSubmitted() { loadSubmitted() {
if (this.profiles) { if (this.profiles && this.profiles.submitted) {
return Promise.resolve(this.profiles); return Promise.resolve(this.profiles.submitted);
} }
return new Promise(resolve => { return new Promise(resolve => {
@@ -39,8 +40,8 @@ export class ProfileService {
} }
loadVerified() { loadVerified() {
if (this.profiles) { if (this.profiles && this.profiles.verified) {
return Promise.resolve(this.profiles); return Promise.resolve(this.profiles.verified);
} }
return new Promise(resolve => { return new Promise(resolve => {
@@ -53,45 +54,74 @@ export class ProfileService {
.map(res => res.json()) .map(res => res.json())
.subscribe( .subscribe(
data => { data => {
this.profiles = {}; this.profiles = this.profiles || {};
this.profiles[type] = data; this.profiles[type] = data;
this.profiles.reduce((map, profile, i) => { this.profiles[type].reduce((map, profile, i) => {
map[profile._id] = i; map[profile._id] = i;
return map; return map;
}, this.idMap[type]); }, this.idMap[type]);
resolve(this.profiles[type]); resolve(this.profiles[type]);
}, },
error => { error => {
this.doGetRequest(this.fallback, resolve); this.doGetRequest(this.fallback, resolve, type);
} }
) );
} }
getNextProfile(id, type) { doProfileSubmission(submission, success: any = false, failure: any = false) {
var nextIdIndex = this.idMap[id] + 1; success = success || function (data) {
nextIdIndex = nextIdIndex >= this.profiles.length ? 0 : nextIdIndex; console.debug('doProfileSubmission Success', data);
return this.profiles[nextIdIndex]; };
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]);
} }
getPreviousProfile(id, type) { this.http
var prevIdIndex = this.idMap[id] + 1; .post(this.endpoint + this.epSubmission, formData, httpOptions)
prevIdIndex = prevIdIndex < 0 ? (this.profiles.length - 1) : prevIdIndex; .subscribe(data => {
return this.profiles[prevIdIndex]; success(data);
}, error => {
failure(error, false);
});
}
getNextProfile(id, type = 'all') {
var nextIdIndex = this.idMap[type][id] + 1;
nextIdIndex = nextIdIndex >= this.profiles[type].length ? 0 : nextIdIndex;
return this.profiles[type][nextIdIndex];
}
getPreviousProfile(id, type = 'all') {
var prevIdIndex = this.idMap[type][id] - 1;
prevIdIndex = prevIdIndex < 0 ? (this.profiles[type].length - 1) : prevIdIndex;
return this.profiles[type][prevIdIndex];
} }
getProfiles() { getProfiles() {
return this.profiles; return this.profiles.all;
} }
getProfileById(id) { getProfileById(id, type = 'all') {
return this.profiles[this.idMap[id]]; return this.profiles[type][this.idMap[type][id]];
} }
getSubmittedProfiles() { getSubmittedProfiles() {
return this.profiles.submitted;
} }
getVerifiedProfiles() { getVerifiedProfiles() {
return this.profiles.verified;
} }
} }