Skip to content
Commits on Source (11)
......@@ -28,13 +28,13 @@
</div>
<ng-container *ngIf="!collapseNavItems">
<!-- <a
<a
class="m-proChannelTopbar__navItem"
[routerLink]="['/pro', channel.username, 'feed']"
[queryParams]="{algorithm: 'pro'}"
routerLinkActive="active"
i18n
>Feed</a>-->
>Feed</a>
<a
class="m-proChannelTopbar__navItem"
[routerLink]="linkTo('videos', searchedText)"
......@@ -65,19 +65,6 @@
routerLinkActive="active"
i18n
>Donate</a>
<a
class="m-proChannelTopbar__navItem"
[routerLink]="['/pro', channel.username, 'signup']"
routerLinkActive="active"
*ngIf="!currentUser"
i18n
>Signup / Login</a>
</ng-container>
<ng-container *ngIf="currentUser">
<a [routerLink]="['/', channel.username]" routerLinkActive="active">
<minds-avatar [object]="currentUser" [editMode]="false"></minds-avatar>
</a>
</ng-container>
<m-pro-user-menu [channelName]="channel.username" [showNavItems]="collapseNavItems" [query]="searchedText"></m-pro-user-menu>
......
......@@ -15,7 +15,7 @@ m-pro--channel {
display: grid;
grid-template-rows: repeat(2, 100px) 1fr 100px;
grid-template-columns: repeat(12, 1fr);
min-height: 100%;
min-height: calc(100vh - 52px); /* 52px is the topbar height */
.m-proChannel__topbar {
grid-row: 1 / span 1;
......@@ -57,24 +57,30 @@ m-pro--channel {
position: absolute;
margin: 6px;
font-size: 20px;
color: rgba(0,0,0,.87)!important;
@include m-theme() {
color: themed($m-black);
}
}
i.clear {
font-size: 16px;
background-color: #3e3737;
color: white;
border-radius: 20px;
cursor: pointer;
position: absolute;
top: 16px;
right: 10px;
@include m-theme() {
color: themed($m-black);
}
}
input {
height: 32px;
border-radius: 18px;
font-family: Roboto,sans-serif;
font-family: Roboto, sans-serif;
font-size: 14px;
letter-spacing: .5px;
font-weight: 600;
......
......@@ -3,16 +3,17 @@ import {
ChangeDetectorRef,
Component,
ElementRef,
HostBinding, HostListener,
HostBinding,
HostListener,
OnDestroy,
OnInit
} from '@angular/core';
import { ActivatedRoute, Router, NavigationEnd, NavigationStart } from "@angular/router";
import { ActivatedRoute, Router, NavigationEnd, NavigationStart } from "@angular/router";
import { Session } from "../../../services/session";
import { Subscription } from "rxjs";
import { MindsUser } from "../../../interfaces/entities";
import { Client } from "../../../services/api/client";
import { Title } from "@angular/platform-browser";
import { MindsTitle } from '../../../services/ux/title';
import { ProChannelService } from './channel.service';
@Component({
......@@ -48,7 +49,7 @@ export class ProChannelComponent implements OnInit, OnDestroy {
protected session: Session,
protected channelService: ProChannelService,
protected client: Client,
protected title: Title,
protected title: MindsTitle,
protected router: Router,
protected route: ActivatedRoute,
protected cd: ChangeDetectorRef,
......@@ -67,8 +68,9 @@ export class ProChannelComponent implements OnInit, OnDestroy {
if (!navigationEvent.urlAfterRedirects) {
return;
}
this.currentURL = navigationEvent.urlAfterRedirects;
this.setTitle();
}
} catch (e) {
console.error('Minds: router hook(SearchBar)', e);
......@@ -86,6 +88,23 @@ export class ProChannelComponent implements OnInit, OnDestroy {
});
}
setTitle() {
let title = this.channel.pro_settings.title as string || this.channel.name;
const childRoute = this.route.children.length > 0 ? this.route.children[0].snapshot : null;
if (childRoute && childRoute.params['type']) {
title += ` - ${childRoute.params['type']}`;
}
if (this.channel.pro_settings.headline) {
title += ` - ${this.channel.pro_settings.headline}`;
}
this.title.setTitle(title);
}
ngOnDestroy() {
this.params$.unsubscribe();
this.routerSubscription.unsubscribe();
......@@ -102,24 +121,18 @@ export class ProChannelComponent implements OnInit, OnDestroy {
try {
this.channel = await this.channelService.load(this.username);
let title = this.channel.pro_settings.title as string || this.channel.name;
this.bindCssVariables();
if (this.channel.pro_settings.headline) {
title += ` - ${this.channel.pro_settings.headline}`;
}
this.title.setTitle(title);
this.setTitle();
} catch (e) {
this.error = e.getMessage();
}
this.detectChanges();
}
bindCssVariables() {
const styles = this.channel.pro_settings.styles;
const modal: HTMLElement = document.querySelector('m-app m-overlay-modal');
for (const style in styles) {
if (!styles.hasOwnProperty(style)) {
......@@ -135,6 +148,7 @@ export class ProChannelComponent implements OnInit, OnDestroy {
const styleAttr = style.replace(/_/g, "-");
this.element.nativeElement
.style.setProperty(`--${styleAttr}`, styles[style]);
modal.style.setProperty(`--${styleAttr}`, styles[style]);
}
}
......@@ -151,6 +165,14 @@ export class ProChannelComponent implements OnInit, OnDestroy {
return `url(${this.channel.pro_settings.background_image})`;
}
@HostBinding('class') get cssColorSchemeOverride() {
if (!this.channel) {
return '';
}
return `m-theme--wrapper__${this.channel.pro_settings.scheme || 'light'}`;
}
@HostListener('window:resize') onResize() {
this.collapseNavItems = window.innerWidth <= 992 ? true : false;
}
......@@ -164,7 +186,7 @@ export class ProChannelComponent implements OnInit, OnDestroy {
}
search() {
if(!this.currentURL){
if (!this.currentURL) {
this.currentURL = `/pro/${this.channel.username}/articles`; //TODO ADD /TOP when algorithm is enable
} else {
if (this.currentURL.includes('query')) {
......@@ -172,7 +194,7 @@ export class ProChannelComponent implements OnInit, OnDestroy {
}
}
this.router.navigate([this.currentURL,{ query: this.searchedText, period: '24h' }]);
this.router.navigate([this.currentURL, { query: this.searchedText, period: '24h' }]);
}
clearSearch() {
......
......@@ -3,8 +3,8 @@
}
.m-overlay-modal.m-overlayModal--media {
padding:0px;
max-width:95%;
padding: 0px;
max-width: 95%;
z-index: 9999998;
}
......@@ -31,28 +31,30 @@ m-media--modal {
position: relative;
width: 100%;
overflow: hidden; // .????
@include m-theme(){
@include m-theme() {
background-color: rgba(themed($m-black-always), 0.95);
}
&:hover {
.m-mediaModal__theaterOverlay{
.m-mediaModal__theaterOverlay {
opacity: 1;
}
}
img{
img {
object-fit: contain;
flex: 1;
overflow: hidden;
}
m-video{
@include m-theme(){
m-video {
@include m-theme() {
background-color: themed($m-black-always);
}
video{
max-width:100%;
height:100%;
video {
max-width: 100%;
height: 100%;
}
}
......@@ -69,8 +71,8 @@ m-media--modal {
transition: opacity 500ms cubic-bezier(.22, 1, .33, 1);
box-sizing: border-box;
font-size: 24px;
@include m-theme(){
background: linear-gradient(rgba(themed($m-black-always),0.5), transparent);
@include m-theme() {
background: linear-gradient(rgba(themed($m-black-always), 0.5), transparent);
}
&:hover {
......@@ -83,9 +85,8 @@ m-media--modal {
text-overflow: ellipsis;
text-decoration: none;
@include m-theme(){
color: themed($m-white-always);
}
color: var(--text-color);
&:hover {
text-decoration: underline;
}
......@@ -93,9 +94,7 @@ m-media--modal {
// TODO OJM fullscreen styles e.g. .myClass:not(:fullscreen)
.m-mediaModal__fullscreenButton {
@include m-theme(){
color: themed($m-white-always);
}
color: var(--text-color);
transition: transform 150ms ease;
......@@ -108,6 +107,7 @@ m-media--modal {
.m-mediaModal__fullscreenIcon--enable {
transform: scale(1.2);
}
.m-mediaModal__fullscreenIcon--disable {
transform: scale(0.83);
}
......@@ -116,6 +116,7 @@ m-media--modal {
.m-mediaModal__fullscreenIcon--disable {
font-size: 28px;
}
.m-mediaModal__fullscreenIcon--disable {
font-size: 34px;
}
......@@ -138,9 +139,7 @@ m-media--modal {
padding: 16px;
font-family: 'Roboto', Helvetica, sans-serif;
@include m-theme(){
background-color: themed($m-white);
}
background-color: var(--plain-background-color);
.m-mediaModal__ownerBlock {
padding: 0;
......@@ -154,6 +153,7 @@ m-media--modal {
white-space: nowrap;
font-weight: 500;
}
.m-ownerBlock__channelLink, .m-ownerBlock__groupLink {
text-decoration: none;
}
......@@ -168,9 +168,7 @@ m-media--modal {
white-space: pre-wrap;
line-height: 18px;
-webkit-font-smoothing: antialiased;
@include m-theme(){
color: themed($m-grey-400);
}
color: var(--text-color);
> * {
padding-right: 8px;
......@@ -184,14 +182,12 @@ m-media--modal {
.m-ownerBlock__permalinkFlag {
text-transform: uppercase;
padding: 0 8px 0 0 ;
padding: 0 8px 0 0;
letter-spacing: 0.5px;
font-weight: 700;
font-size: 11px;
line-height: 1;
@include m-theme(){
color: themed($m-grey-400);
}
color: var(--text-color);
}
.m-ownerBlock__permalinkFlag--boosted {
......@@ -207,18 +203,15 @@ m-media--modal {
a {
vertical-align: middle;
@include m-theme(){
color: themed($m-grey-400);
}
color: var(--text-color);
}
&.m-ownerBlock__permalinkFlag--onchain {
@include m-theme(){
color: themed($m-blue);
}
color: var(--primary-color);
a {
@include m-theme(){
color: themed($m-blue);
@include m-theme() {
color: var(--primary-color);
}
}
}
......@@ -226,12 +219,14 @@ m-media--modal {
}
}
.m-mediaModal__actionButtonsWrapper {
.m-mediaModal__actionButtonsRow {
display: flex;
justify-content: space-around;
padding-top: 16px;
}
minds-button-boost {
button {
margin-top: 8px;
......@@ -243,7 +238,7 @@ m-media--modal {
.m-mediaModal__commentsWrapper {
padding-top: $minds-padding;
@include m-theme(){
@include m-theme() {
border-top: 1px solid themed($m-grey-100);
}
......@@ -252,7 +247,6 @@ m-media--modal {
flex: 1;
m-comments__tree {
height: 100%;
// height: calc(100vh - 45px);
......@@ -294,6 +288,7 @@ m-media--modal {
}
.minds-comment {
padding: 8px 0px;
......@@ -305,8 +300,9 @@ m-media--modal {
display: block;
}
.m-comment-attachment .m-rich-embed{
.m-comment-attachment .m-rich-embed {
max-width: 63%;
.m-blurb {
display: block;
}
......
<span>{{footerText}}</span>
<div class="m-pro--channel-footer">
<span class="m-pro--channel-footer--text">{{footerText}}</span>
<div class="mdl-color-text--blue-grey-600">
<div class="m-pro--channel-footer--social-profiles">
<span *ngFor="let profile of footerSocialProfiles">
<a *ngIf="profile.key && profile.value"
[href]="getSocialProfileURL(profile.value)"
rel="noopener noreferrer"
target="_blank"
[href]="getSocialProfileURL(profile.value)"
rel="noopener noreferrer"
target="_blank"
><i [ngClass]="[ getSocialProfileIconClass(profile) ]"></i></a>
</span>
</div>
<a [href]="link.href" *ngFor="let link of footerLinks">{{link.title}}</a>
</div>
<a
*ngFor="let link of footerLinks"
class="m-pro--channel-footer--link"
[href]="link.href"
>{{link.title}}</a>
</div>
m-pro--channel-footer {
.m-pro--channel-footer {
display: flex;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
height: 100px;
color: var(--text-color);
a {
text-decoration: none;
......
......@@ -7,3 +7,17 @@
grid-gap: 16px;
grid-template-columns: repeat(3, 1fr);
}
m-overlay-modal {
.m-overlayModal--seeMore {
background-color: var(--plain-background-color) !important;
a.m-overlay-modal--close {
background-color: var(--transparent-background-color) !important;
i {
color: var(--text-color) !important;
}
}
}
}
......@@ -78,13 +78,21 @@ export class ProChannelListModal {
}
async expand(entity) {
if (entity.subtype !== 'video' && entity.subtype !== 'image') {
return;
switch (this.getType(entity)) {
case 'object:blog':
window.open(`${window.Minds.site_url}${entity.route}/`, '_blank');
break;
case 'object:image':
case 'object:video':
this.modalService.create(ProContentModalComponent, entity, {
class: 'm-overlayModal--media'
}, this.injector).present();
break;
}
}
this.modalService.create(ProContentModalComponent, entity, {
class: 'm-overlayModal--media'
}, this.injector).present();
private getType(entity: any) {
return entity.type === 'object' ? `${entity.type}:${entity.subtype}` : entity.type;
}
detectChanges() {
......
......@@ -136,7 +136,14 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
seeMore() {
this.modalService
.create(ProChannelListModal, { type: this.type, algorithm: 'latest', query: this.query }, void 0, this.injector)
.create(ProChannelListModal, {
type: this.type,
algorithm: 'latest',
query: this.query,
},
{
class: 'm-overlayModal--seeMore'
}, this.injector)
.present();
}
......
......@@ -45,25 +45,6 @@
<a [routerLink]="['/pro', channel.username, 'donate']" routerLinkActive="active">Donate</a>
</li>
</ng-container>
<li
class="m-dropdownList__item m-pro-user-menuDropdown__item"
(click)="closeMenu()"
>
<a [routerLink]="['/', channelName]">
<i class="material-icons">remove_red_eye</i>
<span i18n>View on Minds</span>
</a>
</li>
<li
class="m-dropdownList__item m-pro-user-menuDropdown__item"
*ngIf="getCurrentUser()"
(click)="closeMenu()"
>
<a routerLink="/logout">
<i class="material-icons">exit_to_app</i>
<span i18n>Logout</span>
</a>
</li>
</ul>
</div>
......
......@@ -2,6 +2,10 @@ m-pro-user-menu {
display: inline-block;
position: relative;
cursor: pointer;
@media screen and (min-width: 1000px) {
display: none;
}
}
.m-pro-user-menu__dropdown {
......
......@@ -29,7 +29,23 @@ export class ProService {
}
async get(): Promise<{ isActive, settings }> {
return await this.client.get('api/v2/pro/settings', {}, {cache: false}) as any;
const { isActive, settings } = await this.client.get('api/v2/pro/settings', {}, {cache: false}) as any;
if (settings) {
if (settings.tag_list) {
settings.tag_list = settings.tag_list.map(({ tag, label }) => {
const formattedTag = `#${tag}`;
return { tag: formattedTag, label };
});
}
if (!settings.scheme) {
settings.scheme = 'light';
}
}
return { isActive, settings };
}
async set(settings): Promise<boolean> {
......
......@@ -24,6 +24,17 @@
</m-tooltip>
</a>
<a
class="m-topbar--navigation--item"
[class.m-topbar--navigation--item-active]="currentTab === 'hashtags'"
(click)="currentTab = 'hashtags'"
>
<span i18n>Hashtags</span>
<m-tooltip icon="help" i18n>
TBD
</m-tooltip>
</a>
<a
class="m-topbar--navigation--item"
[class.m-topbar--navigation--item-active]="currentTab === 'footer'"
......@@ -86,7 +97,7 @@
<ng-template ngSwitchCase="theme">
<p class="m-pro--settings--note" i18n>
Set up your colors schema below.
Set up your color scheme below.
</p>
<div class="m-pro--settings--field">
......@@ -104,12 +115,64 @@
<input type="color" id="plain_background_color" name="plain_background_color" [(ngModel)]="settings.plain_background_color">
</div>
<div class="m-pro--settings--field">
<label i18n>Color Schema</label>
<input type="radio" id="scheme_light" name="scheme" value="light" [(ngModel)]="settings.scheme">
<label for="scheme_light" class="m-pro--settings--inline-label">Light</label>
<input type="radio" id="scheme_dark" name="scheme" value="dark" [(ngModel)]="settings.scheme">
<label for="scheme_dark" class="m-pro--settings--inline-label">Dark</label>
</div>
<div class="m-pro--settings--field">
<label for="logo_guid" i18n>Logo Asset GUID</label>
<input type="text" id="logo_guid" name="logo_guid" [(ngModel)]="settings.logo_guid">
</div>
</ng-template>
<!-- Tags -->
<ng-template ngSwitchCase="hashtags">
<p class="m-pro--settings--note" i18n>
Set up your category filter hashtags here.
</p>
<div class="m-pro--settings--field" *ngFor="let tag of settings.tag_list; let i = index">
<label for="headline" i18n>Hashtag #{{ i + 1 }}</label>
<div class="m-pro--settings--flex-inputs">
<input
type="text"
placeholder="Label"
[id]="'tag-label-' + i"
[name]="'tag[' + i + '][label]'"
[(ngModel)]="tag.label"
i18n-placeholder
>
<input
type="text"
placeholder="#hashtag"
[id]="'tag-tag-' + i"
[name]="'tag[' + i + '][tag]'"
[(ngModel)]="tag.tag"
i18n-placeholder
>
</div>
</div>
<div class="m-pro--settings--field">
<button
class="m-btn m-btn--slim"
type="button"
[disabled]="inProgress"
(click)="addBlankTag()"
i18n
>+ Add Tag</button>
</div>
</ng-template>
<!-- Footer -->
<ng-template ngSwitchCase="footer">
......
......@@ -38,6 +38,12 @@
@include m-theme() {
color: themed($m-grey-800);
}
&.m-pro--settings--inline-label {
display: inline-block;
padding: 0;
margin: 0 0.35em;
}
}
input[type=text],
......
......@@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@
import { ProService } from '../pro.service';
import { Session } from '../../../services/session';
import { Router } from '@angular/router';
import { MindsTitle } from '../../../services/ux/title';
@Component({
selector: 'm-pro--settings',
......@@ -16,13 +17,14 @@ export class ProSettingsComponent implements OnInit {
saved: boolean = false;
currentTab: 'general' | 'theme' | 'footer' | 'cancel' = 'general';
currentTab: 'general' | 'theme' | 'hashtags' | 'footer' | 'cancel' = 'general';
constructor(
protected service: ProService,
protected session: Session,
protected router: Router,
protected cd: ChangeDetectorRef,
protected title: MindsTitle
) {
}
......@@ -43,6 +45,8 @@ export class ProSettingsComponent implements OnInit {
this.settings = settings;
this.title.setTitle('Pro Settings');
this.inProgress = false;
this.detectChanges();
}
......@@ -58,6 +62,14 @@ export class ProSettingsComponent implements OnInit {
this.detectChanges();
}
addBlankTag() {
if (!this.settings) {
return;
}
this.settings.tag_list.push({ label: '', tag: '' });
}
addBlankFooterLink() {
if (!this.settings) {
return;
......
......@@ -3,7 +3,8 @@
// Colors change when .theme__light/.theme__dark classes are toggled on body tag
@mixin m-theme() {
@each $theme, $colors in $themes {
body.m-theme__#{$theme} & {
body.m-theme__#{$theme} &,
body .m-theme--wrapper__#{$theme} & {
$theme-map: () !global;
@each $color-name, $color in $colors {
$value: map-get(map-get($themes, $theme), '#{$color-name}');
......