Skip to content

Commit

Permalink
NFT UI
Browse files Browse the repository at this point in the history
  • Loading branch information
1aerostorm committed Oct 8, 2023
1 parent cc3352d commit fa68dad
Show file tree
Hide file tree
Showing 34 changed files with 2,595 additions and 57 deletions.
12 changes: 10 additions & 2 deletions app/ResolveRoute.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
export const routeRegex = {
UserProfile1: /^\/(@[\w\.\d-]+)\/?$/,
UserProfile2: /^\/(@[\w\.\d-]+)\/(transfers|assets|create-asset|invites|curation-rewards|author-rewards|donates-from|donates-to|filled-orders|permissions|created|password|witness|settings)\/??(?:&?[^=&]*=[^=&]*)*$/,
UserProfile2: /^\/(@[\w\.\d-]+)\/(transfers|assets|create-asset|invites|curation-rewards|author-rewards|donates-from|donates-to|nft-history|nft-tokens|nft-collections|filled-orders|permissions|created|password|witness|settings)\/??(?:&?[^=&]*=[^=&]*)*$/,
UserProfile3: /^\/(@[\w\.\d-]+)\/[\w\.\d-]+/,
UserAssetEndPoints: /^\/(@[\w\.\d-]+)\/assets\/([\w\d.-]+)\/(update|transfer)$/,
UserEndPoints: /^(transfers|assets|create-asset|invites|curation-rewards|author-rewards|donates-from|donates-to|filled-orders|permissions|created|password|witness|settings)$/,
UserEndPoints: /^(transfers|assets|create-asset|invites|curation-rewards|author-rewards|donates-from|donates-to|nft-history|nft-tokens|nft-collections|filled-orders|permissions|created|password|witness|settings)$/,
WorkerSort: /^\/workers\/([\w\d\-]+)\/?($|\?)/,
WorkerSearchByAuthor: /^\/workers\/([\w\d\-]+)\/(\@[\w\d.-]+)\/?($|\?)/,
WorkerRequest: /^\/workers\/([\w\d\-]+)\/(\@[\w\d.-]+)\/([\w\d-]+)\/?($|\?)/,
MarketPair: /^\/market\/([\w\d\.]+)\/([\w\d.]+)\/?($|\?)/,
ConvertPair: /^\/convert\/([\w\d\.]+)\/([\w\d.]+)\/?($|\?)/,
NFTMarket: /^\/nft\/([\w\d\.]+)\/?($|\?)/,
UserJson: /^\/(@[\w\.\d-]+)(\.json)$/,
UserNameJson: /^.*(?=(\.json))/
};
Expand Down Expand Up @@ -89,5 +90,12 @@ export default function resolveRoute(path)
if (match) {
return {page: 'ConvertAssetsPage', params: match.slice(1)}
}
if (path === '/nft') {
return {page: 'NFTMarketPage'}
}
match = path.match(routeRegex.NFTMarket);
if (match) {
return {page: 'NFTMarketPage', params: match.slice(1)}
}
return {page: 'NotFound'};
}
2 changes: 2 additions & 0 deletions app/RootRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export default {
cb(null, [require('@pages/UserProfile')]);
} else if (route.page === 'ConvertAssetsPage') {
cb(null, [require('@pages/ConvertAssetsPage')]);
} else if (route.page === 'NFTMarketPage') {
cb(null, [require('@pages/NFTMarketPage')]);
} else if (route.page === 'Market') {
cb(null, [require('@pages/MarketLoader')]);
} else if (route.page === 'Rating') {
Expand Down
Binary file added app/assets/images/nft.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions app/components/all.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
@import "./elements/market/MarketPair";
@import "./elements/market/OrderForm";
@import "./elements/market/TickerPriceStat";
@import "./elements/nft/NFTSmallIcon";
@import "./elements/workers/WorkerRequestVoting";

// dialogs
Expand Down Expand Up @@ -67,6 +68,12 @@
@import "./modules/Powerdown.scss";
@import "./modules/QuickBuy.scss";
@import "./modules/Modals";
@import "./modules/nft/NFTCollections";
@import "./modules/nft/CreateNFTCollection";
@import "./modules/nft/IssueNFTToken";
@import "./modules/nft/NFTTokens";
@import "./modules/nft/NFTTokenTransfer";
@import "./modules/nft/NFTTokenDetails";

// pages
@import "./pages/Exchanges";
Expand Down
77 changes: 74 additions & 3 deletions app/components/cards/TransferHistoryRow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,38 @@ class TransferHistoryRow extends React.Component {
/* all transfers involve up to 2 accounts, context and 1 other. */
let description_start = "";
let link = null, linkTitle = null, linkExternal = false
let description_middle = ''
let link2 = null, linkTitle2 = null, linkExternal2 = false
let description_middle2 = ''
let link3 = null, linkTitle3 = null, linkExternal3 = false
let code_key = "";
let description_end = "";
let link4 = null, linkTitle4 = null, linkExternal4 = false
let target_hint = "";
let data_memo = data.memo;

const getToken = (token_id) => {
const { nft_tokens } = this.props
let tokenLink
let tokenTitle
const token = nft_tokens && nft_tokens.toJS()[data.token_id]
if (token) {
try {
const meta = JSON.parse(token.json_metadata)
tokenTitle = meta.title
if (meta.image) {
tokenLink = <a href={meta.image} target='_blank' rel='noopener noreferrer'>{tokenTitle}</a>
}
} catch (err) {
console.error(err)
}
}
if (!tokenTitle) {
tokenTitle = '#' + data.token_id
}
return { tokenTitle, tokenLink }
}

if (/^transfer$|^transfer_to_savings$|^transfer_from_savings$/.test(type)) {
const fromWhere =
type === 'transfer_to_savings' ? tt('transferhistoryrow_jsx.to_savings') :
Expand Down Expand Up @@ -312,12 +339,52 @@ class TransferHistoryRow extends React.Component {
} else {
code_key = JSON.stringify({type, ...data}, null, 2);
}
} else if (type === 'nft_token') {
link = data.creator
description_middle = tt('transferhistoryrow_jsx.nft_issued') + tt('transferhistoryrow_jsx.nft_token') + ' '
const { tokenTitle, tokenLink } = getToken(data.token_id)
link2 = tokenLink
if (!link2) {
description_middle += tokenTitle
}
linkExternal2 = true
if (data.creator !== data.to) {
description_middle2 += tt('transferhistoryrow_jsx.nft_issued_for')
link3 = data.to
}
description_end = ', ' + tt('transferhistoryrow_jsx.nft_issued_cost') + Asset(data.issue_cost).floatString
} else if (type === 'nft_transfer') {
if (this.props.context === data.from) {
if (data.to === 'null') {
description_end += tt('transferhistoryrow_jsx.burnt') + ' '
description_end += tt('transferhistoryrow_jsx.nft_token')
} else {
description_start += tt('transferhistoryrow_jsx.you_gifted0') + ' '
link = data.to
description_end += tt('transferhistoryrow_jsx.you_gifted') + ': '
description_end += tt('transferhistoryrow_jsx.nft_token')
}
} else {
link = data.from
description_end += ' ' + tt('transferhistoryrow_jsx.gifted') + ' '
description_end += tt('transferhistoryrow_jsx.nft_token')
}
const { tokenTitle, tokenLink } = getToken(data.token_id)
link4 = tokenLink
linkExternal4 = true
description_end += ' ' + (!link4 ? tokenTitle : '')
}

else {
code_key = JSON.stringify({type, ...data}, null, 2);
}

const wrapLink = (href, title, isExternal) => {
return (isExternal ?
<a href={href} target='_blank' rel='noreferrer noopener'>{title || href}</a> :
<Link to={`/@${href}`}>{title || href}</Link>)
}

return(
<tr key={op[0]} className="Trans">
<td style={{fontSize: "85%"}}>
Expand All @@ -328,10 +395,13 @@ class TransferHistoryRow extends React.Component {
<td className="TransferHistoryRow__text" style={{maxWidth: "35rem"}}>
{description_start}
{code_key && <span style={{fontSize: "85%"}}>{code_key}</span>}
{link && (linkExternal ?
<a href={link} target='_blank' rel='noreferrer noopener'>{linkTitle || link}</a> :
<Link to={`/@${link}`}>{linkTitle || link}</Link>)}
{link && wrapLink(link, linkTitle, linkExternal)}
{description_middle}
{link2 && wrapLink(link2, linkTitle2, linkExternal2)}
{description_middle2}
{link3 && wrapLink(link3, linkTitle3, linkExternal3)}
{description_end}
{link4 && wrapLink(link4, linkTitle4, linkExternal4)}
{target_hint && <span style={{fontSize: "85%", padding: "5px"}}>[{target_hint}]</span>}
</td>
<td className="show-for-medium" style={{maxWidth: "25rem", wordWrap: "break-word", fontSize: "85%"}}>
Expand All @@ -358,6 +428,7 @@ export default connect(
username,
curation_reward,
author_reward,
nft_tokens: state.global.get('nft_token_map')
}
},
)(TransferHistoryRow)
4 changes: 2 additions & 2 deletions app/components/elements/DropdownMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ export default class DropdownMenu extends React.Component {
}

render() {
const {el, items, selected, children, className, title, href, noArrow} = this.props;
const {el, items, selected, children, className, title, href, onClick, noArrow} = this.props;
const hasDropdown = items.length > 0

let entry = children || <span key='label'>
{this.getSelectedLabel(items, selected)}
{hasDropdown && !noArrow && <Icon name="dropdown-arrow" />}
</span>

if(hasDropdown) entry = <a key="entry" href={href || '#'} onClick={this.toggle}>{entry}</a>
if(hasDropdown) entry = <a key="entry" href={href || '#'} onClick={onClick ? (e) => { onClick(e); this.toggle(e) } : this.toggle}>{entry}</a>

const menu = <VerticalMenu key="menu" title={title} items={items} hideValue={selected} className="VerticalMenu" />;
const cls = 'DropdownMenu' + (this.state.shown ? ' show' : '') + (className ? ` ${className}` : '')
Expand Down
4 changes: 2 additions & 2 deletions app/components/elements/Expandable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ class Expandable extends Component {
};

render() {
const { title, } = this.props;
const { title, ...rest } = this.props;
const { opened, } = this.state;
return (<div className={'Expandable' + (opened ? ' opened' : '')}>
return (<div className={'Expandable' + (opened ? ' opened' : '')} {...rest}>
<div className='Expander' onClick={this.onToggleExpander}>
<Icon name={opened ? 'chevron-up-circle' : 'chevron-down-circle'} size='2x' />
<h5 style={{ paddingLeft: '0.5rem', }}>{title}</h5>
Expand Down
17 changes: 15 additions & 2 deletions app/components/elements/Memo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { connect, } from 'react-redux';
import tt from 'counterpart';
import { memo, } from 'golos-lib-js';
import { Link, } from 'react-router';
import links from 'app/utils/Links';

import links from 'app/utils/Links'
import shouldComponentUpdate from 'app/utils/shouldComponentUpdate'
import { validate_account_name, } from 'app/utils/ChainValidation'
import user from 'app/redux/User';
import user from 'app/redux/User'
import { blogsUrl } from 'app/utils/blogsUtils'

class Memo extends React.Component {
static propTypes = {
Expand Down Expand Up @@ -36,6 +38,17 @@ class Memo extends React.Component {
const sections = []
let idx = 0
if (!text || (typeof text.split !== 'function')) return
const isNftPost = text.startsWith('Post: ')
const isNftComment = !isNftPost && text.startsWith('Comment: ')
if (isNftPost || isNftComment) {
sections.push((isNftPost ? tt('g.for_the_post') : tt('g.for_the_comment')) + ': ')
const link = text.split(' ')[1]
let linkText = link
const truncateText = isNftPost ? 50 : 40
if (linkText.length > truncateText) linkText = linkText.substr(0, truncateText) + '...'
sections.push(<a key={idx++} href={blogsUrl(link)} target='_blank' rel='nofollow noreferrer'>{linkText}&nbsp;</a>)
return sections
}
for (let section of text.split(' ')) {
if (section.trim().length === 0) continue
const matchUserName = section.match(/(^|\s)(@[a-z][-\.a-z\d]+[a-z\d])/i)
Expand Down
12 changes: 12 additions & 0 deletions app/components/elements/nft/NFTSmallIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { Component, } from 'react'

class NFTSmallIcon extends Component {
render() {
const { image, ...rest } = this.props

return <a className='NFTSmallIcon'
style={{ backgroundImage: `url(${image})` }} href={image} target='_blank' rel='nofollow noreferrer' {...rest}></a>
}
}

export default NFTSmallIcon
11 changes: 11 additions & 0 deletions app/components/elements/nft/NFTSmallIcon.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.NFTSmallIcon {
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
border-radius: 50%;

width: 3rem;
height: 3rem;
display: inline-block;
vertical-align: top;
}
22 changes: 13 additions & 9 deletions app/components/modules/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,27 @@ class Header extends React.Component {
const name = acct_meta ? normalizeProfile(acct_meta.toJS()).name : null;
const user_title = name ? `${name} (@${user_name})` : user_name;
page_title = user_title;
if(route.params[1] === "curation-rewards"){
if (route.params[1] === "curation-rewards"){
page_title = tt('header_jsx.curation_rewards_by') + " " + user_title;
}
if(route.params[1] === "author-rewards"){
} else if (route.params[1] === "author-rewards"){
page_title = tt('header_jsx.author_rewards_by') + " " + user_title;
}
if(route.params[1] === "donates-from"){
} else if (route.params[1] === "donates-from"){
page_title = tt('header_jsx.donates_from') + " " + user_title;
}
if(route.params[1] === "donates-to"){
} else if (route.params[1] === "donates-to"){
page_title = tt('header_jsx.donates_to') + " " + user_title;
}
if(route.params[1] === "recent-replies"){
} else if (route.params[1] === "recent-replies"){
page_title = tt('header_jsx.replies_to') + " " + user_title;
} else if (route.params[1] === "nft-tokens"){
page_title = tt('header_jsx.nft_tokens') + " " + user_title
} else if (route.params[1] === "nft-collections"){
page_title = tt('header_jsx.nft_collections') + " " + user_title
} else if (route.params[1] === "nft-history"){
page_title = tt('g.nft_history') + " " + user_title
}
} else if (route.page === 'ConvertAssetsPage') {
page_title = tt('g.convert_assets')
} else if (route.page === `NFTMarketPage`){
page_title = tt('header_jsx.nft_market')
} else {
page_name = ''; //page_title = route.page.replace( /([a-z])([A-Z])/g, '$1 $2' ).toLowerCase();
}
Expand Down
Loading

0 comments on commit fa68dad

Please sign in to comment.