...
 
Commits (6)
<ng-container *ngIf="ready">
<ng-container *ngIf="!isProDomain">
<ng-container *ngIf="useNewNavigation; else v2Topbar">
<m-v3topbar>
<ng-container search>
<m-search--bar [defaultSizes]="false"></m-search--bar>
</ng-container>
</m-v3topbar>
</ng-container>
<ng-template #v2Topbar>
<m-v2-topbar>
<ng-container search>
<m-search--bar [defaultSizes]="false"></m-search--bar>
</ng-container>
<ng-container icons>
<m-notifications--topbar-toggle
*ngIf="session.isLoggedIn()"
></m-notifications--topbar-toggle>
</ng-container>
</m-v2-topbar>
<m-sidebar--markers
[class.has-v2-navbar]="featuresService.has('top-feeds')"
></m-sidebar--markers>
</ng-template>
</ng-container>
<m-body
[class.has-markers-sidebar]="hasMarkersSidebar()"
[class.has-v2-navbar]="featuresService.has('top-feeds')"
[class.has-v3-navbar]="featuresService.has('navigation-2020')"
[class.is-pro-domain]="isProDomain"
>
<m-emailConfirmation *ngIf="!isProDomain"></m-emailConfirmation>
<m-announcement [id]="'festival:sale'" *mIfFeature="'radiocity'">
<span
class="m-blockchain--wallet-address-notice--action"
i18n="@@MINDS_FESTIVAL_TICKET_SALE"
>
BREAKING: Tickets on sale for "MINDS: FESTIVAL OF IDEAS" @ Radio City on
6/13/2020. HELP US SELL OUT FAST!
</span>
</m-announcement>
<m-blockchain--wallet-address-notice></m-blockchain--wallet-address-notice>
<ng-container *ngIf="useNewNavigation; else oldLayout">
<div class="m-grid">
<m-sidebar--navigation></m-sidebar--navigation>
<router-outlet></router-outlet>
</div>
</ng-container>
<ng-template #oldLayout>
<router-outlet></router-outlet>
</ng-template>
</m-body>
<ng-container *mIfBrowser>
<m-messenger *ngIf="session.isLoggedIn() && !isProDomain"></m-messenger>
</ng-container>
<m-hovercard-popup></m-hovercard-popup>
<m-overlay-modal></m-overlay-modal>
<m--blockchain--transaction-overlay></m--blockchain--transaction-overlay>
<m-modal--tos-updated *ngIf="session.isLoggedIn()"></m-modal--tos-updated>
<ng-container *mIfBrowser>
<m-juryDutySession__summons
*ngIf="session.isLoggedIn() && !isProDomain"
></m-juryDutySession__summons>
<m-topbarwrapper></m-topbarwrapper>
</ng-container>
<m-modal-signup
*ngIf="!isProDomain && !session.getLoggedInUser()"
[open]="false"
></m-modal-signup>
<m-channel--onboarding *ngIf="showOnboarding"></m-channel--onboarding>
<m-cookies-notice *ngIf="!session.isLoggedIn()"></m-cookies-notice>
<m-page></m-page>
</ng-container>
......@@ -35,7 +35,7 @@ m-app {
grid-template-areas: 'nav content side' 'footer footer footer';
grid-template-columns: 3fr 5fr 4fr;
grid-template-rows: auto 1fr auto;
grid-template-rows: 1fr;
grid-gap: 0;
height: 100%;
......
......@@ -44,12 +44,8 @@ export class Minds implements OnInit, OnDestroy {
ready: boolean = false;
showOnboarding: boolean = false;
showTOSModal: boolean = false;
useNewNavigation: boolean = false;
protected router$: Subscription;
protected routerConfig: Route[];
......@@ -66,7 +62,6 @@ export class Minds implements OnInit, OnDestroy {
public web3Wallet: Web3WalletService,
public client: Client,
public webtorrent: WebtorrentService,
public onboardingService: ChannelOnboardingService,
public router: Router,
public blockListService: BlockListService,
public featuresService: FeaturesService,
......@@ -90,7 +85,6 @@ export class Minds implements OnInit, OnDestroy {
}
async ngOnInit() {
this.useNewNavigation = this.featuresService.has('navigation-2020');
// MH: does loading meta tags before the configs have been set cause issues?
this.router$ = this.router.events
.pipe(
......@@ -142,10 +136,6 @@ export class Minds implements OnInit, OnDestroy {
this.session.isLoggedIn(async is => {
if (is && !this.site.isProDomain) {
if (!this.site.isProDomain) {
this.showOnboarding = await this.onboardingService.showModal();
}
const user = this.session.getLoggedInUser();
const language = this.configs.get('language');
......@@ -156,14 +146,6 @@ export class Minds implements OnInit, OnDestroy {
}
});
this.onboardingService.onClose.subscribe(() => {
this.showOnboarding = false;
});
this.onboardingService.onOpen.subscribe(async () => {
this.showOnboarding = await this.onboardingService.showModal(true);
});
this.loginReferrer
.avoid([
'/login',
......@@ -187,14 +169,6 @@ export class Minds implements OnInit, OnDestroy {
this.socketsService.setUp();
}
hasMarkersSidebar() {
return (
this.session.isLoggedIn() &&
!this.isProDomain &&
!this.featuresService.has('navigation-2020')
);
}
ngOnDestroy() {
this.loginReferrer.unlisten();
this.scrollToTop.unlisten();
......
......@@ -81,6 +81,8 @@ import { CookieModule } from '@gorniv/ngx-universal';
import { HomepageModule } from './modules/homepage/homepage.module';
import { OnboardingV2Module } from './modules/onboarding-v2/onboarding.module';
import { ConfigsService } from './common/services/configs.service';
import { TopbarWrapperComponent } from './page/topbar.component';
import { PageComponent } from './page/page.component';
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
......@@ -96,6 +98,8 @@ export class SentryErrorHandler implements ErrorHandler {
bootstrap: [Minds],
declarations: [
Minds,
TopbarWrapperComponent,
PageComponent,
MINDS_APP_ROUTING_DECLARATIONS,
MINDS_DECLARATIONS,
MINDS_PLUGIN_DECLARATIONS,
......
......@@ -165,5 +165,7 @@
</ul>
</nav>
<ng-template dynamic-host></ng-template>
<div class="m-sidebar--groups" *ngIf="session.isLoggedIn()">
<ng-template dynamic-host></ng-template>
</div>
</div>
......@@ -145,16 +145,7 @@ m-sidebar--navigation {
}
i.material-icons {
//font-size:17px;
//line-height:44px;
margin-right: 30px;
}
span {
//text-transform: uppercase;
//font-size: 8px;
//letter-spacing: 1.25px;
//padding-top: 4px;
}
}
}
......@@ -14,7 +14,7 @@ export class TopbarService {
}
constructor(private featuresService: FeaturesService) {
this.useV3Topbar = this.featuresService.has('navigation-2020');
this.useV3Topbar = this.featuresService.has('navigation');
}
setContainer(container: V2TopbarComponent | V3TopbarComponent) {
......
@import 'defaults';
minds-admin {
grid-area: content / span 2;
min-width: 0;
}
minds-admin-boosts {
minds-button-comment {
display: none !important;
......
......@@ -2,6 +2,9 @@
m-analytics {
display: block;
grid-area: content / span 2;
min-width: 0;
@include m-theme() {
background-color: themed($m-white);
}
......
......@@ -70,7 +70,7 @@ export class LoginComponent implements OnInit, OnDestroy {
}
this.newDesign = this.featuresService.has('register_pages-december-2019');
this.newNavigation = this.featuresService.has('navigation-2020');
this.newNavigation = this.featuresService.has('navigation');
if (this.newDesign) {
this.topbarService.toggleVisibility(false);
......
......@@ -32,7 +32,7 @@
</span>
</div>
<ng-container *mIfFeature="'navigation-2020'; else v1Channel">
<ng-container *mIfFeature="'navigation'; else v1Channel">
<div class="m-channel__middleColumn">
feed goes here
</div>
......
......@@ -16,8 +16,9 @@ m-channel {
.m-channel__rightColumn {
grid-area: side;
//padding-left: 59px;
//padding-right: 33.3%;
padding-left: 56px;
padding-right: 33%;
margin-top: 25px;
min-width: 0;
}
......
......@@ -130,7 +130,7 @@ describe('ChannelComponent', () => {
featuresServiceMock.mock('es-feeds', false);
featuresServiceMock.mock('top-feeds', false);
featuresServiceMock.mock('channel-filter-feeds', false);
featuresServiceMock.mock('navigation-2020', false);
featuresServiceMock.mock('navigation', false);
comp = fixture.componentInstance;
comp.username = 'username';
......
......@@ -29,6 +29,8 @@ import { ChannelSortedComponent } from './sorted/sorted.component';
import { ChannelSortedModuleComponent } from './sorted/module.component';
import { ReferralsModule } from '../wallet/tokens/referrals/referrals.module';
import { ChannelSidebarV2Component } from './sidebar-v2/sidebar-v2.component';
import { ChannelStatsComponent } from './sidebar-v2/stats/channel-stats.component';
import { ChannelBiofieldsComponent } from './sidebar-v2/biofields/biofields.component';
const routes: Routes = [
{ path: 'channels', redirectTo: '/newsfeed/global/top', pathMatch: 'full' },
......@@ -64,6 +66,8 @@ const routes: Routes = [
ExplicitOverlayComponent,
ChannelSortedComponent,
ChannelSortedModuleComponent,
ChannelStatsComponent,
ChannelBiofieldsComponent,
],
exports: [
ChannelModulesComponent,
......
<div class="m-channelBiofields">
<!-- [ngClass]="{'m-channelBiofields&#45;&#45;flex': !editing}"-->
<!-- City / Location -->
<div
class="m-channelBiofields__field m-channelBiofields__city"
[hidden]="editing || !user.city"
>
<i class="material-icons">location_on</i>
<span>{{ user.city }}</span>
</div>
<div class="m-channelBiofields__editor" *ngIf="editing && isOwner()">
<div class="m-channelBiofields__cityInput">
<i class="material-icons">location_on</i>
<input
(keyup)="findCity(user.city)"
name="city"
[(ngModel)]="user.city"
class=""
placeholder="Enter your city..."
i18n-placeholder="@@M__COMMON__ENTER_CITY"
/>
</div>
<div
class="m-channelBiofields__cityAutocomplete"
*ngIf="editing && cities.length > 0"
>
<p i18n="@@M__COMMON__SELECT_CITY">
Select your city:
</p>
<li
(click)="setCity(c)"
*ngFor="let c of cities"
[hidden]="!(c.address.town || c.address.city)"
>
{{ c.address.town }}{{ c.address.city }}, {{ c.address.state }}
</li>
</div>
</div>
<!-- END City / Location -->
<!-- <div-->
<!-- class="m-channelBiofields__field"-->
<!-- *ngIf="user.tags && !editing"-->
<!-- >-->
<!-- <div-->
<!-- class="m-channelBiofields__field__tags-container"-->
<!-- [hidden]="editing || !user.tags"-->
<!-- >-->
<!-- <i class="material-icons">local_offer</i>-->
<!-- <span *ngFor="let tag of user.tags">#{{tag}}</span>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div-->
<!-- class="m-channel-bio-editor m-channel-city-editor"-->
<!-- *ngIf="editing && isOwner()"-->
<!-- >-->
<!-- <div class="m-channel-bio-input">-->
<!-- <i class="material-icons">local_offer</i>-->
<!-- <m-hashtags-selector-->
<!-- #hashtagsSelector-->
<!-- [alignLeft]="true"-->
<!-- [tags]="user.tags"-->
<!-- (tagsChange)="onTagsChange($event)"-->
<!-- (tagsAdded)="onTagsAdded($event)"-->
<!-- (tagsRemoved)="onTagsRemoved($event)"-->
<!-- >-->
<!-- </m-hashtags-selector>-->
<!-- </div>-->
<!-- <div-->
<!-- class="mdl-card mdl-shadow&#45;&#45;2dp"-->
<!-- style="min-height:0;"-->
<!-- *ngIf="errorMessage"-->
<!-- >-->
<!-- <div class="mdl-card__supporting-text">-->
<!-- {{errorMessage}}-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <m-channel&#45;&#45;social-profiles-->
<!-- [user]="user"-->
<!-- [editing]="editing && isOwner()"-->
<!-- (changed)="setSocialProfile($event)"-->
<!-- ></m-channel&#45;&#45;social-profiles>-->
</div>
<div class="m-channelSidebar__briefDescription">
<span [innerHtml]="user.briefdescription | tags" [hidden]="editing"> </span>
<div *ngIf="editing && isOwner()">
<!-- OWNER EDIT FORM -->
<textarea
[autoGrow]
class="mdl-textfield__input"
type="text"
name="briefdescription"
[(ngModel)]="user.briefdescription"
></textarea>
</div>
</div>
m-channelbiofields {
.m-channelBiofields {
margin: 7px 0;
//&.m-channelBiofields--flex {
// display: flex;
// flex-flow: row wrap;
// align-items: center;
// margin: auto;
// justify-content: center;
//}
.m-channelBiofields__field {
@include m-theme() {
color: themed($m-black);
}
}
.m-channelBiofields__city {
i.material-icons {
font-size: 22px;
line-height: 30px;
vertical-align: middle;
margin-right: 10px;
}
span {
font-size: 14px;
line-height: 30px;
}
}
.m-channelBiofields__editor {
}
.m-channelBiofields__cityInput {
display: flex;
input {
border: 0;
padding: 0 8px;
}
}
.m-channelBiofields__cityAutocomplete {
}
}
.m-channelSidebar__briefDescription {
margin: 7px 0;
span {
white-space: pre-line;
text-align: center;
}
textarea {
box-sizing: border-box;
padding: 8px;
text-align: left;
width: 100%;
border: 0 !important;
}
}
}
import { Component, Input, OnInit } from '@angular/core';
import { MindsUser } from '../../../../interfaces/entities';
import { Session } from '../../../../services/session';
import { Tag } from '../../../hashtags/types/tag';
import { Client } from '../../../../services/api/client';
@Component({
selector: 'm-channelbiofields',
templateUrl: 'biofields.component.html',
})
export class ChannelBiofieldsComponent implements OnInit {
@Input() user: MindsUser;
@Input() editing: boolean;
searching;
amountOfTags: number = 0;
tooManyTags: boolean = false;
errorMessage: string = '';
// @todo make a re-usable city selection module to avoid duplication here
cities: Array<any> = [];
constructor(public session: Session, public client: Client) {}
ngOnInit() {}
isOwner() {
return this.session.getLoggedInUser().guid === this.user.guid;
}
findCity(q: string) {
if (this.searching) {
clearTimeout(this.searching);
}
this.searching = setTimeout(() => {
this.client
.get('api/v1/geolocation/list', { q: q })
.then((response: any) => {
this.cities = response.results;
});
}, 100);
}
setCity(row: any) {
this.cities = [];
if (row.address.city) {
this.user.city = row.address.city;
}
if (row.address.town) {
this.user.city = row.address.town;
}
if (window.Minds) {
window.Minds.user.city = this.user.city;
}
this.client.post('api/v1/channel/info', {
coordinates: row.lat + ',' + row.lon,
city: window.Minds.user.city,
});
}
onTagsChange(tags: string[]) {
this.amountOfTags = tags.length;
if (this.amountOfTags > 5) {
this.errorMessage = 'You can only select up to 5 hashtags';
this.tooManyTags = true;
} else {
this.tooManyTags = false;
this.user.tags = tags;
if (this.errorMessage === 'You can only select up to 5 hashtags') {
this.errorMessage = '';
}
}
}
onTagsAdded(tags: Tag[]) {}
onTagsRemoved(tags: Tag[]) {}
setSocialProfile(value: any) {
this.user.social_profiles = value;
}
}
<div class="m-channelSidebar__buttons">
<button class="m-channelSidebar__message" i18n>
<i class="material-icons">sentiment_satisfied_alt</i>
<button class="m-channelSidebar__messageButton" i18n>
<img [src]="cdnAssetsUrl + 'assets/icons/wire.svg'" />
<span>Message</span>
</button>
<button class="m-channelSidebar__pay" i18n>
<i class="material-icons">sentiment_satisfied_alt</i>
<button class="m-channelSidebar__payButton" i18n>
<img [src]="cdnAssetsUrl + 'assets/icons/wire.svg'" />
<span>Pay</span>
</button>
</div>
<div class="m-channelSidebar__stats">
<!-- <a-->
<!-- [routerLink]="['/', user.username, 'feed']"-->
<!-- class="mdl-tabs__tab mdl-color-text&#45;&#45;blue-grey-500"-->
<!-- *ngIf="user.activity_count"-->
<!-- >-->
<!-- <span i18n="Count of activities@@M__COMMON__FEED_COUNT">Feed</span>-->
<!-- <b>{{user.activity_count | number}}</b>-->
<!-- </a>-->
<a
*ngIf="user.supporters_count && session.getLoggedInUser().guid != user.guid"
>
<span class="m-channelSidebarStats__title" i18n>
Followers
</span>
<span class="m-channelSidebarStats__count">{{
user.supporters_count | abbr
}}</span>
</a>
<a
[routerLink]="['/', user.username, 'supporters']"
*ngIf="user.supporters_count && session.getLoggedInUser().guid == user.guid"
>
<span class="m-channelSidebarStats__title" i18n>
Followers
</span>
<span class="m-channelSidebarStats__count">{{
user.supporters_count | abbr
}}</span>
</a>
<a [routerLink]="['/', user.username, 'subscribers']">
<span class="m-channelSidebarStats__title" i18n>
Following
</span>
<span class="m-channelSidebarStats__count">{{
user.subscribers_count | abbr
}}</span>
</a>
<a>
<span class="m-channelSidebarStats__title" i18n>
Views
</span>
<span class="m-channelSidebarStats__count">{{
user.impressions | abbr
}}</span>
</a>
</div>
<m-channelstats [user]="user"></m-channelstats>
<div class="m-channelSidebar__bioFields">
<!-- [ngClass]="{'m-channelSidebar__bioFields&#45;&#45;flex': !editing}"-->
<!-- City / Location -->
<div
class="m-channelSidebar__bioField m-channelSidebar__city"
[hidden]="editing || !user.city"
>
<i class="material-icons">location_on</i>
<span>{{ user.city }}</span>
</div>
<m-channelbiofields [user]="user" [editing]="editing"></m-channelbiofields>
<div
class="m-channel-bio-editor m-channel-city-editor"
*ngIf="editing && isOwner()"
>
<div class="m-channel-bio-input m-channel-city-input">
<i class="material-icons">location_on</i>
<input
(keyup)="findCity(user.city)"
name="city"
[(ngModel)]="user.city"
class=""
placeholder="Enter your city..."
i18n-placeholder="@@M__COMMON__ENTER_CITY"
/>
</div>
<div
class="m-discovery-cities mdl-card m-border"
*ngIf="editing && cities.length > 0"
>
<p i18n="@@M__COMMON__SELECT_CITY">
Select your city:
</p>
<li
(click)="setCity(c)"
*ngFor="let c of cities"
[hidden]="!(c.address.town || c.address.city)"
>
{{ c.address.town }}{{ c.address.city }}, {{ c.address.state }}
</li>
</div>
</div>
<!-- END City / Location -->
<m-channels--sorted-module
title="Images"
i18n-title
type="images"
[channel]="user"
[linksTo]="['/', user.username, 'images']"
[size]="8"
*mIfBrowser
></m-channels--sorted-module>
<!-- <div-->
<!-- class="m-channelSidebar__bioField"-->
<!-- *ngIf="user.tags && !editing"-->
<!-- >-->
<!-- <div-->
<!-- class="m-channelSidebar__bioField__tags-container"-->
<!-- [hidden]="editing || !user.tags"-->
<!-- >-->
<!-- <i class="material-icons">local_offer</i>-->
<!-- <span *ngFor="let tag of user.tags">#{{tag}}</span>-->
<!-- </div>-->
<!-- </div>-->
<m-channels--sorted-module
title="Videos"
i18n-title
type="videos"
[channel]="user"
[linksTo]="['/', user.username, 'videos']"
[size]="8"
*mIfBrowser
></m-channels--sorted-module>
<!-- <div-->
<!-- class="m-channel-bio-editor m-channel-city-editor"-->
<!-- *ngIf="editing && isOwner()"-->
<!-- >-->
<!-- <div class="m-channel-bio-input">-->
<!-- <i class="material-icons">local_offer</i>-->
<!-- <m-hashtags-selector-->
<!-- #hashtagsSelector-->
<!-- [alignLeft]="true"-->
<!-- [tags]="user.tags"-->
<!-- (tagsChange)="onTagsChange($event)"-->
<!-- (tagsAdded)="onTagsAdded($event)"-->
<!-- (tagsRemoved)="onTagsRemoved($event)"-->
<!-- >-->
<!-- </m-hashtags-selector>-->
<!-- </div>-->
<!-- <div-->
<!-- class="mdl-card mdl-shadow&#45;&#45;2dp"-->
<!-- style="min-height:0;"-->
<!-- *ngIf="errorMessage"-->
<!-- >-->
<!-- <div class="mdl-card__supporting-text">-->
<!-- {{errorMessage}}-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<button (click)="changeEditing.emit(true)">toggle editing</button>
<!-- <m-channel&#45;&#45;social-profiles-->
<!-- [user]="user"-->
<!-- [editing]="editing && isOwner()"-->
<!-- (changed)="setSocialProfile($event)"-->
<!-- ></m-channel&#45;&#45;social-profiles>-->
</div>
<m-wire-channel
*mIfBrowser
#wire
[(rewards)]="user.wire_rewards"
[channel]="user"
[editing]="editing"
[channelV2Design]="true"
></m-wire-channel>
m-channel__sidebarv2 {
.m-channelSidebar__buttons {
display: flex;
margin: 7px 0;
button:first-child {
margin-right: 47px;
......@@ -15,64 +16,77 @@ m-channel__sidebarv2 {
@include m-theme() {
color: themed($m-black);
}
img {
height: 14px;
margin-right: 8px;
}
}
}
.m-channelSidebar__stats {
display: flex;
align-items: center;
justify-content: space-between;
a {
text-decoration: none;
display: flex;
flex-direction: column;
height: 60px;
m-channels--sorted-module {
background-color: transparent !important;
border: 0 !important;
margin: 7px 0;
max-width: 245px;
@include m-theme() {
color: themed($m-black);
}
.m-channels--sorted-module__Title {
padding: 0;
span {
.mdl-card__title-text {
font-size: 14px;
line-height: 30px;
font-weight: bold;
margin-bottom: 9px;
}
}
&.m-channelSidebarStats__title {
font-size: 13px;
}
.m-channels--sorted-module__Tiles {
> a {
height: 45px;
width: 45px;
flex-grow: 0;
flex-shrink: 0;
padding: 0;
margin-right: 15px;
margin-bottom: 15px;
box-sizing: content-box;
&.m-channelSidebarStats__count {
font-size: 18px;
&.m-mature-module-thumbnail {
i.material-icons {
font-size: 2em !important;
}
}
}
}
}
.m-channelSidebar__bioFields {
//&.m-channelSidebar__bioFields--flex {
// display: flex;
// flex-flow: row wrap;
// align-items: center;
// margin: auto;
// justify-content: center;
//}
.m-channels--sorted-module__viewMore {
padding: 0 0 16px;
}
}
.m-channelSidebar__bioField {
@include m-theme() {
color: themed($m-black);
}
m-wire-channel {
.mdl-card {
background-color: transparent !important;
box-shadow: none !important;
}
.mdl-card__title {
padding: 8px 0;
}
.m-channelSidebar__city {
i.material-icons {
font-size: 22px;
line-height: 30px;
vertical-align: middle;
margin-right: 10px;
.m-wire-channel--rewards {
//padding: 0 16px;
.m-wire-channel--description {
padding: 16px 0;
}
span {
font-size: 14px;
line-height: 30px;
m-wire-channel-table {
table {
td {
padding: 8px 0;
}
}
}
}
}
......
......@@ -3,83 +3,28 @@ import { MindsUser } from '../../../interfaces/entities';
import { Session } from '../../../services/session';
import { Tag } from '../../hashtags/types/tag';
import { Client } from '../../../services/api/client';
import { ConfigsService } from '../../../common/services/configs.service';
@Component({
selector: 'm-channel__sidebarv2',
templateUrl: 'sidebar-v2.component.html',
})
export class ChannelSidebarV2Component implements OnInit {
minds = window.Minds;
export class ChannelSidebarV2Component {
readonly cdnAssetsUrl;
@Input() user: MindsUser;
@Input() editing: boolean = false;
@Output() changeEditing = new EventEmitter<boolean>();
searching;
errorMessage: string = '';
amountOfTags: number = 0;
tooManyTags: boolean = false;
// @todo make a re-usable city selection module to avoid duplication here
cities: Array<any> = [];
constructor(public client: Client, public session: Session) {}
ngOnInit() {}
constructor(
public client: Client,
public session: Session,
private configs: ConfigsService
) {
this.cdnAssetsUrl = this.configs.get('cdn_assets_url');
}
isOwner() {
return this.session.getLoggedInUser().guid === this.user.guid;
}
findCity(q: string) {
if (this.searching) {
clearTimeout(this.searching);
}
this.searching = setTimeout(() => {
this.client
.get('api/v1/geolocation/list', { q: q })
.then((response: any) => {
this.cities = response.results;
});
}, 100);
}
setCity(row: any) {
this.cities = [];
if (row.address.city) {
this.user.city = row.address.city;
}
if (row.address.town) {
this.user.city = row.address.town;
}
if (window.Minds) {
window.Minds.user.city = this.user.city;
}
this.client.post('api/v1/channel/info', {
coordinates: row.lat + ',' + row.lon,
city: window.Minds.user.city,
});
}
onTagsChange(tags: string[]) {
this.amountOfTags = tags.length;
if (this.amountOfTags > 5) {
this.errorMessage = 'You can only select up to 5 hashtags';
this.tooManyTags = true;
} else {
this.tooManyTags = false;
this.user.tags = tags;
if (this.errorMessage === 'You can only select up to 5 hashtags') {
this.errorMessage = '';
}
}
}
onTagsAdded(tags: Tag[]) {}
onTagsRemoved(tags: Tag[]) {}
setSocialProfile(value: any) {
this.user.social_profiles = value;
}
}
<div class="m-channelStats">
<!-- <a-->
<!-- [routerLink]="['/', user.username, 'feed']"-->
<!-- class="mdl-tabs__tab mdl-color-text&#45;&#45;blue-grey-500"-->
<!-- *ngIf="user.activity_count"-->
<!-- >-->
<!-- <span i18n="Count of activities@@M__COMMON__FEED_COUNT">Feed</span>-->
<!-- <b>{{user.activity_count | number}}</b>-->
<!-- </a>-->
<a
*ngIf="user.supporters_count && session.getLoggedInUser().guid != user.guid"
>
<span class="m-channelStats__title" i18n>
Followers
</span>
<span class="m-channelStats__count">{{
user.supporters_count | abbr
}}</span>
</a>
<a
[routerLink]="['/', user.username, 'supporters']"
*ngIf="user.supporters_count && session.getLoggedInUser().guid == user.guid"
>
<span class="m-channelStats__title" i18n>
Followers
</span>
<span class="m-channelStats__count">{{
user.supporters_count | abbr
}}</span>
</a>
<a [routerLink]="['/', user.username, 'subscribers']">
<span class="m-channelStats__title" i18n>
Following
</span>
<span class="m-channelStats__count">{{
user.subscribers_count | abbr
}}</span>
</a>
<a>
<span class="m-channelStats__title" i18n>
Views
</span>
<span class="m-channelStats__count">{{ user.impressions | abbr }}</span>
</a>
</div>
m-channelstats {
.m-channelStats {
display: flex;
align-items: center;
justify-content: space-between;
margin: 7px 0;
a {
text-decoration: none;
display: flex;
flex-direction: column;
height: 60px;
@include m-theme() {
color: themed($m-black);
}
span {
line-height: 30px;
&.m-channelStats__title {
font-size: 13px;
}
&.m-channelStats__count {
font-size: 18px;
}
}
}
}
}
import { Component, Input } from '@angular/core';
import { MindsUser } from '../../../../interfaces/entities';
import { Session } from '../../../../services/session';
@Component({
selector: 'm-channelstats',
templateUrl: 'channel-stats.component.html',
})
export class ChannelStatsComponent {
@Input() user: MindsUser;
constructor(public session: Session) {}
}
......@@ -40,7 +40,7 @@
></div>
<a
class="mdl-card__supporting-text mdl-color-text--grey-600"
class="mdl-card__supporting-text mdl-color-text--grey-600 m-channels--sorted-module__viewMore"
[routerLink]="linksTo"
>
<ng-container i18n>View More</ng-container>
......
@import 'defaults';
m-newsfeed {
grid-area: content;
grid-area: content / span 2;
min-width: 0;
}
......
......@@ -122,7 +122,7 @@ describe('NewsfeedComponent', () => {
featuresServiceMock.mock('top-feeds', false);
featuresServiceMock.mock('suggested-users', false);
featuresServiceMock.mock('pro', false);
featuresServiceMock.mock('navigation-2020', false);
featuresServiceMock.mock('navigation', false);
sessionMock.user.admin = false;
sessionMock.loggedIn = true;
......
......@@ -82,7 +82,7 @@ export class NewsfeedComponent implements OnInit, OnDestroy {
protected newsfeedService: NewsfeedService,
protected newsfeedHashtagSelectorService: NewsfeedHashtagSelectorService
) {
this.newNavigation = this.featuresService.has('navigation-2020');
this.newNavigation = this.featuresService.has('navigation');
this.urlSubscription = this.route.url.subscribe(() => {
this.tag = null;
......
......@@ -48,6 +48,9 @@ minds-notification.mdl-card {
}
minds-notifications {
grid-area: content/span 2;
min-width: 0;
.m-notifications--load-new {
text-transform: uppercase;
font-family: 'Roboto', Helvetica, sans-serif;
......
......@@ -13,6 +13,7 @@ m-pro--channel {
background-size: cover;
background-blend-mode: overlay;
background-color: var(--m-pro--more-transparent-background-color) !important;
grid-area: content / span 2;
&.m-pro-channel--plainBackground {
background-blend-mode: initial;
......
@import 'defaults';
m-settings {
grid-area: content / span 2;
min-width: 0;
}
.m-settings--wrapper {
max-width: 1280px;
margin: auto;
......
@import 'defaults';
m-wallet {
grid-area: content / span 2;
min-width: 0;
}
.m-wallet--wrapper {
max-width: 1280px;
margin: auto;
......
<div
class="m-wire-channel--call-to-action"
*ngIf="session.getLoggedInUser().guid != channel.guid"
*ngIf="!channelV2Design && session.getLoggedInUser().guid != channel.guid"
>
<button class="mdl-shadow--8dp" (click)="sendWire()">
<i class="ion-icon ion-flash"></i>
......@@ -11,10 +11,21 @@
</button>
</div>
<m-wire-channel--overview [channel]="channel"></m-wire-channel--overview>
<div
class="m-wire-channel--support"
(click)="sendWire()"
*ngIf="channelV2Design && session.getLoggedInUser().guid != channel.guid"
>
<span i18n>Support {{ channel.username }}</span>
</div>
<m-wire-channel--overview
[channel]="channel"
*ngIf="!channelV2Design"
></m-wire-channel--overview>
<div *ngIf="shouldShow()" class="mdl-card mdl-shadow--2dp">
<div class="mdl-card__title">
<div class="mdl-card__title" *ngIf="shouldShowTitle()">
<h2 class="mdl-card__title-text" i18n="@@WIRE__CHANNEL__REWARDS_TITLE">
Rewards
</h2>
......
......@@ -68,6 +68,7 @@ m-wire-channel {
color: themed($m-blue) !important;
}
}
.m-wire-channel--totals-period {
font-size: 11px;
}
......@@ -77,6 +78,7 @@ m-wire-channel {
.m-wire-channel--rewards {
padding-top: 0;
box-sizing: border-box;
tr {
cursor: pointer;
}
......@@ -182,6 +184,7 @@ m-wire-channel {
.m-wire-channel--reward-amount,
.m-wire-channel--reward-description {
font-weight: 400;
span {
padding-right: $minds-padding;
}
......@@ -275,6 +278,13 @@ m-wire-channel {
}
}
.m-wire-channel--support {
font-size: 14px;
line-height: 30px;
font-weight: bold;
cursor: pointer;
}
m--crypto-token-symbol {
.m--crypto-token-symbol--stroke {
@include m-theme() {
......
import { Component, Input, EventEmitter, Output } from '@angular/core';
import { Component, Input, EventEmitter, Output, OnInit } from '@angular/core';
import { Session } from '../../../services/session';
import { OverlayModalService } from '../../../services/ux/overlay-modal';
......@@ -16,9 +16,11 @@ import { SignupModalService } from '../../modals/signup/service';
selector: 'm-wire-channel',
templateUrl: 'channel.component.html',
})
export class WireChannelComponent {
export class WireChannelComponent implements OnInit {
rewards: WireRewardsStruc;
@Input() channelV2Design: boolean = false;
@Input('rewards') set _rewards(rewards: WireRewardsStruc) {
if (rewards) {
this.rewards = rewards;
......@@ -27,9 +29,10 @@ export class WireChannelComponent {
}
}
@Output('rewardsChange') rewardsChangeEmitter: EventEmitter<
@Output('rewardsChange')
rewardsChangeEmitter: EventEmitter<WireRewardsStruc> = new EventEmitter<
WireRewardsStruc
> = new EventEmitter<WireRewardsStruc>();
>();
@Input() channel: any;
......@@ -152,6 +155,12 @@ export class WireChannelComponent {
);
}
shouldShowTitle() {
return this.channelV2Design
? this.session.getLoggedInUser().guid === this.channel.guid
: true;
}
getCurrentTypeLabel() {
return this.typeLabels.find(typeLabel => typeLabel.type === this.display);
}
......
<m-body
[class.has-markers-sidebar]="hasMarkersSidebar()"
[class.has-v2-navbar]="featuresService.has('top-feeds')"
[class.has-v3-navbar]="featuresService.has('navigation')"
[class.is-pro-domain]="isProDomain"
>
<m-emailConfirmation *ngIf="!isProDomain"></m-emailConfirmation>
<m-announcement [id]="'festival:sale'" *mIfFeature="'radiocity'">
<span
class="m-blockchain--wallet-address-notice--action"
i18n="@@MINDS_FESTIVAL_TICKET_SALE"
>
BREAKING: Tickets on sale for "MINDS: FESTIVAL OF IDEAS" @ Radio City on
6/13/2020. HELP US SELL OUT FAST!
</span>
</m-announcement>
<m-blockchain--wallet-address-notice></m-blockchain--wallet-address-notice>
<ng-container *mIfFeature="'navigation'; else oldLayout">
<div class="m-grid">
<m-sidebar--navigation></m-sidebar--navigation>
<router-outlet></router-outlet>
</div>
</ng-container>
<ng-template #oldLayout>
<router-outlet></router-outlet>
</ng-template>
</m-body>
<ng-container *mIfBrowser>
<m-messenger *ngIf="session.isLoggedIn() && !isProDomain"></m-messenger>
</ng-container>
<m-hovercard-popup></m-hovercard-popup>
<m-overlay-modal></m-overlay-modal>
<m--blockchain--transaction-overlay></m--blockchain--transaction-overlay>
<m-modal--tos-updated *ngIf="session.isLoggedIn()"></m-modal--tos-updated>
<ng-container *mIfBrowser>
<m-juryDutySession__summons
*ngIf="session.isLoggedIn() && !isProDomain"
></m-juryDutySession__summons>
</ng-container>
<m-modal-signup
*ngIf="!isProDomain && !session.getLoggedInUser()"
[open]="false"
></m-modal-signup>
<m-channel--onboarding *ngIf="showOnboarding"></m-channel--onboarding>
<m-cookies-notice *ngIf="!session.isLoggedIn()"></m-cookies-notice>
import { Component, OnInit } from '@angular/core';
import { Session } from '../services/session';
import { FeaturesService } from '../services/features.service';
import { SiteService } from '../common/services/site.service';
import { ConfigsService } from '../common/services/configs.service';
import { ChannelOnboardingService } from '../modules/onboarding/channel/onboarding.service';
@Component({
selector: 'm-page',
templateUrl: 'page.component.html',
})
export class PageComponent implements OnInit {
useNewNavigation: boolean = false;
showOnboarding: boolean = false;
constructor(
public session: Session,
public featuresService: FeaturesService,
public onboardingService: ChannelOnboardingService,
private site: SiteService,
private configs: ConfigsService
) {}
ngOnInit() {
this.useNewNavigation = this.featuresService.has('navigation');
}
async initialize() {
this.session.isLoggedIn(async is => {
if (is && !this.site.isProDomain) {
if (!this.site.isProDomain) {
this.showOnboarding = await this.onboardingService.showModal();
}
const user = this.session.getLoggedInUser();
const language = this.configs.get('language');
if (user.language !== language) {
console.log('[app]:: language change', user.language, language);
window.location.reload(true);
}
}
});
this.onboardingService.onClose.subscribe(() => {
this.showOnboarding = false;
});
this.onboardingService.onOpen.subscribe(async () => {
this.showOnboarding = await this.onboardingService.showModal(true);
});
}
get isProDomain() {
return this.site.isProDomain;
}
hasMarkersSidebar() {
return (
this.session.isLoggedIn() &&
!this.isProDomain &&
!this.featuresService.has('navigation')
);
}
}
<ng-container *mIfFeature="'navigation'; else v2Topbar">
<m-v3topbar>
<ng-container search>
<m-search--bar [defaultSizes]="false"></m-search--bar>
</ng-container>
</m-v3topbar>
</ng-container>
<ng-template #v2Topbar>
<m-v2-topbar>
<ng-container search>
<m-search--bar [defaultSizes]="false"></m-search--bar>
</ng-container>
<ng-container icons>
<m-notifications--topbar-toggle
*ngIf="session.isLoggedIn()"
></m-notifications--topbar-toggle>
</ng-container>
</m-v2-topbar>
<m-sidebar--markers
[class.has-v2-navbar]="featuresService.has('top-feeds')"
></m-sidebar--markers>
</ng-template>
import { Component } from '@angular/core';
import { Session } from '../services/session';
import { FeaturesService } from '../services/features.service';
@Component({
selector: 'm-topbarwrapper',
templateUrl: 'topbar.component.html',
})
export class TopbarWrapperComponent {
constructor(
public session: Session,
public featuresService: FeaturesService
) {}
}
<?xml version="1.0" encoding="UTF-8"?>
<svg width="21px" height="19px" viewBox="0 0 21 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 62 (91390) - https://sketch.com -->
<title>iconfinder_currency_2318459 (1) 2</title>
<desc>Created with Sketch.</desc>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="elements/post/pay" transform="translate(-37.000000, -1.000000)" fill="#7D7D82" fill-rule="nonzero">
<g id="iconfinder_currency_2318459-(1)-2" transform="translate(37.000000, 1.000000)">
<g id="iconfinder_currency_2318459-(1)">
<path d="M15.306383,6.05231788 C12.4851064,6.05231788 9.62553191,5.01423841 9.62553191,3.03874172 C9.62553191,1.06324503 12.4851064,0.0251655629 15.306383,0.0251655629 C18.1276596,0.0251655629 20.987234,1.06324503 20.987234,3.03874172 C20.987234,5.01423841 18.1276596,6.05231788 15.306383,6.05231788 Z M15.306383,1.74900662 C12.7531915,1.74900662 11.3744681,2.66754967 11.3744681,3.03874172 C11.3744681,3.41622517 12.7531915,4.32847682 15.306383,4.32847682 C17.8595745,4.32847682 19.2382979,3.40993377 19.2382979,3.03874172 C19.2382979,2.66125828 17.8595745,1.74900662 15.306383,1.74900662 Z" id="Shape"></path>
<path d="M15.306383,9.5 C12.4851064,9.5 9.62553191,8.46192053 9.62553191,6.48642384 L9.62553191,3.03874172 L11.3744681,3.03874172 L11.3744681,6.48642384 C11.3744681,6.86390728 12.7531915,7.77615894 15.306383,7.77615894 C17.8595745,7.77615894 19.2382979,6.85761589 19.2382979,6.48642384 L19.2382979,3.03874172 L20.987234,3.03874172 L20.987234,6.48642384 C20.987234,8.46192053 18.1276596,9.5 15.306383,9.5 Z" id="Path"></path>
<path d="M15.306383,12.9413907 C12.4851064,12.9413907 9.62553191,11.9033113 9.62553191,9.92781457 L9.62553191,6.48013245 L11.3744681,6.48013245 L11.3744681,9.92781457 C11.3744681,10.305298 12.7531915,11.2175497 15.306383,11.2175497 C17.8595745,11.2175497 19.2382979,10.2990066 19.2382979,9.92781457 L19.2382979,6.48013245 L20.987234,6.48013245 L20.987234,9.92781457 C20.987234,11.9096026 18.1276596,12.9413907 15.306383,12.9413907 Z" id="Path"></path>
<path d="M15.306383,16.3890728 C12.4851064,16.3890728 9.62553191,15.3509934 9.62553191,13.3754967 L9.62553191,9.92781457 L11.3744681,9.92781457 L11.3744681,13.3754967 C11.3744681,13.7529801 12.7531915,14.6652318 15.306383,14.6652318 C17.8595745,14.6652318 19.2382979,13.7466887 19.2382979,13.3754967 L19.2382979,9.92781457 L20.987234,9.92781457 L20.987234,13.3754967 C20.987234,15.3509934 18.1276596,16.3890728 15.306383,16.3890728 Z" id="Path"></path>
<path d="M5.69361702,12.0794702 C2.87234043,12.0794702 0.0127659574,11.0413907 0.0127659574,9.06589404 C0.0127659574,7.09039735 2.87234043,6.05231788 5.69361702,6.05231788 C8.51489362,6.05231788 11.3744681,7.09039735 11.3744681,9.06589404 C11.3744681,11.0413907 8.51489362,12.0794702 5.69361702,12.0794702 Z M5.69361702,7.77615894 C3.14042553,7.77615894 1.76170213,8.69470199 1.76170213,9.06589404 C1.76170213,9.44337748 3.14042553,10.3556291 5.69361702,10.3556291 C8.24680851,10.3556291 9.62553191,9.43708609 9.62553191,9.06589404 C9.62553191,8.69470199 8.24680851,7.77615894 5.69361702,7.77615894 Z" id="Shape"></path>
<path d="M5.69361702,15.5271523 C2.87234043,15.5271523 0.0127659574,14.4890728 0.0127659574,12.5135762 L0.0127659574,9.06589404 L1.76170213,9.06589404 L1.76170213,12.5135762 C1.76170213,12.8910596 3.14042553,13.8033113 5.69361702,13.8033113 C8.24680851,13.8033113 9.62553191,12.8847682 9.62553191,12.5135762 L9.62553191,9.06589404 L11.3744681,9.06589404 L11.3744681,12.5135762 C11.3744681,14.4890728 8.51489362,15.5271523 5.69361702,15.5271523 Z" id="Path"></path>
<path d="M5.69361702,18.968543 C2.87234043,18.968543 0.0127659574,17.9304636 0.0127659574,15.9549669 L0.0127659574,12.5072848 L1.76170213,12.5072848 L1.76170213,15.9549669 C1.76170213,16.3324503 3.14042553,17.244702 5.69361702,17.244702 C8.24680851,17.244702 9.62553191,16.3261589 9.62553191,15.9549669 L9.62553191,12.5072848 L11.3744681,12.5072848 L11.3744681,15.9549669 C11.3744681,17.936755 8.51489362,18.968543 5.69361702,18.968543 Z" id="Path"></path>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file