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:
Georgi Prodanov 2017-02-21 12:45:02 +02:00
Родитель cb9febce15 3d8a35bfca
Коммит efe385e76d
31 изменённых файлов: 326 добавлений и 163 удалений

Двоичные данные
app/App_Resources/Android/drawable-hdpi/icon_overflow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 565 B

Двоичные данные
app/App_Resources/Android/drawable-mdpi/icon_overflow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 427 B

Двоичные данные
app/App_Resources/Android/drawable-xhdpi/icon_overflow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 917 B

Двоичные данные
app/App_Resources/Android/drawable-xxhdpi/icon_overflow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
app/App_Resources/Android/drawable-xxxhdpi/icon_overflow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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>

Просмотреть файл

@ -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="&#x66;"></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="&#x68;" class="vote yes if"></Label>
<Label *ngIf="alreadyRegistered && !userVotedForDate(date)" text="&#x67;" 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="&#x6a;"></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="&#x6a;"></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="&#x65;"></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]="'&#x77;'"></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]="'&#x77;'"></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="&#x6e;"></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="&#x6e;"></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"
}
}