Commit af8f9600 authored by Emiliano Balbuena's avatar Emiliano Balbuena

(refactor): Infinite modals

1 merge request!507WIP: (feat): Minds Pro (development branch) - Release 3
Pipeline #79163119 running with stages
<div class="m-pro--channel-list-modal">
<div
class="m-pro--channel-list-modal--grid"
[class.m-pro--channel-list-modal--activities-grid]="type === 'activities'"
>
<ng-container *ngFor="let entity$ of (entities$ | async); let i = index">
<ng-container *ngIf="entity$ | async as entity">
<ng-container *ngIf="type === 'all' || type === 'images' || type === 'videos' || type === 'blogs'">
<m-pro--channel-tile
[entity]="entity"
(click)="expand(entity)"
></m-pro--channel-tile>
</ng-container>
<ng-container *ngIf="type === 'activities'">
<minds-activity
[object]="entity"
></minds-activity>
</ng-container>
</ng-container>
</ng-container>
</div>
<infinite-scroll
distance="25%"
(load)="loadMore()"
[moreData]="hasMore$ | async"
[inProgress]="inProgress$ | async"
[scrollSource]="this.parent"
></infinite-scroll>
</div>
<m-overlay-modal #overlayModal></m-overlay-modal>
.m-pro--channel-list-modal {
margin-top: 48px;
}
.m-pro--channel-list-modal--grid {
display: grid;
grid-gap: 16px;
grid-template-columns: repeat(2, 1fr);
&.m-pro--channel-list-modal--activities-grid {
grid-template-columns: repeat(1, 1fr);
max-width: 500px;
margin: 0 auto;
}
}
m-overlay-modal {
.m-overlayModal--seeMore {
background-color: var(--m-pro--plain-background-color) !important;
a.m-overlay-modal--close {
background-color: var(--m-pro--transparent-background-color) !important;
i {
color: var(--m-pro--text-color) !important;
}
}
}
}
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Injector, ViewChild } from '@angular/core';
import { ProChannelService } from '../channel.service';
import { FeedsService } from '../../../../common/services/feeds.service';
import { OverlayModalService } from '../../../../services/ux/overlay-modal';
import { OverlayModalComponent } from '../../../../common/components/overlay-modal/overlay-modal.component';
@Component({
selector: 'm-pro--channel-list-modal',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: 'list-modal.component.html',
providers: [FeedsService, OverlayModalService],
})
export class ProChannelListModal {
type: string;
algorithm: string;
query: string;
hashtag: string;
parent: HTMLDivElement;
@ViewChild('overlayModal', { static: true }) protected overlayModal: OverlayModalComponent;
set data({ type, query, hashtag }) {
this.type = type;
this.query = query;
this.hashtag = hashtag;
}
constructor(
protected channelService: ProChannelService,
protected feedsService: FeedsService,
protected modalService: OverlayModalService,
protected element: ElementRef,
protected cd: ChangeDetectorRef,
protected injector: Injector,
) {
}
ngAfterViewInit() {
this.modalService
.setContainer(this.overlayModal)
.setRoot(this.element.nativeElement);
this.load(true);
}
async load(refresh: boolean = false) {
if (refresh) {
this.feedsService.clear();
}
this.detectChanges();
let url = `api/v2/feeds/channel/${this.channelService.currentChannel.guid}/${this.type}/${this.algorithm}`;
let params = [];
if (this.query && this.query !== '') {
params.push(`query=${this.query}`);
}
if (this.hashtag && this.hashtag !== 'all') {
params.push(`hashtags=${this.hashtag}`);
}
if (params.length > 0) {
url += '?' + params.join('&');
}
try {
this.feedsService
.setEndpoint(url)
.setLimit(12)
.fetch();
} catch (e) {
console.error('ProChannelListModal.load', e);
}
}
get entities$() {
return this.feedsService.feed;
}
get hasMore$() {
return this.feedsService.hasMore;
}
get inProgress$() {
return this.feedsService.inProgress;
}
loadMore() {
this.feedsService.loadMore();
}
expand(entity: any) {
return this.channelService.open(entity, this.modalService);
}
private getType(entity: any) {
return entity.type === 'object' ? `${entity.type}:${entity.subtype}` : entity.type;
}
detectChanges() {
this.cd.markForCheck();
this.cd.detectChanges();
}
}
......@@ -5,51 +5,60 @@
></m-pro--channel--categories>
<div class="m-proChannelList__tools" *ngIf="query !== ''">
<div class="m-proChannelListTools__searchResult"> <!--TODO add ngif after enable algorithm *ngIf="query !== ''"-->
<div class="m-proChannelListTools__searchResult">
<span> Showing results for: <strong> {{query}}</strong></span>
</div>
</div>
<div class="m-proChannelList__content" *ngIf="!(inProgress$ | async); else inProgressLoader">
<div class="m-proChannelList__content">
<ul class="m-proChannelListContent__list" [class.m-proChannelListContent__normalList]="type === 'activities'">
<li *ngFor="let entity of entities; let i = index">
<ng-container *ngIf="type === 'all' || type === 'images' || type === 'videos' || type === 'blogs'">
<m-pro--channel-tile
[entity]="entity"
></m-pro--channel-tile>
</ng-container>
<ng-container *ngIf="type === 'groups'">
<m-pro--channel--group-tile
[entity]="entity"
(onOpen)="onTileClicked(entity)"
[class.big]="i === 0 || i === 1"
></m-pro--channel--group-tile>
</ng-container>
<li *ngFor="let entity$ of (entities$ | async); let i = index">
<ng-container *ngIf="entity$ | async as entity">
<ng-container *ngIf="type === 'all' || type === 'images' || type === 'videos' || type === 'blogs'">
<m-pro--channel-tile
[entity]="entity"
(click)="onTileClicked(entity)"
></m-pro--channel-tile>
</ng-container>
<ng-container *ngIf="type === 'activities'">
<minds-activity
[object]="entity"
></minds-activity>
<ng-container *ngIf="type === 'groups'">
<m-pro--channel--group-tile
[entity]="entity"
(onOpen)="onTileClicked(entity)"
[class.big]="i === 0 || i === 1"
></m-pro--channel--group-tile>
</ng-container>
<ng-container *ngIf="type === 'activities'">
<minds-activity
[object]="entity"
></minds-activity>
</ng-container>
</ng-container>
<li
class="m-proChannelListContentList__seeMore"
*ngIf="entities && displaySeeMoreTile"
(click)="seeMore()"
i18n
>
<span>See more&hellip;</span>
</li>
</ul>
<ng-container *ngIf="entities.length == 0">
<div class="m-proChannelListContent__noContent" i18n>There's nothing to show</div>
</ng-container>
<ng-container *ngIf="type === 'activities'">
<pre *ngFor="let entity of entities"></pre>
<!-- talk to Emi about this -->
<ng-container *ngIf="!(inProgress$ | async)">
<div
*ngIf="hasMore$ | async; else noMore"
class="m-proChannelListContent__loadMore"
(click)="loadMore()"
i18n
>
Click to load more
</div>
<ng-template #noMore>
<div
class="m-proChannelListContent__loadMore"
i18n
>
Click to load more
</div>
</ng-template>
</ng-container>
</div>
<ng-template #inProgressLoader>
<div class="m-proChannelList__loader">
<div class="m-proChannelList__loader" *ngIf="inProgress$ | async">
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div>
</ng-template>
</div>
......@@ -71,21 +71,19 @@ m-pro--channel-list {
color: var(--m-pro--text-color);
}
.m-proChannelListContentList__seeMore {
.m-proChannelListContent__loadMore {
width: 100%;
font-size: 20px;
padding: 16px;
margin-top: 32px;
cursor: pointer;
text-align: center;
font-weight: 300;
color: var(--m-pro--text-color);
background-color: var(--m-pro--transparent-background-color);
font-size: 30px;
text-align: center;
vertical-align: middle;
cursor: pointer;
min-height: 220px;
&.m-proChannelListContent__noMore {
> span {
display: block;
width: 100%;
}
}
......@@ -103,10 +101,6 @@ m-pro--channel-list {
max-width: 500px;
justify-self: center;
&.m-proChannelListContentList__seeMore {
width: 500px;
}
minds-activity {
min-width: 100%;
}
......
......@@ -3,9 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { Subscription } from "rxjs";
import { FeedsService } from "../../../../common/services/feeds.service";
import { ProChannelService, RouterLinkToType } from '../channel.service';
import { first } from "rxjs/operators";
import { OverlayModalService } from "../../../../services/ux/overlay-modal";
import { ProChannelListModal } from '../list-modal/list-modal.component';
@Component({
selector: 'm-pro--channel-list',
......@@ -29,8 +27,6 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
period: string;
displaySeeMoreTile: boolean = false;
selectedHashtag: string = 'all';
constructor(
......@@ -41,14 +37,9 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
protected router: Router,
protected cd: ChangeDetectorRef,
protected injector: Injector,
) {
}
) { }
ngOnInit() {
this.listen();
}
private listen() {
this.params$ = this.route.params.subscribe(params => {
this.entities = [];
if (params['type']) {
......@@ -83,23 +74,6 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
this.load(true);
});
this.feedsService.feed.subscribe(async (entities) => {
if (!entities.length)
return;
for (const entity of entities) {
if (entity)
this.entities.push(await entity.pipe(first()).toPromise());
}
if (this.entities.length >= 10) {
this.displaySeeMoreTile = true;
this.entities = this.entities.slice(0, 9);
}
this.detectChanges();
});
}
ngOnDestroy() {
......@@ -110,12 +84,9 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
async load(refresh: boolean = false) {
if (refresh) {
this.entities = [];
this.feedsService.clear();
}
this.displaySeeMoreTile = false;
this.detectChanges();
let params: any = {};
......@@ -138,7 +109,7 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
.setEndpoint(url)
.setParams(params)
.setCastToActivities(false)
.setLimit(10)
.setLimit(12)
.fetch();
} catch (e) {
......@@ -146,31 +117,20 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
}
}
loadNext() {
this.feedsService.loadMore();
get entities$() {
return this.feedsService.feed;
}
get inProgress$() {
return this.feedsService.inProgress;
get hasMore$() {
return this.feedsService.hasMore;
}
detectChanges() {
this.cd.markForCheck();
this.cd.detectChanges();
get inProgress$() {
return this.feedsService.inProgress;
}
seeMore() {
this.modalService
.create(ProChannelListModal, {
type: this.type,
algorithm: 'latest',
query: this.query,
hashtag: this.selectedHashtag
},
{
class: 'm-overlayModal--seeMore'
}, this.injector)
.present();
loadMore() {
this.feedsService.loadMore();
}
onTileClicked(entity: any) {
......@@ -184,10 +144,15 @@ export class ProChannelListComponent implements OnInit, OnDestroy {
params = { hashtag: tag };
}
return this.router.navigate(this.channelService.getRouterLink(this.paramsType as RouterLinkToType, params))
return this.router.navigate(this.channelService.getRouterLink(this.paramsType as RouterLinkToType, params));
}
get shouldShowCategories() {
return this.paramsType !== 'groups' && this.paramsType !== 'feed';
return this.paramsType !== 'groups' && this.paramsType !== 'feed' && !this.query;
}
detectChanges() {
this.cd.markForCheck();
this.cd.detectChanges();
}
}
......@@ -17,7 +17,6 @@ import { ProChannelFooterComponent } from './channel/footer/footer.component';
import { LegacyModule } from "../legacy/legacy.module";
import { WireModule } from "../wire/wire.module";
import { VideoModule } from "../media/components/video/video.module";
import { ProChannelListModal } from './channel/list-modal/list-modal.component';
import { ProChannelHomeComponent } from './channel/home/home.component';
import { ProGroupTileComponent } from "./channel/tiles/group/group-tile.component";
import { ProUnsubscribeModalComponent } from './channel/unsubscribe-modal/modal.component';
......@@ -103,7 +102,6 @@ export const STANDALONE_ROUTES = [
ProTileComponent,
ProChannelHomeComponent,
ProCategoriesComponent,
ProChannelListModal,
ProChannelComponent,
ProChannelLoginComponent,
ProChannelListComponent,
......@@ -116,7 +114,6 @@ export const STANDALONE_ROUTES = [
],
entryComponents: [
MediaModalComponent,
ProChannelListModal,
ProUnsubscribeModalComponent,
BlogView,
],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment