add reward rate + analytics link on channels page
This commit is contained in:
parent
65c39cbbc8
commit
4815aa9ff1
7 changed files with 87 additions and 3 deletions
|
@ -36,6 +36,7 @@ type Props = {
|
||||||
injectedItem: ?Node,
|
injectedItem: ?Node,
|
||||||
timedOutMessage?: Node,
|
timedOutMessage?: Node,
|
||||||
tileLayout?: boolean,
|
tileLayout?: boolean,
|
||||||
|
renderActions?: Claim => ?Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ClaimList(props: Props) {
|
export default function ClaimList(props: Props) {
|
||||||
|
@ -59,6 +60,7 @@ export default function ClaimList(props: Props) {
|
||||||
injectedItem,
|
injectedItem,
|
||||||
timedOutMessage,
|
timedOutMessage,
|
||||||
tileLayout = false,
|
tileLayout = false,
|
||||||
|
renderActions,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [currentSort, setCurrentSort] = usePersistedState(persistedStorageKey, SORT_NEW);
|
const [currentSort, setCurrentSort] = usePersistedState(persistedStorageKey, SORT_NEW);
|
||||||
|
@ -147,6 +149,7 @@ export default function ClaimList(props: Props) {
|
||||||
includeSupportAction={includeSupportAction}
|
includeSupportAction={includeSupportAction}
|
||||||
showUnresolvedClaim={showUnresolvedClaims}
|
showUnresolvedClaim={showUnresolvedClaims}
|
||||||
properties={renderProperties || (type !== 'small' ? undefined : false)}
|
properties={renderProperties || (type !== 'small' ? undefined : false)}
|
||||||
|
renderActions={renderActions}
|
||||||
showUserBlocked={showHiddenByUser}
|
showUserBlocked={showHiddenByUser}
|
||||||
hideBlock={hideBlock}
|
hideBlock={hideBlock}
|
||||||
customShouldHide={(claim: StreamClaim) => {
|
customShouldHide={(claim: StreamClaim) => {
|
||||||
|
|
|
@ -59,6 +59,8 @@ type Props = {
|
||||||
customShouldHide?: Claim => boolean,
|
customShouldHide?: Claim => boolean,
|
||||||
showUnresolvedClaim?: boolean,
|
showUnresolvedClaim?: boolean,
|
||||||
includeSupportAction?: boolean,
|
includeSupportAction?: boolean,
|
||||||
|
hideActions?: boolean,
|
||||||
|
renderActions?: Claim => ?Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
|
@ -91,12 +93,14 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
customShouldHide,
|
customShouldHide,
|
||||||
showUnresolvedClaim,
|
showUnresolvedClaim,
|
||||||
includeSupportAction,
|
includeSupportAction,
|
||||||
|
hideActions = false,
|
||||||
|
renderActions,
|
||||||
} = props;
|
} = props;
|
||||||
const shouldFetch =
|
const shouldFetch =
|
||||||
claim === undefined || (claim !== null && claim.value_type === 'channel' && isEmpty(claim.meta) && !pending);
|
claim === undefined || (claim !== null && claim.value_type === 'channel' && isEmpty(claim.meta) && !pending);
|
||||||
const abandoned = !isResolvingUri && !claim;
|
const abandoned = !isResolvingUri && !claim;
|
||||||
const showPublishLink = abandoned && !showUnresolvedClaim && placeholder === 'publish';
|
const showPublishLink = abandoned && !showUnresolvedClaim && placeholder === 'publish';
|
||||||
const hideActions = type === 'small' || type === 'tooltip';
|
const shouldHideActions = hideActions || type === 'small' || type === 'tooltip';
|
||||||
const canonicalUrl = claim && claim.canonical_url;
|
const canonicalUrl = claim && claim.canonical_url;
|
||||||
let isValid = false;
|
let isValid = false;
|
||||||
if (uri) {
|
if (uri) {
|
||||||
|
@ -286,7 +290,8 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
<div className="claim-preview__actions">
|
<div className="claim-preview__actions">
|
||||||
{!pending && (
|
{!pending && (
|
||||||
<>
|
<>
|
||||||
{hideActions ? null : actions !== undefined ? (
|
{renderActions && claim && renderActions(claim)}
|
||||||
|
{shouldHideActions || renderActions ? null : actions !== undefined ? (
|
||||||
actions
|
actions
|
||||||
) : (
|
) : (
|
||||||
<div className="claim-preview__primary-actions">
|
<div className="claim-preview__primary-actions">
|
||||||
|
|
|
@ -26,7 +26,7 @@ export default function CreatorAnalytics(props: Props) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const [stats, setStats] = React.useState();
|
const [stats, setStats] = React.useState();
|
||||||
const [error, setError] = React.useState();
|
const [error, setError] = React.useState();
|
||||||
const [fetchingStats, setFetchingStats] = React.useState(false);
|
const [fetchingStats, setFetchingStats] = React.useState(true);
|
||||||
const claimId = claim && claim.claim_id;
|
const claimId = claim && claim.claim_id;
|
||||||
const channelHasClaims = claim && claim.meta && claim.meta.claims_in_channel && claim.meta.claims_in_channel > 0;
|
const channelHasClaims = claim && claim.meta && claim.meta.claims_in_channel && claim.meta.claims_in_channel > 0;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
import { Lbryio } from 'lbryinc';
|
||||||
import ClaimList from 'component/claimList';
|
import ClaimList from 'component/claimList';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import YoutubeTransferStatus from 'component/youtubeTransferStatus';
|
import YoutubeTransferStatus from 'component/youtubeTransferStatus';
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
import Yrbl from 'component/yrbl';
|
import Yrbl from 'component/yrbl';
|
||||||
|
import LbcSymbol from 'component/common/lbc-symbol';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -19,6 +21,7 @@ type Props = {
|
||||||
|
|
||||||
export default function ChannelsPage(props: Props) {
|
export default function ChannelsPage(props: Props) {
|
||||||
const { channels, channelUrls, fetchChannelListMine, fetchingChannels, youtubeChannels } = props;
|
const { channels, channelUrls, fetchChannelListMine, fetchingChannels, youtubeChannels } = props;
|
||||||
|
const [rewardData, setRewardData] = React.useState();
|
||||||
const hasYoutubeChannels = youtubeChannels && Boolean(youtubeChannels.length);
|
const hasYoutubeChannels = youtubeChannels && Boolean(youtubeChannels.length);
|
||||||
const hasPendingChannels = channels && channels.some(channel => channel.confirmations < 0);
|
const hasPendingChannels = channels && channels.some(channel => channel.confirmations < 0);
|
||||||
|
|
||||||
|
@ -26,6 +29,10 @@ export default function ChannelsPage(props: Props) {
|
||||||
fetchChannelListMine();
|
fetchChannelListMine();
|
||||||
}, [fetchChannelListMine, hasPendingChannels]);
|
}, [fetchChannelListMine, hasPendingChannels]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
Lbryio.call('user_rewards', 'view_rate').then(data => setRewardData(data));
|
||||||
|
}, [setRewardData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<div className="card-stack">
|
<div className="card-stack">
|
||||||
|
@ -44,6 +51,44 @@ export default function ChannelsPage(props: Props) {
|
||||||
}
|
}
|
||||||
loading={fetchingChannels}
|
loading={fetchingChannels}
|
||||||
uris={channelUrls}
|
uris={channelUrls}
|
||||||
|
renderActions={claim => {
|
||||||
|
const claimsInChannel = claim.meta.claims_in_channel;
|
||||||
|
return claimsInChannel === 0 ? (
|
||||||
|
<span />
|
||||||
|
) : (
|
||||||
|
<div className="section__actions">
|
||||||
|
<Button
|
||||||
|
button="alt"
|
||||||
|
icon={ICONS.ANALYTICS}
|
||||||
|
label={__('Analytics')}
|
||||||
|
navigate={`/$/${PAGES.CREATOR_DASHBOARD}?channel=${encodeURIComponent(claim.canonical_url)}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
renderProperties={claim => {
|
||||||
|
const claimsInChannel = claim.meta.claims_in_channel;
|
||||||
|
if (!claim || claimsInChannel === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channelRewardData =
|
||||||
|
rewardData &&
|
||||||
|
rewardData.rates.find(data => {
|
||||||
|
return data.channel_claim_id === claim.claim_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (channelRewardData) {
|
||||||
|
return (
|
||||||
|
<span className="claim-preview__custom-properties">
|
||||||
|
<span className="help--inline">{__('Earnings per view')}</span>
|
||||||
|
<LbcSymbol postfix={channelRewardData.view_rate.toFixed(2)} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,14 +8,23 @@ import CreatorAnalytics from 'component/creatorAnalytics';
|
||||||
import ChannelSelector from 'component/channelSelector';
|
import ChannelSelector from 'component/channelSelector';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
import Yrbl from 'component/yrbl';
|
import Yrbl from 'component/yrbl';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
channels: Array<ChannelClaim>,
|
channels: Array<ChannelClaim>,
|
||||||
fetchingChannels: boolean,
|
fetchingChannels: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SELECTED_CHANNEL_QUERY_PARAM = 'channel';
|
||||||
|
|
||||||
export default function CreatorDashboardPage(props: Props) {
|
export default function CreatorDashboardPage(props: Props) {
|
||||||
const { channels, fetchingChannels } = props;
|
const { channels, fetchingChannels } = props;
|
||||||
|
const {
|
||||||
|
push,
|
||||||
|
location: { search, pathname },
|
||||||
|
} = useHistory();
|
||||||
|
const urlParams = new URLSearchParams(search);
|
||||||
|
const channelFromUrl = urlParams.get(SELECTED_CHANNEL_QUERY_PARAM);
|
||||||
const [selectedChannelUrl, setSelectedChannelUrl] = usePersistedState('analytics-selected-channel');
|
const [selectedChannelUrl, setSelectedChannelUrl] = usePersistedState('analytics-selected-channel');
|
||||||
const hasChannels = channels && channels.length > 0;
|
const hasChannels = channels && channels.length > 0;
|
||||||
const firstChannel = hasChannels && channels[0];
|
const firstChannel = hasChannels && channels[0];
|
||||||
|
@ -33,6 +42,19 @@ export default function CreatorDashboardPage(props: Props) {
|
||||||
}
|
}
|
||||||
}, [setSelectedChannelUrl, selectedChannelUrl, firstChannelUrl, channelFoundForSelectedChannelUrl]);
|
}, [setSelectedChannelUrl, selectedChannelUrl, firstChannelUrl, channelFoundForSelectedChannelUrl]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (channelFromUrl) {
|
||||||
|
const decodedChannel = decodeURIComponent(channelFromUrl);
|
||||||
|
setSelectedChannelUrl(decodedChannel);
|
||||||
|
}
|
||||||
|
}, [channelFromUrl, setSelectedChannelUrl]);
|
||||||
|
|
||||||
|
function updateUrl(channelUrl) {
|
||||||
|
const newUrlParams = new URLSearchParams();
|
||||||
|
newUrlParams.append(SELECTED_CHANNEL_QUERY_PARAM, encodeURIComponent(channelUrl));
|
||||||
|
push(`${pathname}?${newUrlParams.toString()}`);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
{fetchingChannels && (
|
{fetchingChannels && (
|
||||||
|
@ -59,6 +81,7 @@ export default function CreatorDashboardPage(props: Props) {
|
||||||
<ChannelSelector
|
<ChannelSelector
|
||||||
selectedChannelUrl={selectedChannelUrl}
|
selectedChannelUrl={selectedChannelUrl}
|
||||||
onChannelSelect={newChannelUrl => {
|
onChannelSelect={newChannelUrl => {
|
||||||
|
updateUrl(newChannelUrl);
|
||||||
setSelectedChannelUrl(newChannelUrl);
|
setSelectedChannelUrl(newChannelUrl);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -200,6 +200,10 @@
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.claim-preview__custom-properties {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
.claim-preview-metadata {
|
.claim-preview-metadata {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
@ -230,6 +230,10 @@ textarea {
|
||||||
@extend .help;
|
@extend .help;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.help--card-actions {
|
.help--card-actions {
|
||||||
|
|
Loading…
Add table
Reference in a new issue