-
-
Notifications
You must be signed in to change notification settings - Fork 364
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
✨ Collection Activity Tab #5345
Merged
Merged
Changes from 7 commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
829f7b5
feat: collection activity chart
daiagi b030b79
remove controls on activity tab
daiagi 66b19b8
feat: holders tab
daiagi 9c9c32b
Merge branch 'main' of https://github.com/kodadot/nft-gallery into co…
daiagi ef606dd
feat: flippers tab
daiagi a0f5b6f
control chart height
daiagi 71dd950
finish owners insights
daiagi 6693f98
reponsivity
daiagi 7b6de3b
feat: events table
daiagi 76b7fa0
touch up events table
daiagi 01eb816
Merge branch 'main' of https://github.com/kodadot/nft-gallery into co…
daiagi 3557ecd
feat: add offers to event table
daiagi 78e7c13
Merge branch 'main' of https://github.com/kodadot/nft-gallery into co…
daiagi dfd86b1
implement design review
daiagi d350989
responsivity
daiagi e1381e7
clear deepScan deepSource issues
daiagi 733cd16
link on nft avatar in mobile
daiagi c9b0661
feat: filters
daiagi 3cfec0f
cleanups, touchups
daiagi 27b6e3b
attempt1 to fix chart responsivity
daiagi 8caac91
visual touchups
daiagi 6300597
attempt to fix / improve chart resize issue
daiagi 6f579f2
fix deepSource issues
daiagi bd27a34
fix wrong to addres for send interaction
daiagi ba37fd5
fix
daiagi 4e28e88
Update components/collection/utils/useCollectionActivity.ts
daiagi 5d6eee6
use one ref for toggling vue
daiagi d07cd73
Merge branch 'collection-activity-tab' of https://github.com/daiagi/n…
daiagi be33938
fix visual issues
daiagi ee0bf80
remove price filter on collection activity
daiagi c1dcf38
fixed breadcrumbs margin
daiagi 6c9e08c
code styling issue
daiagi 293b09b
toggle event row with resizeObserver
daiagi 991e12a
remove a console log
daiagi 8bcb8c3
clip flip profit to 4 digits
daiagi d2a9b12
sensible chart (rolling avg of a day)
daiagi a96e365
deepSource fix
daiagi 90dd650
trim price digits in chart
daiagi afdbcf0
rmrk2 fix
daiagi 5a9091b
Merge branch 'main' into collection-activity-tab
daiagi e6be07b
touch up flippers profit display
daiagi 8146906
Merge branch 'collection-activity-tab' of https://github.com/daiagi/n…
daiagi 433df89
simplify timeAgo function using date-fns
daiagi 5e97419
remove 'set'
daiagi a424df1
fix timeAgo
daiagi 40bceba
use 'has-text-grey'
daiagi b6a53de
move useREplaceUrl to composables
daiagi 5489b24
remove duplicate css, renaming
daiagi e87fc36
move function to utils, rename Chart to ActivityChart
daiagi 3216601
extract some function out of getOwners, getFlippers
daiagi 7e22d7f
remove few lines from getFlippers
daiagi ccd9b10
remove some more lines from getOwners
daiagi d338ea0
Merge branch 'main' of https://github.com/kodadot/nft-gallery into co…
daiagi 5ad06c4
@vikiival update pnpm veriosn to 8 in package.json
daiagi 09ca4b5
undo update pnpm veriosn to 8 in package.json
daiagi fe7eb4f
Merge branch 'collection-activity-tab' of https://github.com/daiagi/n…
daiagi b6603c8
undo pnpm version update
daiagi f6133cb
better organize useCollectionActivityCode
daiagi 5c18cd3
Merge branch 'main' into collection-activity-tab
daiagi 0d04e7a
clear deepSource
daiagi a415e3d
Merge branch 'collection-activity-tab' of https://github.com/daiagi/n…
daiagi a4cfdaf
Merge branch 'main' into collection-activity-tab
daiagi 8078664
move useCollectionActivity to composables
daiagi b2a744f
Merge branch 'main' of https://github.com/kodadot/nft-gallery into co…
daiagi 158db8a
resolve some code review
daiagi d3b5cab
Merge branch 'collection-activity-tab' of https://github.com/daiagi/n…
daiagi 2c9caa6
delete format file
daiagi 9f4865d
removed negative margin
daiagi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<template> | ||
<div class="is-flex is-align-self-flex-start"> | ||
<SidebarFilter /> | ||
<div class="w-full mt-5"> | ||
<div class="columns"> | ||
<div class="column is-two-thirds"> | ||
<ActivityChart :events="events" /> | ||
</div> | ||
<div class="column"> | ||
<OwnerInsights :owners="owners" :flippers="flippers" /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import SidebarFilter from '@/components/explore/SidebarFilter.vue' | ||
import ActivityChart from './Chart.vue' | ||
import OwnerInsights from './OwnerInsights.vue' | ||
|
||
import { useCollectionActivity } from '@/components/collection/utils/useCollectionDetails' | ||
const route = useRoute() | ||
|
||
const collectionId = computed(() => route.params.id) | ||
const { events, flippers, owners } = useCollectionActivity({ | ||
collectionId: collectionId.value, | ||
}) | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
@import '@/styles/abstracts/variables'; | ||
|
||
.fixed-height { | ||
height: 350px; | ||
} | ||
</style> | ||
a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<template> | ||
<GalleryItemChart :nft-events="events" chart-height="350px" /> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ActivityInteraction } from '@/components/rmrk/service/scheme' | ||
|
||
defineProps<{ | ||
events?: ActivityInteraction[] | ||
}>() | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<template> | ||
<div class="fixed-height border"> | ||
<div class="py-4 px-5 is-flex border-bottom" aria-label="controls"> | ||
<div | ||
class="mr-4 is-clickable" | ||
:class="{ 'has-text-weight-bold': activeTab === Tabs.Holders }" | ||
@click="activeTab = Tabs.Holders"> | ||
{{ $t('holders') }} | ||
</div> | ||
<div | ||
class="is-clickable" | ||
:class="{ 'has-text-weight-bold': activeTab === Tabs.Flippers }" | ||
@click="activeTab = Tabs.Flippers"> | ||
{{ $t('flippers') }} | ||
</div> | ||
</div> | ||
<div class="py-4 px-5 limit-height is-scrollable"> | ||
<HoldersTab v-if="activeTab === Tabs.Holders" :owners="owners" /> | ||
<FlippersTab v-if="activeTab === Tabs.Flippers" :flippers="flippers" /> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import HoldersTab from './holdersFlippersTabs/HolderTab.vue' | ||
import FlippersTab from './holdersFlippersTabs/FlipperTab.vue' | ||
import { Flippers, Owners } from '@/components/collection/utils/types' | ||
|
||
enum Tabs { | ||
Holders, | ||
Flippers, | ||
} | ||
|
||
defineProps<{ | ||
owners?: Owners | ||
flippers?: Flippers | ||
}>() | ||
const activeTab = ref(Tabs.Holders) | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
@import '@/styles/abstracts/variables'; | ||
|
||
.fixed-height { | ||
height: 350px; | ||
} | ||
.limit-height { | ||
max-height: 290px; | ||
} | ||
.is-scrollable { | ||
overflow-y: auto; | ||
} | ||
</style> |
123 changes: 123 additions & 0 deletions
123
components/collection/activity/holdersFlippersTabs/FlipperTab.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
<template> | ||
<div> | ||
<div | ||
v-for="[ | ||
flipperId, | ||
{ bestFlip, owned, totalBought, totalsold, latestflipTimestamp, flips }, | ||
] in flippers" | ||
:key="flipperId" | ||
class="hide-last-hr"> | ||
<div class="is-flex is-flex-direction-column gap"> | ||
<ProfileLink :address="flipperId" /> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.owned') }}</span> | ||
<span>{{ owned }}</span> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.totalBought') }}</span> | ||
<Money :value="totalBought" /> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.totalSold') }}</span> | ||
<Money :value="totalsold" /> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.bestFlip') }}</span> | ||
<span :class="{ 'k-green': bestFlip > 0, 'k-red': bestFlip < 0 }">{{ | ||
bestFlip === 0 ? '--' : `${bestFlip}%` | ||
}}</span> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ | ||
$t('activity.latestActivity') | ||
}}</span> | ||
<span class="no-wrap">{{ timeAgo(latestflipTimestamp) }}</span> | ||
</div> | ||
<div> | ||
<div | ||
class="is-size-7 k-blue is-clickable" | ||
@click="toggleNFTDetails(flipperId)"> | ||
{{ $t('activity.nftDetails') }} | ||
<NeoIcon | ||
:icon=" | ||
isNFTDetailsOpen[flipperId] ? 'chevron-down' : 'chevron-right' | ||
" /> | ||
</div> | ||
|
||
<div v-if="isNFTDetailsOpen[flipperId]"> | ||
<MoreNFTS :flips="flips" variant="Flippers" /> | ||
</div> | ||
</div> | ||
</div> | ||
<hr class="my-3" /> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { Flippers } from '@/components/collection/utils/types' | ||
import ProfileLink from '@/components/rmrk/Profile/ProfileLink.vue' | ||
import Money from '@/components/shared/format/ChainMoney.vue' | ||
import { NeoIcon } from '@kodadot1/brick' | ||
import { set } from 'vue' | ||
|
||
import MoreNFTS from './moreNFTS.vue' | ||
import { timeAgo } from '../utils' | ||
|
||
const toggleNFTDetails = (flipperId: string) => { | ||
const isOpen = isNFTDetailsOpen.value[flipperId] | ||
set(isNFTDetailsOpen.value, flipperId, !isOpen) | ||
} | ||
|
||
const flippers = computed(() => Object.entries(props.flippers || {})) | ||
|
||
// map of flipper id to bolean, is the NFT details section of that flipper open or nor | ||
// {id0: false, id1: true, id3: false, ...} | ||
const isFlipperMoreNFTSectionOpen = flippers.value.reduce( | ||
(accumelator, [holderId, _]) => ({ | ||
...accumelator, | ||
[holderId]: false, | ||
}), | ||
{} | ||
) | ||
const isNFTDetailsOpen = ref(isFlipperMoreNFTSectionOpen) | ||
|
||
const props = defineProps<{ | ||
flippers?: Flippers | ||
}>() | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
@import '@/styles/abstracts/variables'; | ||
.gap { | ||
gap: 0.5rem; | ||
} | ||
.hide-last-hr:last-child > hr { | ||
display: none; | ||
} | ||
.k-blue { | ||
@include ktheme() { | ||
color: theme('k-blue'); | ||
} | ||
&:hover { | ||
@include ktheme() { | ||
color: theme('k-blue-hover'); | ||
} | ||
} | ||
} | ||
.k-grey { | ||
@include ktheme() { | ||
color: theme('k-grey'); | ||
} | ||
} | ||
.k-green { | ||
@include ktheme() { | ||
color: theme('k-green'); | ||
} | ||
} | ||
.k-red { | ||
@include ktheme() { | ||
color: theme('k-red'); | ||
} | ||
} | ||
</style> |
104 changes: 104 additions & 0 deletions
104
components/collection/activity/holdersFlippersTabs/HolderTab.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<template> | ||
<div> | ||
<div | ||
v-for="[holderId, holdings] in holders" | ||
:key="holderId" | ||
class="hide-last-hr"> | ||
<div class="is-flex is-flex-direction-column gap"> | ||
<ProfileLink :address="holderId" /> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.owned') }}</span> | ||
<span>{{ holdings.nftCount }}</span> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.totalBought') }}</span> | ||
<Money :value="holdings.totalBought" /> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.totalSold') }}</span> | ||
<Money v-if="holdings.totalSold > 0" :value="holdings.totalSold" /> | ||
<span v-else>--</span> | ||
</div> | ||
<div class="is-flex is-justify-content-space-between"> | ||
<span class="is-size-7 k-grey">{{ $t('activity.date') }}</span> | ||
<span>{{ timeAgo(holdings.lastActivityTimestamp) }}</span> | ||
</div> | ||
<div> | ||
<div | ||
class="is-size-7 k-blue is-clickable" | ||
@click="toggleNFTDetails(holderId)"> | ||
{{ $t('activity.nftDetails') }} | ||
<NeoIcon | ||
:icon=" | ||
isNFTDetailsOpen[holderId] ? 'chevron-down' : 'chevron-right' | ||
" /> | ||
</div> | ||
|
||
<div v-if="isNFTDetailsOpen[holderId]"> | ||
<MoreNFTS :holder-nfts="holdings.nfts" variant="Holders" /> | ||
</div> | ||
</div> | ||
</div> | ||
<hr class="my-3" /> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import ProfileLink from '@/components/rmrk/Profile/ProfileLink.vue' | ||
import { Owners } from '@/components/collection/utils/types' | ||
import Money from '@/components/shared/format/ChainMoney.vue' | ||
import { NeoIcon } from '@kodadot1/brick' | ||
import { set } from 'vue' | ||
|
||
import MoreNFTS from './moreNFTS.vue' | ||
import { timeAgo } from '../utils' | ||
|
||
const toggleNFTDetails = (holderId: string) => { | ||
const isOpen = isNFTDetailsOpen.value[holderId] | ||
set(isNFTDetailsOpen.value, holderId, !isOpen) | ||
} | ||
|
||
const holders = computed(() => Object.entries(props.owners || {})) | ||
|
||
// map of owner id to bolean, is the NFT details section of that owner open or nor | ||
// {id0: false, id1: true, id3: false, ...} | ||
const isNFTDetailsOpen = ref( | ||
holders.value.reduce( | ||
(isOpen, [holderId, _]) => ({ | ||
...isOpen, | ||
[holderId]: false, | ||
}), | ||
{} | ||
) | ||
) | ||
|
||
const props = defineProps<{ | ||
owners?: Owners | ||
}>() | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
@import '@/styles/abstracts/variables'; | ||
.gap { | ||
gap: 0.5rem; | ||
} | ||
.hide-last-hr:last-child > hr { | ||
display: none; | ||
} | ||
.k-blue { | ||
@include ktheme() { | ||
color: theme('k-blue'); | ||
} | ||
&:hover { | ||
@include ktheme() { | ||
color: theme('k-blue-hover'); | ||
} | ||
} | ||
} | ||
.k-grey { | ||
@include ktheme() { | ||
color: theme('k-grey'); | ||
} | ||
} | ||
</style> |
24 changes: 24 additions & 0 deletions
24
components/collection/activity/holdersFlippersTabs/moreNFTS.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<template> | ||
daiagi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<div> | ||
<Holder v-if="variant === 'Holders'" :nfts="holderNfts" /> | ||
<Flipper v-else :flips="flips" /> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { FlipEvent, NFTExcludingEvents } from '../../utils/types' | ||
import Flipper from './moreNFTs/Flipper.vue' | ||
import Holder from './moreNFTs/Holder.vue' | ||
|
||
withDefaults( | ||
defineProps<{ | ||
variant: 'Holders' | 'Flippers' | ||
holderNfts?: NFTExcludingEvents[] | ||
flips?: FlipEvent[] | ||
}>(), | ||
{ | ||
holderNfts: () => [], | ||
flips: () => [], | ||
} | ||
) | ||
</script> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use relative imports (starting with @)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but Actvity.vue and Chart (renames to ActivityChart to be more clear) are in the same dir.
isn't this acceptable in that case?