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

Feat/nft showcase preview #371

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
15 changes: 15 additions & 0 deletions src/app/backend-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class BackendRoutes {
static RoutePathGetNFTsForUser = "/api/v0/get-nfts-for-user";
static RoutePathGetNFTBidsForUser = "/api/v0/get-nft-bids-for-user";
static RoutePathGetNFTShowcase = "/api/v0/get-nft-showcase";
static RoutePathGetNFTShowcasePreview = "/api/v0/admin/get-nft-showcase-preview";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to live with the rest of the admin routes below.

static RoutePathGetNextNFTShowcase = "/api/v0/get-next-nft-showcase";
static RoutePathGetNFTCollectionSummary = "/api/v0/get-nft-collection-summary";
static RoutePathGetNFTEntriesForPostHash = "/api/v0/get-nft-entries-for-nft-post";
Expand Down Expand Up @@ -906,6 +907,20 @@ export class BackendApiService {
});
}

GetNFTShowcaseAdminPreview(
endpoint: string,
AdminPublicKey: string,
ReaderPublicKeyBase58Check: string,
DropIdx: number
): Observable<any> {
return this.jwtPost(endpoint, BackendRoutes.RoutePathGetNFTShowcasePreview, AdminPublicKey, {
AdminPublicKey,
ReaderPublicKeyBase58Check,
DropIdx,
});
}


