Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Welcome sequence after verifying email for the first time #24

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ import { UserComponent } from './user/user.component';
import { MessagesWithUserComponent } from './messages-with-user/messages-with-user.component';
import { MapComponent } from './map/map.component';

// welcome
import { WelcomeComponent } from './welcome/welcome.component';
import { WelcomeStartComponent } from './welcome/welcome-start/welcome-start.component';
import { WelcomeTagsComponent } from './welcome/welcome-tags/welcome-tags.component';
import { WelcomeInfoComponent } from './welcome/welcome-info/welcome-info.component';
import { WelcomeLocationComponent } from './welcome/welcome-location/welcome-location.component';
import { WelcomeFinishComponent } from './welcome/welcome-finish/welcome-finish.component';

// user edit
import { UserEditComponent } from './user-edit/user-edit.component';
import { UserEditProfileComponent } from './user-edit/user-edit-profile/user-edit-profile.component';
Expand Down Expand Up @@ -75,7 +83,12 @@ import { TagResolver } from './tag/tag-resolver.service';
import { ContactResolver } from './contact/contact-resolver.service';
import { ThreadsResolver } from './messages/threads-resolver.service';
import { MessagesResolver } from './messages-with-user/messages-resolver.service';
import { TagsRelatedToMyTagsResolver, RandomTagsResolver, TagsRelatedToTagResolver } from './tags/tags-resolver.service';
import {
PopularTagsResolver,
TagsRelatedToMyTagsResolver,
RandomTagsResolver,
TagsRelatedToTagResolver
} from './tags/tags-resolver.service';
import { PeopleWithMyTagsResolver, NewPeopleResolver, PeopleWithTagResolver } from './people/people-resolver.service';

// services
Expand Down Expand Up @@ -353,6 +366,40 @@ const routes: Routes = [
user: LoggedUserResolver
}
},
{
path: 'welcome',
component: WelcomeComponent,
canActivate: [AuthGuard],
resolve: {
user: LoggedUserResolver
},
children: [
{
path: '',
component: WelcomeStartComponent
},
{
path: '1',
component: WelcomeTagsComponent,
resolve: {
userTags: LoggedUserTagsResolver,
popularTags: PopularTagsResolver
}
},
{
path: '2',
component: WelcomeInfoComponent
},
{
path: '3',
component: WelcomeLocationComponent
},
{
path: 'done',
component: WelcomeFinishComponent
}
]
},
{
path: '**',
component: FofComponent
Expand Down Expand Up @@ -389,6 +436,7 @@ const routeWrapper: Routes = [
TagsRelatedToMyTagsResolver,
TagsRelatedToTagResolver,
RandomTagsResolver,
PopularTagsResolver,
PeopleWithMyTagsResolver,
PeopleWithTagResolver,
NewPeopleResolver,
Expand Down
16 changes: 15 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ import { CommentsComponent } from './comments/comments.component';
import { CommentComponent } from './comments/comment/comment.component';
import { CommentFormComponent } from './comments/comment-form/comment-form.component';
import { TagRelatedIdeasComponent } from './tag/tag-related-ideas/tag-related-ideas.component';
import { WelcomeComponent } from './welcome/welcome.component';
import { WelcomeStartComponent } from './welcome/welcome-start/welcome-start.component';
import { WelcomeTagsComponent } from './welcome/welcome-tags/welcome-tags.component';
import { WelcomeInfoComponent } from './welcome/welcome-info/welcome-info.component';
import { WelcomeLocationComponent } from './welcome/welcome-location/welcome-location.component';
import { WelcomeFinishComponent } from './welcome/welcome-finish/welcome-finish.component';
import { WelcomeNavigationComponent } from './welcome/welcome-navigation/welcome-navigation.component';

@NgModule({
declarations: [
Expand Down Expand Up @@ -197,7 +204,14 @@ import { TagRelatedIdeasComponent } from './tag/tag-related-ideas/tag-related-id
CommentsComponent,
CommentComponent,
CommentFormComponent,
TagRelatedIdeasComponent
TagRelatedIdeasComponent,
WelcomeComponent,
WelcomeStartComponent,
WelcomeTagsComponent,
WelcomeInfoComponent,
WelcomeLocationComponent,
WelcomeFinishComponent,
WelcomeNavigationComponent
],
imports: [
BrowserModule,
Expand Down
1 change: 1 addition & 0 deletions src/app/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
* Reloading avatar image
*/
this.updateAvatarSubscription = this.headerControl.updateAvatar$.subscribe(() => {
if (!this.display) { return; }
this.avatar.reload();
});
}
Expand Down
29 changes: 27 additions & 2 deletions src/app/model.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ describe('ModelService', () => {

req.flush({ meta: {
email: '[email protected]',
token: 'aaaa.bbbb.cccc'
token: 'aaaa.bbbb.cccc',
isNewUser: false
} });
const response = await verifyEmailPromise;
expect(response).toEqual({ email: '[email protected]', token: 'aaaa.bbbb.cccc' });
expect(response).toEqual({ email: '[email protected]', token: 'aaaa.bbbb.cccc', isNewUser: false });
}));

});
Expand Down Expand Up @@ -156,6 +157,30 @@ describe('ModelService', () => {
}));
});

describe('findPopularTags(limit = 10)', () => {
it('should success', async(async () => {
const findPopularTagsPromise = service.findPopularTags(4);

const req = httpMock.expectOne(`${baseUrl}/tags?sort=-popularityByUses&page[offset]=0&page[limit]=4`);

expect(req.request.method).toEqual('GET');
expect(req.request.headers.get('content-type')).toEqual('application/vnd.api+json');
expect(req.request.headers.has('authorization')).toEqual(true);

req.flush({
data: [
{ type: 'tags', id: 'tag3', attributes: { popularityByUses: 25 } },
{ type: 'tags', id: 'tag4', attributes: { popularityByUses: 12 } },
{ type: 'tags', id: 'tag6', attributes: { popularityByUses: 11 } },
{ type: 'tags', id: 'tag0', attributes: { popularityByUses: 7 } }
]
});

const response = await findPopularTagsPromise;
expect(response.length).toEqual(4);
}));
});

describe('findNewUsers()', () => {

it('should success', async(async () => {
Expand Down
27 changes: 23 additions & 4 deletions src/app/model.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class ModelService {
});
}

async verifyEmail(username: string, code: string): Promise<{ email: string, token: string }> {
async verifyEmail(username: string, code: string): Promise<{ email: string, token: string, isNewUser: boolean }> {

const body = {
data: {
Expand All @@ -103,8 +103,8 @@ export class ModelService {
.patch(`${this.baseUrl}/account`, body, { headers: this.notLoggedHeaders })
.toPromise();

const { email, token } = response.meta;
return { email, token };
const { email, token, isNewUser } = response.meta;
return { email, token, isNewUser };
} catch (e) {
throw { status: e.status, message: 'todo error' };
}
Expand Down Expand Up @@ -519,6 +519,19 @@ export class ModelService {
return tags;
}

public async findPopularTags(limit = 10): Promise<Tag[]> {
const headers = this.loggedHeaders;

const response: any = await this.http
.get(`${this.baseUrl}/tags?sort=-popularityByUses&page[offset]=0&page[limit]=${limit}`, { headers })
.toPromise();

const { data } = response;

const tags: Tag[] = data.map(tag => this.deserializeTag(tag));
return tags;
}

public async readMessagesWith(username: string): Promise<Message[]> {
const headers = this.loggedHeaders;

Expand Down Expand Up @@ -1070,7 +1083,13 @@ export class ModelService {
}

private deserializeTag(tagData: any): Tag {
return { tagname: tagData.id };
const tag: Tag = { tagname: tagData.id };

if (tagData.attributes && tagData.attributes.hasOwnProperty('popularityByUses')) {
tag.popularityByUses = tagData.attributes.popularityByUses;
}

return tag;
}

private deserializeUserTag(rawUserTag: any, included: any[]): UserTag {
Expand Down
5 changes: 3 additions & 2 deletions src/app/shared/select-location/select-location.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<button [disabled]="disabled"
(click)="updateLocation()">Update My Location</button>
<div class="edit-location-container">
<button [disabled]="disabled"
class="save-button"
(click)="updateLocation()">Update My Location</button>
<div #locationContainer class="edit-location-map"></div>
<div class="edit-location-overlay"></div>
</div>
7 changes: 7 additions & 0 deletions src/app/shared/select-location/select-location.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@
background-repeat: no-repeat;
z-index: 1000;
}

.save-button {
position: absolute;
z-index: 999; // above map but below header menu
top: 16px;
right: 16px;
}
12 changes: 10 additions & 2 deletions src/app/shared/tag-list/tag-list.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
<ul>
<ul *ngIf="!linksDisabled">
<li *ngFor="let tag of tags"
[routerLink]="'/tag/' + tag.tagname">{{tag.tagname}}</li>
[routerLink]="'/tag/' + tag.tagname">{{tag.tagname}}
<span class="tag-popularity" *ngIf="tag.popularityByUses">{{tag.popularityByUses}}&times;</span>
</li>
</ul>

<ul *ngIf="linksDisabled">
<li *ngFor="let tag of tags" class="link-disabled">{{tag.tagname}}
<span class="tag-popularity" *ngIf="tag.popularityByUses">{{tag.popularityByUses}}&times;</span>
</li>
</ul>
8 changes: 8 additions & 0 deletions src/app/shared/tag-list/tag-list.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ li {
cursor: pointer;
background-color: $accent;
color: white;

&.link-disabled {
cursor: auto;
}
}

.tag-popularity {
font-size: small;
}
2 changes: 2 additions & 0 deletions src/app/shared/tag-list/tag-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export class TagListComponent implements OnInit {

@Input() tags: Tag[] = [];

@Input() linksDisabled = false;

constructor() { }

ngOnInit() {
Expand Down
1 change: 1 addition & 0 deletions src/app/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class User {

export class Tag {
constructor(public tagname: string,
public popularityByUses?: number,
public created?: number) {

// TODO fix the creator
Expand Down
36 changes: 35 additions & 1 deletion src/app/tags/tags-resolver.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { TestBed, inject } from '@angular/core/testing';

import { TagsRelatedToMyTagsResolver, RandomTagsResolver, TagsRelatedToTagResolver } from './tags-resolver.service';
import {
PopularTagsResolver,
TagsRelatedToMyTagsResolver,
RandomTagsResolver,
TagsRelatedToTagResolver } from './tags-resolver.service';

import { ModelService } from '../model.service';

Expand All @@ -22,6 +26,14 @@ class ModelStubService {
];
}

public async findPopularTags(): Promise<Tag[]> {
return [
{ tagname: 'tag1', popularityByUses: 21 },
{ tagname: 'tag0', popularityByUses: 12 },
{ tagname: 'tag2', popularityByUses: 2 }
];
}

public async findTagsByTags(tagsIn: Tag[]): Promise<Tag[]> {

// the tags to choose from
Expand Down Expand Up @@ -86,6 +98,28 @@ describe('RandomTagsResolver', () => {
}));
});

describe('PopularTagsResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
PopularTagsResolver,
{ provide: ModelService, useClass: ModelStubService }
],
});
});

it('should be created', inject([PopularTagsResolver], (service: PopularTagsResolver) => {
expect(service).toBeTruthy();
}));

it('should resolve with some tags', inject([PopularTagsResolver], async (service: PopularTagsResolver) => {
expect(service).toBeTruthy();
const tags = await service.resolve();

expect(tags.length).toEqual(3);
}));
});

describe('TagsRelatedToTagResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
10 changes: 10 additions & 0 deletions src/app/tags/tags-resolver.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ export class TagsRelatedToMyTagsResolver implements Resolve<Tag[]> {
}
}

@Injectable()
export class PopularTagsResolver implements Resolve<Tag[]> {

constructor(private model: ModelService) { }

async resolve(): Promise<Tag[]> {
return await this.model.findPopularTags();
}
}

@Injectable()
export class RandomTagsResolver implements Resolve<Tag[]> {

Expand Down
Loading