...
 
Commits (5)
import generateRandomId from "../../support/utilities";
context('Onboarding', () => {
const remindText = 'remind test text';
const username = generateRandomId();
const password = `${generateRandomId()}0oA!`;
const email = 'test@minds.com';
const usernameField = 'minds-form-register #username';
const emailField = 'minds-form-register #email';
const passwordField = 'minds-form-register #password';
const password2Field = 'minds-form-register #password2';
const checkbox = '[data-cy=data-minds-accept-tos-input]';
const submitButton = 'minds-form-register .mdl-card__actions button';
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
cy.visit('/register');
cy.location('pathname').should('eq', '/register');
cy.server();
cy.route("POST", "**/api/v1/register").as("register");
cy.get(usernameField)
.focus()
.type(username);
cy.get(emailField)
.focus()
.type(email);
cy.get(passwordField)
.focus()
.type(password);
cy.wait(500);
cy.get(password2Field)
.focus()
.type(password);
cy.get(checkbox)
.click({ force: true });
//submit
cy.get(submitButton)
.click()
.wait('@register')
.then((xhr) => {
expect(xhr.status).to.equal(200);
}
});
cy.visit(`/onboarding`);
);
cy.wait(500);
cy.location('pathname').should('eq', '/onboarding/notice');
});
// create two test groups
after(() => {
cy.deleteUser(username, password);
cy.clearCookies();
});
beforeEach(() => {
......@@ -21,7 +65,7 @@ context('Onboarding', () => {
it('should go through the process of onboarding', () => {
// notice should appear
cy.get('h1.m-onboarding__noticeTitle').contains('Welcome to the Minds Community');
cy.get('h2.m-onboarding__noticeTitle').contains(`@${Cypress.env().username}`);
cy.get('h2.m-onboarding__noticeTitle').contains(username);
// should redirect to /hashtags
cy.get('.m-onboarding__form button.mf-button').contains("Let's Get Setup").click();
......@@ -73,8 +117,8 @@ context('Onboarding', () => {
// should have a Location input
cy.get('.m-onboarding__controls > .m-onboarding__control label[data-minds=location]').contains('Location');
cy.get('.m-onboarding__controls > .m-onboarding__control input[data-minds=locationInput]').type('London');
cy.get('ul.m-onboarding__cities > li:first-child').click();
// cy.get('.m-onboarding__controls > .m-onboarding__control input[data-minds=locationInput]').type('London');
// cy.get('ul.m-onboarding__cities > li:first-child').click();
// should have Date of Birth inputs
......@@ -91,7 +135,11 @@ context('Onboarding', () => {
// should have a continue and a skip button
cy.get('button.mf-button--hollow').contains('Skip');
cy.get('button.mf-button--alt').contains('Continue').click();
cy.get('button.mf-button--alt').contains('Finish').click();
// TODO: disable the following line and uncomment the rest when we re-enable the screens
// should be in the newsfeed
cy.location('pathname').should('eq', '/newsfeed/subscriptions');
// should be in the Groups step
......@@ -105,8 +153,8 @@ context('Onboarding', () => {
// cy.get('.m-groupList__list .m-groupList__item:first-child .m-join__subscribe i').contains('add');
// should have a continue and a skip button
cy.get('button.mf-button--hollow').contains('Skip');
cy.get('button.mf-button--alt').contains('Continue').click();
// cy.get('button.mf-button--hollow').contains('Skip');
// cy.get('button.mf-button--alt').contains('Continue').click();
// should be in the Channels step
......@@ -120,10 +168,10 @@ context('Onboarding', () => {
// cy.get('.m-channelList__list .m-channelList__item:first-child .m-join__subscribe i').contains('add');
// should have a continue and a skip button
cy.get('button.mf-button--hollow').contains('Skip');
cy.get('button.mf-button--alt').contains('Finish').click();
// cy.get('button.mf-button--hollow').contains('Skip');
// cy.get('button.mf-button--alt').contains('Finish').click();
// should be in the newsfeed
cy.location('pathname').should('eq', '/newsfeed/subscriptions');
// cy.location('pathname').should('eq', '/newsfeed/subscriptions');
});
});
......@@ -60,7 +60,7 @@ context('Registration', () => {
});
cy.wait(500);
cy.location('pathname').should('eq', '/newsfeed/subscriptions');
cy.location('pathname').should('eq', '/onboarding/notice');
});
it('should display an error if passwords do not match', () => {
......
......@@ -2,27 +2,32 @@ m-date__dropdowns {
display: flex;
justify-content: space-between;
select {
display: inline-block;
background-color: #fff;
box-sizing: border-box;
margin: 0 10px 0 0;
padding: 8px 10px;
height: 36px;
.m-dateDropdowns__selectWrapper {
position: relative;
overflow: hidden;
min-width: 80px;
max-width: 90px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
font-size: 16px;
line-height: 21px;
border-radius: 2px;
border-radius: 3px;
margin: 0 10px 0 0;
@include m-theme() {
color: themed($m-grey-800);
background-color: themed($m-white);
border: 1px solid #e2e2e2;
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.1);
}
&::after {
content: '\25bc';
font-size: 10px;
padding: 10px;
position: absolute;
right: 0;
top: 0;
text-align: center;
pointer-events: none;
@include m-theme() {
color: themed($m-grey-200);
}
}
// month
......@@ -40,4 +45,28 @@ m-date__dropdowns {
min-width: 77px;
}
}
select {
display: inline-block;
background-color: #fff;
box-sizing: border-box;
padding: 8px 10px;
height: 36px;
width: 100%;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
font-size: 16px;
line-height: 21px;
border-radius: 2px;
appearance: none;
@include m-theme() {
color: themed($m-grey-800);
background-color: themed($m-white);
border: 1px solid #e2e2e2;
}
}
}
......@@ -3,27 +3,33 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core';
@Component({
selector: 'm-date__dropdowns',
template: `
<select
data-minds="monthDropdown"
[ngModel]="selectedMonth"
(ngModelChange)="selectMonth($event)"
>
<option *ngFor="let month of monthNames">{{ month }}</option>
</select>
<select
data-minds="dayDropdown"
[ngModel]="selectedDay"
(ngModelChange)="selectDay($event)"
>
<option *ngFor="let day of days">{{ day }}</option>
</select>
<select
data-minds="yearDropdown"
[ngModel]="selectedYear"
(ngModelChange)="selectYear($event)"
>
<option *ngFor="let year of years">{{ year }}</option>
</select>
<div class="m-dateDropdowns__selectWrapper">
<select
data-minds="monthDropdown"
[ngModel]="selectedMonth"
(ngModelChange)="selectMonth($event)"
>
<option *ngFor="let month of monthNames">{{ month }}</option>
</select>
</div>
<div class="m-dateDropdowns__selectWrapper">
<select
data-minds="dayDropdown"
[ngModel]="selectedDay"
(ngModelChange)="selectDay($event)"
>
<option *ngFor="let day of days">{{ day }}</option>
</select>
</div>
<div class="m-dateDropdowns__selectWrapper">
<select
data-minds="yearDropdown"
[ngModel]="selectedYear"
(ngModelChange)="selectYear($event)"
>
<option *ngFor="let year of years">{{ year }}</option>
</select>
</div>
`,
})
export class DateDropdownsComponent implements OnInit {
......@@ -56,30 +62,42 @@ export class DateDropdownsComponent implements OnInit {
ngOnInit() {
this.years = this.range(100, this.selectedYear, false);
this.selectedYear = this.years[0];
this.selectMonth('January');
this.selectMonth('January', false);
}
selectMonth(month: string) {
selectMonth(month: string, emit: boolean = true) {
this.selectedMonth = month;
this.populateDays(
this.getDaysInMonth(this.getMonthNumber(month), this.selectedYear)
);
this.selectedDateChange.emit(this.buildDate());
if (emit) {
this.emitChanges();
}
}
selectDay(day: string) {
selectDay(day: string, emit: boolean = true) {
this.selectedDay = day;
this.selectedDateChange.emit(this.buildDate());
if (emit) {
this.emitChanges();
}
}
selectYear(year) {
selectYear(year, emit: boolean = true) {
this.selectedYear = year;
this.populateDays(
this.getDaysInMonth(this.getMonthNumber(this.selectedMonth), year)
);
if (emit) {
this.emitChanges();
}
}
emitChanges() {
this.selectedDateChange.emit(this.buildDate());
}
......
......@@ -135,16 +135,12 @@
justify-content: space-between;
width: 100%;
height: 52px;
max-width: 1296px;
max-width: 1084px;
margin: 0 auto;
padding: 0 8px;
padding: 15px 0 15px;
//padding-right: 46px;
box-sizing: border-box;
@media screen and (min-width: 1296px) {
padding: 0 46px 0 0;
}
@media screen and (max-width: 480px) {
.m-v2-topbarNav__RouterNav {
display: none;
......@@ -297,6 +293,7 @@
}
> a {
margin-right: 40px;
text-decoration: none;
height: 32px;
border-radius: 18px;
......
......@@ -4,6 +4,8 @@ import {
ViewChild,
ChangeDetectorRef,
HostListener,
OnInit,
OnDestroy,
Inject,
PLATFORM_ID,
} from '@angular/core';
......@@ -20,7 +22,7 @@ import { GroupsService } from '../groups-service';
selector: 'm-group--sidebar-markers',
templateUrl: 'sidebar-markers.component.html',
})
export class GroupsSidebarMarkersComponent {
export class GroupsSidebarMarkersComponent implements OnInit, OnDestroy {
inProgress: boolean = false;
$updateMarker;
markers = [];
......@@ -58,6 +60,10 @@ export class GroupsSidebarMarkersComponent {
return;
}
if (update.show) {
// if the group already exists in the list, don't re-add it
if (this.groups.findIndex(g => g.guid == update.guid) !== -1) {
return;
}
this.groupsService.load(update.guid).then(group => {
this.groups.unshift(group);
});
......
......@@ -383,6 +383,7 @@ m-onboarding {
line-height: 21px;
padding-left: 8px;
margin-bottom: 8px;
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.1);
@include m-theme() {
color: themed($m-grey-800);
......@@ -405,6 +406,7 @@ m-onboarding {
flex-grow: 1;
display: flex;
margin-bottom: 8px;
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.1);
.m-phone-input--wrapper {
justify-content: flex-start;
......@@ -421,6 +423,7 @@ m-onboarding {
font-size: 16px;
line-height: 21px;
box-shadow: none;
@include m-theme() {
color: themed($m-grey-800);
......
......@@ -21,14 +21,14 @@ export class OnboardingComponent implements OnDestroy {
name: 'Info',
selected: false,
},
{
name: 'Groups',
selected: false,
},
{
name: 'Channels',
selected: false,
},
// {
// name: 'Groups',
// selected: false,
// },
// {
// name: 'Channels',
// selected: false,
// },
];
showTitle: boolean = false;
shown: boolean = false;
......
......@@ -9,6 +9,6 @@ export class ChannelsStepComponent {
constructor(private router: Router) {}
finish() {
this.router.navigate(['/newsfeed']);
this.router.navigate(['/newsfeed/global/top']);
}
}
......@@ -4,6 +4,8 @@ m-onboarding__channelList {
.m-onboarding__channelList {
display: flex;
position: relative;
h3 {
margin: 0;
font-size: 13px;
......@@ -33,6 +35,8 @@ m-onboarding__channelList {
padding: 0;
list-style: none;
width: 100%;
max-height: 245px;
overflow-y: auto;
}
.m-channelList__item {
......@@ -43,6 +47,27 @@ m-onboarding__channelList {
border-bottom: 0;
}
&:nth-child(4) {
& ~ :last-child {
position: relative;
z-index: 1;
}
& ~ :nth-last-child(2):after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
to bottom,
rgba(255, 255, 255, 0) 0%,
#fff 100%
);
height: 65px;
}
}
a {
display: flex;
text-decoration: none;
......
......@@ -61,7 +61,7 @@ export class ChannelListComponent implements OnInit {
query,
nsfw,
})
.setLimit(3)
.setLimit(12)
.setExportUserCounts(true)
.fetch();
} catch (e) {
......
......@@ -4,6 +4,8 @@ m-onboarding__groupList {
.m-onboarding__groupList {
display: flex;
position: relative;
h3 {
margin: 0;
font-size: 13px;
......@@ -33,6 +35,8 @@ m-onboarding__groupList {
padding: 0;
list-style: none;
width: 100%;
max-height: 245px;
overflow-y: auto;
}
.m-groupList__item {
......@@ -43,6 +47,27 @@ m-onboarding__groupList {
border-bottom: 0;
}
&:nth-child(4) {
& ~ :last-child {
position: relative;
z-index: 1;
}
& ~ :nth-last-child(2):after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
to bottom,
rgba(255, 255, 255, 0) 0%,
#fff 100%
);
height: 65px;
}
}
a {
display: flex;
flex-grow: 1;
......
......@@ -61,7 +61,7 @@ export class GroupListComponent implements OnInit {
query,
nsfw,
})
.setLimit(3)
.setLimit(12)
.setCastToActivities(true)
.fetch();
} catch (e) {
......
import { Component, OnInit } from '@angular/core';
import { TopbarHashtagsService } from '../../../hashtags/service/topbar.service';
import { Router } from '@angular/router';
import { Storage } from '../../../../services/storage';
type Hashtag = {
value: string;
......@@ -16,9 +17,14 @@ export class HashtagsStepComponent implements OnInit {
error: string;
inProgress: boolean;
constructor(private service: TopbarHashtagsService, private router: Router) {}
constructor(
private service: TopbarHashtagsService,
private storage: Storage,
private router: Router
) {}
ngOnInit() {
this.storage.set('preferred_hashtag_state', '1'); // turn on preferred hashtags for discovery
this.load();
}
......
......@@ -70,7 +70,7 @@
Skip
</button>
<button class="mf-button mf-button--alt" (click)="continue()" i18n>
Continue
Finish
</button>
</div>
</div>
......@@ -24,6 +24,7 @@ export class InfoStepComponent {
locationError: string;
date: string;
dateOfBirthError: string;
dateOfBirthChanged: boolean = false;
cities: Array<any> = [];
......@@ -86,6 +87,9 @@ export class InfoStepComponent {
}
async updateDateOfBirth() {
if (!this.dateOfBirthChanged) {
return true;
}
this.dateOfBirthError = null;
try {
......@@ -102,6 +106,7 @@ export class InfoStepComponent {
selectedDateChange(date: string) {
this.date = date;
this.dateOfBirthChanged = true;
}
cancel() {
......@@ -112,12 +117,12 @@ export class InfoStepComponent {
}
skip() {
this.router.navigate(['/onboarding', 'groups']);
this.router.navigate(['/newsfeed']);
}
continue() {
if (this.saveData()) {
this.router.navigate(['/onboarding', 'groups']);
this.router.navigate(['/newsfeed']);
}
}
......
......@@ -28,7 +28,7 @@ export class NoticeStepComponent implements OnInit {
}
skip() {
this.router.navigate(['/newsfeed']);
this.router.navigate(['/newsfeed/global/top']);
}
isMobile() {
......