GetNextNFTShowcase(endpoint: string, UserPublicKeyBase58Check: string): Observable<any> {
return this.post(endpoint, BackendRoutes.RoutePathGetNextNFTShowcase, {
UserPublicKeyBase58Check,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
<i class="fas fa-ellipsis-h"></i>
</a>
<div class="dropdown-menu dropdown-menu-right p-0 border background-color-light-grey fs-15px" *dropdownMenu>
<a
class="dropdown-menu-item d-block link--unstyled p-10px feed-post__dropdown-menu-item"
(click)="reportUser()"
>
<i class="fas fa-flag"></i>
Report User
</a>
lazynina marked this conversation as resolved.
Show resolved Hide resolved
<a
class="dropdown-menu-item d-block link--unstyled p-10px feed-post__dropdown-menu-item"
(click)="globalVars.hasUserBlockedCreator(profile.PublicKeyBase58Check) ? unblock() : block()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ export class CreatorProfileTopCardComponent implements OnInit, OnDestroy {
this.userBlocked.emit(this.profile.PublicKeyBase58Check);
}

reportUser(): void {
this.globalVars.logEvent("post : report-user");
window.open(
`https://report.bitclout.com/account?ReporterPublicKey=${this.globalVars.loggedInUser?.PublicKeyBase58Check}&ReportedAccountPublicKey=${this.profile.PublicKeyBase58Check}`
);
}

messageUser(): void {
this.router.navigate(["/" + this.globalVars.RouteNames.INBOX_PREFIX], {
queryParams: { username: this.profile.Username },
Expand Down
9 changes: 7 additions & 2 deletions src/app/nft-drop-mgr/nft-drop-mgr.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@
<simple-center-loader *ngIf="loading"></simple-center-loader>

<div class="w-100 light-grey-divider border-bottom border-top border-color-grey" style="height:10px"></div>

<div *ngIf="posts.length > 0 && (!loading || loadingNewDrop)" class="p-15px fs-15px">
<tab-selector [tabs]="feedTabs" [activeTab]="activeTab" (tabClick)="_handleTabClick($event)"></tab-selector>
<!--Admin panel-->
<div *ngIf="showShowcaseManagementTab()" class="p-15px fs-15px">
<b *ngIf="!loadingNewDrop">NFTs in this drop:</b>
<div #uiScroll *uiScroll="let post of datasource" [ngClass]="{'d-flex align-items-center mt-15px border border-color-grey br-8px': !loadingNewDrop}">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this uiScroll directive needs to be moved into a separate component. If you switch back and forth between the tabs, you're going to lose the Showcase Management view. You'll see an error that looks like the below:

ERROR TypeError: Cannot read property 'dispose' of undefined
    at UiScrollComponent.ngOnDestroy (ngx-ui-scroll.js:57)
    at executeOnDestroys (core.js:7405)
    at cleanUpView (core.js:7318)
    at destroyViewTree (core.js:7144)
    at destroyLView (core.js:7296)
    at ViewContainerRef.remove (core.js:23208)
    at ViewContainerRef.clear (core.js:23116)
    at NgIf._updateView (common.js:3535)
    at NgIf.set ngIf [as ngIf] (common.js:3502)
    at setInputsForProperty (core.js:10961)

<i (click)="removeNFT(post.PostHashHex)"
Expand All @@ -115,3 +116,7 @@
<span *ngIf="post.PostHashHex === nftBeingRemoved">&nbsp;Removing...</span>
</div>
</div>
<!--Showcase preview-->
<div *ngIf="showShowcasePreviewTab()">
<nft-showcase [showcaseIdx]="dropNumber"></nft-showcase>
</div>
52 changes: 50 additions & 2 deletions src/app/nft-drop-mgr/nft-drop-mgr.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { Component, OnInit } from "@angular/core";
import {Component, Input, OnInit} from "@angular/core";
lazynina marked this conversation as resolved.
Show resolved Hide resolved
import { GlobalVarsService } from "../global-vars.service";
import { BackendApiService } from "../backend-api.service";
import { SwalHelper } from "../../lib/helpers/swal-helper";
import { InfiniteScroller } from "../infinite-scroller";
import { IAdapter, IDatasource } from "ngx-ui-scroll";
import {ActivatedRoute, Router} from "@angular/router";
lazynina marked this conversation as resolved.
Show resolved Hide resolved

@Component({
selector: "nft-drop-mgr",
templateUrl: "./nft-drop-mgr.component.html",
})
export class NftDropMgrComponent implements OnInit {
static SHOWCASE_MANAGEMENT = "Manage Showcase";
static SHOWCASE_PREVIEW_TAB = "Showcase Preview";

@Input() activeTab = NftDropMgrComponent.SHOWCASE_MANAGEMENT;

globalVars: GlobalVarsService;

loading: boolean = false;
Expand Down Expand Up @@ -47,10 +53,52 @@ export class NftDropMgrComponent implements OnInit {

datasource: IDatasource<IAdapter<any>> = this.infiniteScroller.getDatasource();

constructor(private _globalVars: GlobalVarsService, private backendApi: BackendApiService) {
feedTabs = [NftDropMgrComponent.SHOWCASE_MANAGEMENT, NftDropMgrComponent.SHOWCASE_PREVIEW_TAB];
switchingTabs = false;

constructor(
private _globalVars: GlobalVarsService,
private backendApi: BackendApiService,
private router: Router,
private route: ActivatedRoute
) {
this.globalVars = _globalVars;
}

showShowcaseManagementTab() {
return (
this.activeTab === NftDropMgrComponent.SHOWCASE_MANAGEMENT &&
this.posts.length > 0 &&
(!this.loading || this.loadingNewDrop)
);
}

showShowcasePreviewTab() {
return (
this.activeTab === NftDropMgrComponent.SHOWCASE_PREVIEW_TAB &&
this.posts.length > 0 &&
(!this.loading || this.loadingNewDrop)
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should avoid using these functions to determine what should be shown. Instead, we should have a container div that is conditionally shown *ngIf="posts.length && (!loading || loadingNewDrop)", inside of which we show the showcase management *ngIf="activeTab === NftDropMgrComponent.SHOWCASE_MANAGEMENT" and show the preview *ngIf="activeTab === NftDropMgrComponent.SHOWCASE_PREVIEW_TAB"


_handleTabClick(tab: string) {
this.activeTab = tab;
this.router.navigate([], {
relativeTo: this.route,
queryParams: { feedTab: this.activeTab },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not call the query param feedTab. I think we call it feedTab in the feed component and this could cause some issues when merging queryParams.

queryParamsHandling: "merge",
});
this._onTabSwitch();
}

_onTabSwitch() {
// Delay rendering the posts for a hot second so nav is fast.
this.switchingTabs = true;
setTimeout(() => {
this.switchingTabs = false;
}, 0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... I don't think this is necessary?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you may be running into some weirdness with the uiScroll directive. I'll talk with you offline about it.


ngOnInit(): void {
// Get the latest NFT drop
this.loading = true;
Expand Down
2 changes: 1 addition & 1 deletion src/app/nft-showcase/nft-showcase.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</div>
</div>

<div *ngIf="!loading && !nftCollections || !nftCollections.length" class="d-flex align-items-center justify-content-center">
<div *ngIf="showcaseComingSoon()" class="d-flex align-items-center justify-content-center">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should avoid using functions for conditionals. ChangeDetection is faster for variables than it is for functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<div *ngIf="showcaseComingSoon()" class="d-flex align-items-center justify-content-center">
<div *ngIf="!loading && !nftCollections?.length" class="d-flex align-items-center justify-content-center">

with the ?, we have safe access so !(null)?.length is truthy and so is !([])?.length


<div class="d-flex flex-column align-items-center justify-content-center fc-muted fs-15px p-15px text-center" style="height: 400px;">
<div>The NFT Showcase is coming soon!</div>
Expand Down
49 changes: 46 additions & 3 deletions src/app/nft-showcase/nft-showcase.component.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { Component, OnInit } from "@angular/core";
import {Component, Input, OnInit} from "@angular/core";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import {Component, Input, OnInit} from "@angular/core";
import { Component, Input, OnInit } from "@angular/core";

import { BackendApiService, NFTCollectionResponse } from "../backend-api.service";
import { GlobalVarsService } from "../global-vars.service";
import { InfiniteScroller } from "../infinite-scroller";
import { IAdapter, IDatasource } from "ngx-ui-scroll";
import { has } from "lodash";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { has } from "lodash";


@Component({
selector: "nft-showcase",
templateUrl: "./nft-showcase.component.html",
})
export class NftShowcaseComponent implements OnInit {
@Input() showcaseIdx: number;

globalVars: GlobalVarsService;
loading: boolean = false;
nftCollections: NFTCollectionResponse[];
Expand All @@ -32,8 +35,11 @@ export class NftShowcaseComponent implements OnInit {
this.globalVars = _globalVars;
}

ngOnInit(): void {
this.loading = true;
showcaseComingSoon() {
return !this.loading && (!this.nftCollections || !has(this.nftCollections, length));
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should be able to kill this function and just use the constants to define the conditional

getCurrentShowcase() {
this.backendApi
.GetNFTShowcase(
this.globalVars.localNode,
Expand All @@ -57,6 +63,43 @@ export class NftShowcaseComponent implements OnInit {
});
}

getShowcaseByIdx(dropIdx) {
this.backendApi
.GetNFTShowcaseAdminPreview(
this.globalVars.localNode,
this.globalVars.loggedInUser?.PublicKeyBase58Check,
this.globalVars.loggedInUser?.PublicKeyBase58Check,
dropIdx
)
.subscribe(
(res: any) => {
this.nftCollections = res.NFTCollections;
if (this.nftCollections) {
this.nftCollections.sort((a, b) => b.HighestBidAmountNanos - a.HighestBidAmountNanos);
}
this.lastPage = Math.floor(this.nftCollections.length / NftShowcaseComponent.PAGE_SIZE);
},
(error) => {
this.globalVars._alertError(error.error.error);
}
)
.add(() => {
this.loading = false;
});
}

ngOnInit(): void {
console.log('Here is the showcase idx');
console.log(this.showcaseIdx);
console.log(this.showcaseIdx === undefined);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log('Here is the showcase idx');
console.log(this.showcaseIdx);
console.log(this.showcaseIdx === undefined);

this.loading = true;
if (this.showcaseIdx === undefined) {
this.getCurrentShowcase();
} else {
this.getShowcaseByIdx(this.showcaseIdx);
}
}

getPage(page: number) {
if (this.lastPage != null && page > this.lastPage) {
return [];
Expand Down