Merge branch 'master' into test
# Conflicts: # app/events/event-list/event-list.component.ts # app/events/events/events.component.ts # package.json
This commit is contained in:
Коммит
efe385e76d
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 565 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 427 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 917 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.2 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.0 KiB |
|
@ -26,7 +26,8 @@
|
|||
<item name="colorPrimary">@color/ns_primary</item>
|
||||
<item name="colorPrimaryDark">@color/ns_primaryDark</item>
|
||||
<item name="colorAccent">@color/ns_accent</item>
|
||||
<item name="colorControlNormal">#fff</item>
|
||||
<item name="colorControlNormal">#000</item>
|
||||
<item name="actionOverflowButtonStyle">@style/OverflowMenuButton</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme" parent="AppThemeBase">
|
||||
|
@ -42,4 +43,8 @@
|
|||
|
||||
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
|
||||
</style>
|
||||
|
||||
<style name="OverflowMenuButton" parent="@style/Widget.AppCompat.ActionButton.Overflow">
|
||||
<item name="android:src">@drawable/icon_overflow</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
@ -37,9 +37,6 @@
|
|||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
28
app/app.css
28
app/app.css
|
@ -1,4 +1,4 @@
|
|||
@import url('~/css/core.light.css');
|
||||
@import '~/css/core.light.css';
|
||||
@import url('~/platform.css');
|
||||
|
||||
.if {
|
||||
|
@ -54,32 +54,6 @@ ActivityIndicator {
|
|||
color: #F4550F;
|
||||
}
|
||||
|
||||
.switch {
|
||||
margin: 14 16 14 0;
|
||||
color: #333;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.switch[checked=true] {
|
||||
background-color: #F4550F;
|
||||
color: #F4550F;
|
||||
}
|
||||
|
||||
.switch[checked=true][isEnabled=false] {
|
||||
background-color: #e0e0e0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.switch[isEnabled=false] {
|
||||
background-color: #e0e0e0;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.switch .btn-primary.btn-active:highlighted {
|
||||
border-color: #F4550F;
|
||||
background-color: #F4550F;
|
||||
}
|
||||
|
||||
.switch-field .switch,
|
||||
.switch-field .label {
|
||||
vertical-align: middle;
|
||||
|
|
|
@ -206,16 +206,28 @@ export class EventDetailsComponent implements OnInit {
|
|||
this._routerExtensions.navigateByUrl(`/events/${this.event.Id}/participants`);
|
||||
}
|
||||
|
||||
rethinkMode() {
|
||||
return this.event && !this.isPastEvent && this.event.RegistrationCompleted;
|
||||
}
|
||||
|
||||
canRegister() {
|
||||
return !this.alreadyRegistered && !this.isPastEvent && this.event.OpenForRegistration && !this.event.RegistrationCompleted;
|
||||
return this.event && !this.alreadyRegistered && !this.isPastEvent && this._openAndNotComplete();
|
||||
}
|
||||
|
||||
canUnregister() {
|
||||
return this.event && this.alreadyRegistered && !this.isPastEvent && this.event.OpenForRegistration && !this.event.RegistrationCompleted;
|
||||
return this._reggedAndNotPast() && this._openAndNotComplete();
|
||||
}
|
||||
|
||||
canChangeVote() {
|
||||
return this.event && this.alreadyRegistered && !this.event.EventDate;
|
||||
return this._reggedAndNotPast() && !this.event.EventDate && !this.event.RegistrationCompleted;
|
||||
}
|
||||
|
||||
rethinkAndGo() {
|
||||
return this.rethinkMode() && !this.alreadyRegistered;
|
||||
}
|
||||
|
||||
rethinkAndDontGo() {
|
||||
return this.rethinkMode() && this.alreadyRegistered;
|
||||
}
|
||||
|
||||
unregister() {
|
||||
|
@ -254,14 +266,36 @@ export class EventDetailsComponent implements OnInit {
|
|||
return utilities.showIf(shouldShow);
|
||||
}
|
||||
|
||||
getRegisterBtnText() {
|
||||
let text: string;
|
||||
if (this.event.EventDate) {
|
||||
text = 'I\'m going';
|
||||
} else {
|
||||
text = 'Vote for date';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private _reggedAndNotPast() {
|
||||
return this.event && this.alreadyRegistered && !this.isPastEvent;
|
||||
}
|
||||
|
||||
private _openAndNotComplete() {
|
||||
return this.event && this.event.OpenForRegistration && !this.event.RegistrationCompleted;
|
||||
}
|
||||
|
||||
private _setupActions() {
|
||||
this._actions = [];
|
||||
if (this.rethinkAndGo()) {
|
||||
this._actions.push('I\'m going');
|
||||
}
|
||||
|
||||
if (this.canChangeVote()) {
|
||||
this._actions.push('Change Date Vote');
|
||||
}
|
||||
|
||||
if (this.canUnregister()) {
|
||||
this._actions.push('Unregister');
|
||||
if (this.canUnregister() || this.rethinkAndDontGo()) {
|
||||
this._actions.push('I\'m not going');
|
||||
}
|
||||
|
||||
if (this.canEdit()) {
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
</ActionItem>
|
||||
|
||||
<ActionItem *ngIf="isAndroid" [visibility]="showIf(canChangeVote())" (tap)="changeVote()" text="Change Date Vote" android.position="popup"></ActionItem>
|
||||
<ActionItem *ngIf="isAndroid" [visibility]="showIf(canUnregister())" (tap)="unregister()" text="Unregister" android.position="popup"></ActionItem>
|
||||
<ActionItem *ngIf="isAndroid" [visibility]="showIf(canUnregister() || rethinkAndDontGo())" (tap)="unregister()" text="I'm not going" android.position="popup"></ActionItem>
|
||||
<ActionItem *ngIf="isAndroid" [visibility]="showIf(rethinkAndGo())" (tap)="register()" text="I'm going" android.position="popup"></ActionItem>
|
||||
<ActionItem *ngIf="isAndroid" [visibility]="showIf(canEdit())" (tap)="deleteEvent()" text="Delete Event" android.position="popup"></ActionItem>
|
||||
|
||||
<ActionItem (tap)="toggleActions()" *ngIf="!isAndroid && (canChangeVote() || canUnregister() || canEdit())" ios.position="right">
|
||||
<ActionItem (tap)="toggleActions()" *ngIf="!isAndroid && (canChangeVote() || canUnregister() || canEdit() || rethinkMode())" ios.position="right">
|
||||
<StackLayout>
|
||||
<Label class="button if" text="f"></Label>
|
||||
</StackLayout>
|
||||
|
@ -33,7 +34,7 @@
|
|||
</AbsoluteLayout>
|
||||
|
||||
<StackLayout class="info-container">
|
||||
<Label *ngIf="canRegister()" text="Register" (tap)="register()" class="btn btn-primary"></Label>
|
||||
<Label *ngIf="canRegister()" [text]="getRegisterBtnText()" (tap)="register()" class="btn btn-primary"></Label>
|
||||
|
||||
<StackLayout class="info-wrapper">
|
||||
<GridLayout columns="auto, auto, *" rows="auto, auto">
|
||||
|
@ -45,7 +46,7 @@
|
|||
<Label *ngIf="alreadyRegistered && userVotedForDate(date)" text="h" class="vote yes if"></Label>
|
||||
<Label *ngIf="alreadyRegistered && !userVotedForDate(date)" text="g" class="vote no if"></Label>
|
||||
<Label class="info-value" [text]="date | date:dateFormat"></Label>
|
||||
<Label class="votes-count" *ngIf="countsInitialized()" [text]="getVoteText(date)"></Label>
|
||||
<Label class="votes-count" *ngIf="countsInitialized()" [text]="getVoteText(date)" textWrap="true"></Label>
|
||||
</StackLayout>
|
||||
<Label class="info-value" *ngIf="event.EventDate" [text]="event.EventDate | date:dateFormat"></Label>
|
||||
</StackLayout>
|
||||
|
|
|
@ -81,3 +81,6 @@
|
|||
height: 1;
|
||||
}
|
||||
|
||||
.load-more-btn {
|
||||
font-size: 24;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<ScrollView class="list-events">
|
||||
<StackLayout>
|
||||
<StackLayout *ngFor="let event of events; let isLast = last" (tap)="eventTap(event)">
|
||||
<StackLayout *ngFor="let event of events; let isLast = last; trackBy: event?.Id" (tap)="eventTap(event)">
|
||||
<WrapLayout class="event-name-wrp">
|
||||
<Label [text]="event.Name" textWrap="true" class="event-name"></Label>
|
||||
<Label *ngIf="userIsRegistered(event.Id) && !isPastEvent(event)" class="registered-label" text="Registered"></Label>
|
||||
|
@ -21,5 +21,6 @@
|
|||
|
||||
<Label class="event-list-separator" *ngIf="!isLast" text=""></Label>
|
||||
</StackLayout>
|
||||
<Label *ngIf="hasMore" class="load-more-btn" (tap)="onLoadMore()" text="Load more..."></Label>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
|
|
@ -13,12 +13,20 @@ import { utilities } from '../../shared';
|
|||
styleUrls: ['./events.component.css']
|
||||
})
|
||||
export class EventsComponent implements OnInit {
|
||||
upcomingEvents: Event[];
|
||||
pastEvents: Event[];
|
||||
upcomingEvents: Event[] = [];
|
||||
pastEvents: Event[] = [];
|
||||
userGroups: Group[] = [];
|
||||
initialized: boolean = false;
|
||||
dateFormat: string = utilities.dateFormat;
|
||||
canAdd: boolean = false;
|
||||
hasMoreUpcoming: boolean = true;
|
||||
hasMorePast: boolean = true;
|
||||
|
||||
|
||||
private _upcomingPage = 0;
|
||||
private _pastPage = 0;
|
||||
private _userGroupIds: string[];
|
||||
private readonly _pageSize = 3;
|
||||
|
||||
constructor(
|
||||
private _usersService: UsersService,
|
||||
|
@ -27,7 +35,7 @@ export class EventsComponent implements OnInit {
|
|||
private _routerExtensions: RouterExtensions,
|
||||
private _alertsService: AlertService,
|
||||
private _page: Page
|
||||
) { }
|
||||
) {}
|
||||
|
||||
onAdd() {
|
||||
this._routerExtensions.navigateByUrl('/events/add');
|
||||
|
@ -52,17 +60,13 @@ export class EventsComponent implements OnInit {
|
|||
return Promise.resolve([]);
|
||||
}
|
||||
this.userGroups = userGroups;
|
||||
let userGroupIds = userGroups.map(g => g.Id);
|
||||
let prm1 = this._eventsService.getPast(userGroupIds);
|
||||
let prm2 = this._eventsService.getUpcoming(userGroupIds);
|
||||
this._userGroupIds = userGroups.map(g => g.Id);
|
||||
let pastEventsPrm = this.loadPastEvents();
|
||||
let upcomingEventsPrm = this.loadUpcomingEvents();
|
||||
|
||||
return Promise.all([prm1, prm2]);
|
||||
})
|
||||
.then((events) => {
|
||||
this.pastEvents = events[0] || [];
|
||||
this.upcomingEvents = events[1] || [];
|
||||
this.initialized = true;
|
||||
return Promise.all([pastEventsPrm, upcomingEventsPrm]);
|
||||
})
|
||||
.then((events) => this.initialized = true)
|
||||
.catch(err => this._alertsService.showError(err.message));
|
||||
}
|
||||
|
||||
|
@ -74,6 +78,58 @@ export class EventsComponent implements OnInit {
|
|||
this._routerExtensions.navigate([`/events/${event.Id}`]);
|
||||
}
|
||||
|
||||
private _lockUpcoming: boolean = false;
|
||||
loadUpcomingEvents() {
|
||||
if (!this.hasMoreUpcoming || this._lockUpcoming) {
|
||||
return;
|
||||
}
|
||||
this._lockUpcoming = true;
|
||||
// this.hasMoreUpcoming = false;
|
||||
// console.log(`getting upc page: ${this._upcomingPage}`);
|
||||
return this._eventsService.getUpcoming(this._userGroupIds, this._upcomingPage, this._pageSize)
|
||||
.then(events => {
|
||||
// console.log(`got upc: ${events.length}`);
|
||||
// this.upcomingEvents = this.upcomingEvents.concat(events);
|
||||
this.upcomingEvents = [...this.upcomingEvents, ...events];
|
||||
this.hasMoreUpcoming = !!(events && events.length === this._pageSize);
|
||||
if (this.hasMoreUpcoming) {
|
||||
this._upcomingPage++;
|
||||
}
|
||||
this._lockUpcoming = false;
|
||||
// console.log(`upcpage: ${this._upcomingPage}`);
|
||||
})
|
||||
.catch(err => {
|
||||
this.hasMoreUpcoming = true;
|
||||
this._lockUpcoming = false;
|
||||
console.log(JSON.stringify(err));
|
||||
});
|
||||
}
|
||||
|
||||
private _lockPast: boolean = false;
|
||||
loadPastEvents() {
|
||||
if (!this.hasMorePast || this._lockPast) {
|
||||
return;
|
||||
}
|
||||
this._lockPast = true;
|
||||
// console.log(`getting upc page: ${this._pastPage}`);
|
||||
return this._eventsService.getPast(this._userGroupIds, this._pastPage, this._pageSize)
|
||||
.then(events => {
|
||||
// console.log(`got past: ${events.length}`);
|
||||
this.pastEvents = this.pastEvents.concat(events);
|
||||
// this.pastEvents = [...this.pastEvents, ...events];
|
||||
this.hasMorePast = !!(events && events.length === this._pageSize);
|
||||
if (this.hasMorePast) {
|
||||
this._pastPage++;
|
||||
}
|
||||
this._lockPast = false;
|
||||
// console.log(`pastpage: ${this._pastPage}`);
|
||||
})
|
||||
.catch(err => {
|
||||
this._lockPast = false;
|
||||
console.log(JSON.stringify(err));
|
||||
});
|
||||
}
|
||||
|
||||
goToAllGroups() {
|
||||
this._routerExtensions.navigate(['groups', { selectedTabIndex: 1 }]);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
<TabView *ngIf="initialized && userGroups.length && (upcomingEvents.length || pastEvents.length)" #tabview [selectedIndex]="0" class="tab-view">
|
||||
<StackLayout *tabItem="{ title: 'Upcoming' }" class="main-container">
|
||||
<event-list *ngIf="upcomingEvents.length" [events]="upcomingEvents" (onEventTap)="showDetails($event)"></event-list>
|
||||
<event-list *ngIf="upcomingEvents.length" [events]="upcomingEvents" (onEventTap)="showDetails($event)" [hasMore]="hasMoreUpcoming" (scrolledToBottom)="loadUpcomingEvents()"></event-list>
|
||||
|
||||
<StackLayout *ngIf="!upcomingEvents.length" class="no-items">
|
||||
<Label class="if" text="j"></Label>
|
||||
|
@ -47,7 +47,7 @@
|
|||
</StackLayout>
|
||||
|
||||
<StackLayout *tabItem="{ title: 'Past' }" class="main-container">
|
||||
<event-list *ngIf="pastEvents.length" [events]="pastEvents" (onEventTap)="showDetails($event)"></event-list>
|
||||
<event-list *ngIf="pastEvents.length" [events]="pastEvents" (onEventTap)="showDetails($event)" [hasMore]="hasMorePast" (scrolledToBottom)="loadPastEvents()"></event-list>
|
||||
|
||||
<StackLayout *ngIf="!pastEvents.length" class="no-items">
|
||||
<Label class="if" text="j"></Label>
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
<ScrollView class="ctnr">
|
||||
<ActionBarExtension>
|
||||
<NavigationButton *ngIf="isAndroid" icon="res://icon_back" (tap)="onBack()"></NavigationButton>
|
||||
<ActionItem *ngIf="!isAndroid" ios.systemIcon="1" ios.position="left" (tap)="onBack()"></ActionItem>
|
||||
<ActionItem *ngIf="!isAndroid" ios.systemIcon="1" ios.position="left" (tap)="onBack()">
|
||||
<label text="Back"></label>
|
||||
</ActionItem>
|
||||
<ActionItem (tap)="onEdit()" *ngIf="canEdit()" ios.position="right">
|
||||
<StackLayout>
|
||||
<Label class="button if" text="e"></Label>
|
||||
|
|
|
@ -52,3 +52,7 @@
|
|||
font-size: 28;
|
||||
color: rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
.load-more-btn {
|
||||
font-size: 24;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { RouterExtensions } from 'nativescript-angular/router';
|
||||
import { ScrollView } from 'ui/scroll-view';
|
||||
// import { RadListView } from 'nativescript-telerik-ui/listview';
|
||||
|
||||
import { GroupsService, UsersService, AlertService, EventsService } from '../../services';
|
||||
import { Group, User } from '../../shared/models';
|
||||
|
@ -13,8 +15,10 @@ import { utilities } from '../../shared';
|
|||
})
|
||||
export class GroupListComponent implements OnInit {
|
||||
@Input() groups: Group[];
|
||||
@Output() onGroupTap: EventEmitter<Group> = new EventEmitter<Group>();
|
||||
@Input() hasMore: boolean = true;
|
||||
@Input() areUserGroups: boolean;
|
||||
@Output() onGroupTap: EventEmitter<Group> = new EventEmitter<Group>();
|
||||
@Output() scrolledToBottom: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
groupInfoById: any = {};
|
||||
initialized = false;
|
||||
|
@ -66,6 +70,10 @@ export class GroupListComponent implements OnInit {
|
|||
return (count || 'No') + postfix;
|
||||
}
|
||||
|
||||
onLoadMore() {
|
||||
this.scrolledToBottom.emit();
|
||||
}
|
||||
|
||||
private _getUserCountByGroup() {
|
||||
return this._usersService.currentUser()
|
||||
.then(u => this._groupsService.getUserCountByGroup(u.Id))
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
<StackLayout *ngIf="groups && initialized">
|
||||
<StackLayout *ngFor="let group of groups; let isLast = last" (tap)="groupTap(group)">
|
||||
<GridLayout columns="65, *, auto" rows="auto, auto" class="group">
|
||||
<StackLayout rowSpan="2" row="0" col="0">
|
||||
<photo-picker class="group-image" [url]="group.ImageUrl" [type]="'group'" [small]="true" [noImageIcon]="'w'"></photo-picker>
|
||||
</StackLayout>
|
||||
<ScrollView>
|
||||
<StackLayout *ngIf="groups && initialized">
|
||||
<StackLayout *ngFor="let group of groups; let isLast = last" (tap)="groupTap(group)">
|
||||
<GridLayout columns="65, *, auto" rows="auto, auto" class="group">
|
||||
<StackLayout rowSpan="2" row="0" col="0">
|
||||
<photo-picker class="group-image" [url]="group.ImageUrl" [type]="'group'" [small]="true" [noImageIcon]="'w'"></photo-picker>
|
||||
</StackLayout>
|
||||
|
||||
<Label row="0" col="1" [text]="group.Name" class="group-name" textWrap="true"></Label>
|
||||
<Label row="1" col="1" [text]="getSubtext(group)" class="group-subtext" textWrap="true"></Label>
|
||||
<Label row="0" col="1" [text]="group.Name" class="group-name" textWrap="true"></Label>
|
||||
<Label row="1" col="1" [text]="getSubtext(group)" class="group-subtext" textWrap="true"></Label>
|
||||
|
||||
<Label *ngIf="!areUserGroups" rowSpan="2" row="0" col="2" [text]="getJoinBtnText(group)" (tap)="onJoin(group)" class="join-btn"></Label>
|
||||
</GridLayout>
|
||||
<Label class="group-list-separator" text=""></Label>
|
||||
<Label *ngIf="!areUserGroups" rowSpan="2" row="0" col="2" [text]="getJoinBtnText(group)" (tap)="onJoin(group)" class="join-btn"></Label>
|
||||
</GridLayout>
|
||||
<Label class="group-list-separator" text=""></Label>
|
||||
</StackLayout>
|
||||
<Label *ngIf="hasMore" class="load-more-btn" (tap)="onLoadMore()" text="Load more..."></Label>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
|
|
@ -13,12 +13,18 @@ import { Group } from '../../shared/models';
|
|||
styleUrls: ['./groups.component.css']
|
||||
})
|
||||
export class GroupsComponent implements OnInit {
|
||||
publicGroups: Group[];
|
||||
userGroups: Group[];
|
||||
@ViewChild("groupsTabView") groupsTabView: ElementRef;
|
||||
|
||||
publicGroups: Group[] = [];
|
||||
userGroups: Group[] = [];
|
||||
initialized: boolean = false;
|
||||
selectedIndex: number = 0;
|
||||
|
||||
@ViewChild("groupsTabView") groupsTabView: ElementRef;
|
||||
hasMoreUnjoined: boolean = true;
|
||||
hasMoreUserGroups: boolean = true;
|
||||
private _userId: string;
|
||||
private _pageSize = 5;
|
||||
private _unjoinedPage = 0;
|
||||
private _userGroupsPage = 0;
|
||||
|
||||
constructor(
|
||||
private _page: Page,
|
||||
|
@ -33,23 +39,19 @@ export class GroupsComponent implements OnInit {
|
|||
this._page.actionBar.title = 'Groups';
|
||||
this._route.params.subscribe(p => {
|
||||
if ('selectedTabIndex' in p) {
|
||||
let index = Number(p['selectedTabIndex']);
|
||||
// ngIf on the tab view makes it impossible to toggle it with goToTab()
|
||||
// but setting this.selectedIndex doesnt switch tabs after this initial time
|
||||
// so we use a mix of both...
|
||||
this.selectedIndex = index;
|
||||
this.goToTab(Number(p['selectedTabIndex']));
|
||||
}
|
||||
});
|
||||
|
||||
this._usersService.currentUser()
|
||||
.then(u => {
|
||||
let unjoinedGroupsPromise = this._groupsService.getUnjoinedGroups(u.Id)
|
||||
.then(res => this.publicGroups = res);
|
||||
let userGroupsPromise = this._groupsService.getUserGroups(u.Id)
|
||||
.then(res => this.userGroups = res);
|
||||
this._userId = u.Id;
|
||||
let unjoinedGroupsPromise = this.loadMoresUnjoinedGroups();
|
||||
let userGroupsPromise = this.loadMoresUserGroups();
|
||||
return Promise.all([unjoinedGroupsPromise, userGroupsPromise]);
|
||||
})
|
||||
.then(r => this.initialized = true);
|
||||
.then(r => this.initialized = true)
|
||||
.catch(err => err && this._alertService.showError(err.message));
|
||||
}
|
||||
|
||||
selectGroup(group: Group) {
|
||||
|
@ -61,6 +63,40 @@ export class GroupsComponent implements OnInit {
|
|||
}
|
||||
|
||||
goToTab(tabIndex: number) {
|
||||
this.groupsTabView.nativeElement.selectedIndex = tabIndex;
|
||||
this.selectedIndex = tabIndex;
|
||||
}
|
||||
|
||||
loadMoresUserGroups() {
|
||||
this.hasMoreUserGroups = false;
|
||||
console.log(`usr page: ${this._userGroupsPage}`);
|
||||
return this._groupsService.getUserGroups(this._userId, this._userGroupsPage, this._pageSize)
|
||||
.then(groups => {
|
||||
this.userGroups = this.userGroups.concat(groups);
|
||||
this.hasMoreUserGroups = this._hasMore(groups.length, this._pageSize);
|
||||
if (this.hasMoreUserGroups) {
|
||||
this._userGroupsPage++;
|
||||
}
|
||||
console.log(`loaded usr: ${groups.length}`);
|
||||
})
|
||||
.catch(err => this.hasMoreUserGroups = true);
|
||||
}
|
||||
|
||||
loadMoresUnjoinedGroups() {
|
||||
this.hasMoreUnjoined = false;
|
||||
console.log(`unj page: ${this._unjoinedPage}`);
|
||||
return this._groupsService.getUnjoinedGroups(this._userId, this._unjoinedPage, this._pageSize)
|
||||
.then(groups => {
|
||||
this.publicGroups = this.publicGroups.concat(groups);
|
||||
this.hasMoreUnjoined = this._hasMore(groups.length, this._pageSize);
|
||||
if (this.hasMoreUnjoined) {
|
||||
this._unjoinedPage++;
|
||||
}
|
||||
console.log(`loaded unj: ${groups.length}`);
|
||||
})
|
||||
.catch(err => this.hasMoreUnjoined = true);
|
||||
}
|
||||
|
||||
private _hasMore(receivedCount: number, pageSize: number) {
|
||||
return receivedCount === pageSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
</StackLayout>
|
||||
</StackLayout>
|
||||
|
||||
<TabView #groupsTabView *ngIf="initialized && (userGroups.length || publicGroups.length)" [selectedIndex]="selectedIndex" class="tab-view">
|
||||
<ScrollView *tabItem="{ title: 'My Groups' }" class="tab-item">
|
||||
<TabView #groupsTabView *ngIf="initialized && (userGroups.length || publicGroups.length)" [(ngModel)]="selectedIndex" class="tab-view">
|
||||
<StackLayout *tabItem="{ title: 'My Groups' }" class="tab-item">
|
||||
|
||||
<StackLayout class="tab-items-wrapper" [ngClass]="{ 'no-groups': !userGroups.length }">
|
||||
<group-list *ngIf="userGroups.length" [groups]="userGroups" [areUserGroups]="true" (onGroupTap)="selectGroup($event)"></group-list>
|
||||
<group-list *ngIf="userGroups.length" [groups]="userGroups" [areUserGroups]="true" [hasMore]="hasMoreUserGroups" (onGroupTap)="selectGroup($event)" (scrolledToBottom)="loadMoresUserGroups()"></group-list>
|
||||
<StackLayout *ngIf="!userGroups.length" class="no-items">
|
||||
<Label class="if" text="n"></Label>
|
||||
<Label text="It's time to join a group!" [textWrap]="true" class="title"></Label>
|
||||
|
@ -33,10 +34,10 @@
|
|||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<ScrollView *tabItem="{ title: 'All Groups' }" class="tab-item">
|
||||
</StackLayout>
|
||||
<StackLayout *tabItem="{ title: 'All Groups' }" class="tab-item">
|
||||
<StackLayout class="tab-items-wrapper" [ngClass]="{ 'no-groups': !publicGroups.length }">
|
||||
<group-list *ngIf="publicGroups.length" [groups]="publicGroups" (onGroupTap)="selectGroup($event)"></group-list>
|
||||
<group-list *ngIf="publicGroups.length" [groups]="publicGroups" [hasMore]="hasMoreUnjoined" (onGroupTap)="selectGroup($event)" (scrolledToBottom)="loadMoresUnjoinedGroups()"></group-list>
|
||||
<StackLayout *ngIf="!publicGroups.length" class="no-items">
|
||||
<Label class="if" text="n"></Label>
|
||||
<Label text="No groups yet" [textWrap]="true" class="title"></Label>
|
||||
|
@ -48,7 +49,7 @@
|
|||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</StackLayout>
|
||||
</TabView>
|
||||
|
||||
<ScrollView class="cntnr">
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
.registered-label {
|
||||
padding: 8 20 0 15;
|
||||
}
|
||||
|
||||
.btn-wrp {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.switch {
|
||||
margin: 14 16 14 0;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.switch[checked=true] {
|
||||
background-color: #F4550F;
|
||||
color: #F4550F;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
.registered-label {
|
||||
padding: 0 20 0 15;
|
||||
}
|
||||
|
||||
.btn-wrp {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.switch[checked=true] {
|
||||
background-color: #F4550F;
|
||||
}
|
||||
|
|
|
@ -22,12 +22,14 @@ export class EventsService {
|
|||
ReturnAs: 'Organizer',
|
||||
Expand: {
|
||||
Image: {
|
||||
TargetTypeName: 'System.Files',
|
||||
ReturnAs: 'ImageUrl',
|
||||
SingleField: 'Uri'
|
||||
}
|
||||
}
|
||||
},
|
||||
Image: {
|
||||
TargetTypeName: 'System.Files',
|
||||
ReturnAs: 'ImageUrl',
|
||||
SingleField: 'Uri'
|
||||
}
|
||||
|
@ -57,6 +59,7 @@ export class EventsService {
|
|||
ReturnAs: 'Event',
|
||||
Expand: {
|
||||
Image: {
|
||||
TargetTypeName: 'System.Files',
|
||||
ReturnAs: 'ImageUrl',
|
||||
SingleField: 'Uri'
|
||||
},
|
||||
|
@ -65,6 +68,7 @@ export class EventsService {
|
|||
ReturnAs: 'Organizer',
|
||||
Expand: {
|
||||
Image: {
|
||||
TargetTypeName: 'System.Files',
|
||||
ReturnAs: 'ImageUrl',
|
||||
SingleField: 'Uri'
|
||||
}
|
||||
|
@ -111,11 +115,11 @@ export class EventsService {
|
|||
});
|
||||
}
|
||||
|
||||
getUpcoming(groupIds: string[]) {
|
||||
getUpcoming(groupIds: string[], page = 0, pageSize = 5) {
|
||||
return this._usersService.currentUser()
|
||||
.then(user => {
|
||||
let filter = this._getUpcomingFilter(groupIds, user.Id);
|
||||
return this._getWithFilter(filter);
|
||||
return this._getWithFilter(filter, true, null, page, pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -128,7 +132,7 @@ export class EventsService {
|
|||
return this._data.aggregate(query).then((r: any) => r.result);
|
||||
}
|
||||
|
||||
getPast(userGroupIds: string[]) {
|
||||
getPast(userGroupIds: string[], page = 0, pageSize = 5) {
|
||||
if (!userGroupIds.length) {
|
||||
return Promise.reject({ message: 'No group ids specified' });
|
||||
}
|
||||
|
@ -138,7 +142,7 @@ export class EventsService {
|
|||
GroupId: { $in: userGroupIds }
|
||||
};
|
||||
return this._usersService.currentUser()
|
||||
.then(u => this._getWithFilter(filter, true, { field: 'EventDate', desc: true }));
|
||||
.then(u => this._getWithFilter(filter, true, { field: 'EventDate', desc: true }, page, pageSize));
|
||||
}
|
||||
|
||||
getParticipants(eventId: string) {
|
||||
|
@ -220,7 +224,7 @@ export class EventsService {
|
|||
delete event.ImageUrl;
|
||||
}
|
||||
|
||||
private _getWithFilter(filter: any, expand: any = true, sorting?: { field: string, desc?: boolean }|Array<{ field: string, desc?: boolean }>) {
|
||||
private _getWithFilter(filter: any, expand: any = true, sorting?: { field: string, desc?: boolean }|Array<{ field: string, desc?: boolean }>, page = 0, pageSize = 5) {
|
||||
let query = this._elProvider.getNewQuery();
|
||||
query.where(filter);
|
||||
|
||||
|
@ -230,6 +234,8 @@ export class EventsService {
|
|||
let sortFunc = sortType.desc ? query.orderDesc : query.order;
|
||||
sortFunc.call(query, sortType.field);
|
||||
});
|
||||
query.skip(page * pageSize);
|
||||
query.take(pageSize);
|
||||
|
||||
if (expand === true) {
|
||||
query.expand(this._eventExpandExpression);
|
||||
|
|
|
@ -53,42 +53,23 @@ export class GroupsService {
|
|||
return this._groupsData.getById(id).then(r => r.result);
|
||||
}
|
||||
|
||||
getAllVisible(userId: string) {
|
||||
let filter = {
|
||||
$or: [
|
||||
{ IsPublic: true },
|
||||
{ Owner: userId }
|
||||
]
|
||||
};
|
||||
let userGroups: Group[];
|
||||
return this.getUserGroups(userId)
|
||||
.then(joinedGroups => {
|
||||
userGroups = joinedGroups;
|
||||
return this._getGroupsByFilter(filter);
|
||||
})
|
||||
.then(publicAndOwnedGroups => {
|
||||
return this._mergeGroups(publicAndOwnedGroups, userGroups);
|
||||
});
|
||||
}
|
||||
|
||||
getPublicGroups() {
|
||||
let filter = { IsPublic: true };
|
||||
return this._getGroupsByFilter(filter);
|
||||
}
|
||||
|
||||
getUnjoinedGroups(userId: string) {
|
||||
return this._membershipsData.get({ UserId: userId })
|
||||
.then(memberships => {
|
||||
let ids = memberships.result.map(m => m.GroupId);
|
||||
let filter = {
|
||||
$and: [
|
||||
{ Id: { $nin: ids } },
|
||||
{ $or: [ { IsPublic: true }, { Owner: userId } ] }
|
||||
]
|
||||
};
|
||||
return this._getGroupsByFilter(filter);
|
||||
});
|
||||
}
|
||||
// getAllVisible(userId: string) {
|
||||
// let filter = {
|
||||
// $or: [
|
||||
// { IsPublic: true },
|
||||
// { Owner: userId }
|
||||
// ]
|
||||
// };
|
||||
// let userGroups: Group[];
|
||||
// return this.getUserGroups(userId)
|
||||
// .then(joinedGroups => {
|
||||
// userGroups = joinedGroups;
|
||||
// return this._getGroupsByFilter(filter);
|
||||
// })
|
||||
// .then(publicAndOwnedGroups => {
|
||||
// return this._mergeGroups(publicAndOwnedGroups, userGroups);
|
||||
// });
|
||||
// }
|
||||
|
||||
getUserCountByGroup(userId: string): Promise<{GroupId: string, UserId: number}[]> {
|
||||
return this.getUnjoinedGroups(userId)
|
||||
|
@ -99,12 +80,26 @@ export class GroupsService {
|
|||
})
|
||||
.then((res: any) => res.result);
|
||||
}
|
||||
|
||||
getUnjoinedGroups(userId: string, page = 0, pageSize = 5) {
|
||||
return this._membershipsData.get({ UserId: userId })
|
||||
.then(memberships => {
|
||||
let ids = memberships.result.map(m => m.GroupId);
|
||||
let filter = {
|
||||
$and: [
|
||||
{ Id: { $nin: ids } },
|
||||
{ $or: [ { IsPublic: true }, { Owner: userId } ] }
|
||||
]
|
||||
};
|
||||
return this._getGroupsByFilter(filter, null, page, pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
getUserGroups(userId: string) {
|
||||
getUserGroups(userId: string, page = 0, pageSize = 5) {
|
||||
return this._membershipsData.get({ UserId: userId })
|
||||
.then(resp => {
|
||||
let userGroupsIds = resp.result.map(reg => reg.GroupId);
|
||||
return this._getGroupsByFilter({ Id: { $in: userGroupsIds }});
|
||||
return this._getGroupsByFilter({ Id: { $in: userGroupsIds }}, null, page, pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -206,10 +201,12 @@ export class GroupsService {
|
|||
return joinedGroups;
|
||||
}
|
||||
|
||||
private _getGroupsByFilter(filter: any, sorting?: { field: string, desc?: boolean }|{ field: string, desc?: boolean }[]) {
|
||||
private _getGroupsByFilter(filter: any, sorting?: { field: string, desc?: boolean }|{ field: string, desc?: boolean }[], page = 0, pageSize = 5) {
|
||||
let query = this._elProvider.getNewQuery();
|
||||
query.where(filter);
|
||||
query.expand(this._imageExpandExp);
|
||||
query.skip(page * pageSize);
|
||||
query.take(pageSize);
|
||||
|
||||
sorting = sorting || [{ field: 'Name' }];
|
||||
sorting = [].concat(sorting);
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
margin-top: 25;
|
||||
}
|
||||
|
||||
.btn-wrp {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
margin-bottom: 20;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
.cntnr {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20;
|
||||
vertical-align: center;
|
||||
background-color: #fff;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<StackLayout class="cntnr">
|
||||
<!-- TODO: use app-modal -->
|
||||
<StackLayout>
|
||||
<DatePicker #datePicker [(ngModel)]="date" (loaded)="configureDatePicker(datePicker)"></DatePicker>
|
||||
<TimePicker #timePicker></TimePicker>
|
||||
</StackLayout>
|
||||
<ScrollView>
|
||||
<StackLayout class="cntnr">
|
||||
<!-- TODO: use app-modal -->
|
||||
<StackLayout>
|
||||
<DatePicker #datePicker [(ngModel)]="date" (loaded)="configureDatePicker(datePicker)"></DatePicker>
|
||||
<TimePicker #timePicker></TimePicker>
|
||||
</StackLayout>
|
||||
|
||||
<StackLayout class="btn-wrp">
|
||||
<Label (tap)="onSelect(datePicker, timePicker)" class="btn btn-primary" text="Add Option"></Label>
|
||||
<StackLayout class="btn-wrp">
|
||||
<Label (tap)="onSelect(datePicker, timePicker)" class="btn btn-primary" text="Add Option"></Label>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { Component, Input, OnInit, Output, EventEmitter, ViewChild } from '@angular/core';
|
||||
import * as nsImgSource from 'image-source';
|
||||
import * as nsImage from 'ui/image';
|
||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
|
||||
import { ImagePickerService } from '../../services';
|
||||
import { utilities, constants } from '../';
|
||||
import { utilities } from '../';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
@ -11,8 +9,8 @@ import { utilities, constants } from '../';
|
|||
templateUrl: './photo-picker.template.html',
|
||||
styleUrls: [ './photo-picker.component.css' ]
|
||||
})
|
||||
export class PhotoPickerComponent implements OnInit {
|
||||
resizedUrl: string;
|
||||
export class PhotoPickerComponent {
|
||||
private _resizedUrl: string;
|
||||
|
||||
@Input('url') rawUrl: string;
|
||||
@Input() type: string;
|
||||
|
@ -27,12 +25,19 @@ export class PhotoPickerComponent implements OnInit {
|
|||
private _imgPickerService: ImagePickerService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
get resizedUrl() {
|
||||
if (!this.rawUrl) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
this.resizedUrl = this._resizeAccordingly(this.rawUrl, this.type);
|
||||
if (!this._resizedUrl) {
|
||||
this._resizedUrl = this._resizeAccordingly(this.rawUrl, this.type);
|
||||
}
|
||||
return this._resizedUrl;
|
||||
}
|
||||
|
||||
set resizedUrl(newValue: string) {
|
||||
this._resizedUrl = newValue;
|
||||
}
|
||||
|
||||
onEdit(event) {
|
||||
|
|
|
@ -9,12 +9,20 @@ import { User } from '../models';
|
|||
styleUrls: [ './user-display.component.css' ]
|
||||
})
|
||||
export class UserDisplayComponent implements OnInit {
|
||||
@Input() users: User[] = [];
|
||||
private _users: User[] = [];
|
||||
|
||||
@Input('withImages') imgCount: number = null;
|
||||
@Input() showNames: boolean = false;
|
||||
|
||||
@Input() set users(newValue: User[]) {
|
||||
this._users = [].concat(newValue);
|
||||
}
|
||||
|
||||
get users() {
|
||||
return this._users;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.users = [].concat(this.users);
|
||||
if (typeof this.imgCount !== 'number') {
|
||||
this.imgCount = this.users.length;
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ function getNotificationObject (alertType, context) {
|
|||
break;
|
||||
|
||||
|
||||
default:
|
||||
default: // TODO: remove this, it's for testing purposes only
|
||||
title = 'New Message!';
|
||||
message = 'Well, we dont know what it is... :|';
|
||||
break;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"@angular/router": "3.4.6",
|
||||
"everlive-sdk": "1.9.1",
|
||||
"nativescript-angular": "1.4.0",
|
||||
"nativescript-imagepicker": "^2.4.1",
|
||||
"nativescript-imagepicker": "2.5.0",
|
||||
"nativescript-permissions": "^1.2.0",
|
||||
"nativescript-push-notifications": "0.1.2",
|
||||
"nativescript-telerik-ui": "next",
|
||||
|
@ -66,6 +66,8 @@
|
|||
"prebuild-android-bundle": "npm run webpack-android",
|
||||
"prebuild-ios-bundle": "npm run webpack-ios",
|
||||
"build-android-bundle": "tns build android --bundle --disable-npm-install",
|
||||
"build-ios-bundle": "tns build ios --bundle --disable-npm-install"
|
||||
"build-ios-bundle": "tns build ios --bundle --disable-npm-install",
|
||||
"typescript": "~2.1.6",
|
||||
"zone.js": "~0.7.2"
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче