Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Commit

Permalink
Support review activity
Browse files Browse the repository at this point in the history
  • Loading branch information
kikakkz committed Dec 7, 2023
1 parent c447780 commit 3acf790
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 0 deletions.
66 changes: 66 additions & 0 deletions webui/src/components/ReviewActivities.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<q-table
:rows='activities'
:columns='(columns as never)'
@row-click='(_evt, row, _index) => onActivityClick(row as Activity)'
/>
</template>

<script setup lang='ts'>
import { Activity, useReviewStore } from 'src/stores/review'
import { computed } from 'vue'
import { useUserStore } from 'src/stores/user'
import { useRouter } from 'vue-router'
import { useFoundationStore } from 'src/stores/foundation'
import { Cookies } from 'quasar'
import { useActivityStore } from 'src/stores/activity'
const review = useReviewStore()
const activities = computed(() => Array.from(review.activityApplications.values()) || [])
const user = useUserStore()
const account = computed(() => user.account)
const router = useRouter()
const foundation = useFoundationStore()
const estimatedReward = computed(() => Number(foundation.reviewRewardBalance) / foundation.reviewRewardFactor)
const port = computed(() => Cookies.get('service-port'))
const activity = useActivityStore()
const columns = computed(() => [
{
name: 'ActivityID',
label: 'Activity ID',
field: (row: Activity) => row.activityId
}, {
name: 'Title',
label: 'Title',
field: (row: Activity) => activity.activity(row.activityId)?.title
}, {
name: 'Approved',
label: 'Approved',
field: (row: Activity) => row.approved
}, {
name: 'Rejected',
label: 'Rejected',
field: (row: Activity) => row.rejected
}, {
name: 'Estimated Reward',
label: 'Estimated Reward',
field: (row: Activity) => review.activityReviewed(row.activityId, account.value) ? '-' : estimatedReward.value.toString() + ' Lineras'
}, {
name: 'Reviewed',
label: 'Reviewed',
field: (row: Activity) => review.activityReviewed(row.activityId, account.value)
}
])
const onActivityClick = (activity: Activity) => {
void router.push({
path: '/reviewactivity',
query: {
activityId: activity.activityId,
port: port.value
}
})
}
</script>
138 changes: 138 additions & 0 deletions webui/src/components/ReviewActivity.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<template>
<div class='row'>
<q-space />
<div :style='{maxWidth:"960px"}'>
<div class='row' :style='{margin:"16px 0"}'>
<div class='row cursor-pointer' :style='{lineHeight:"32px"}' @click='onBackClick'>
<q-icon name='arrow_back' size='32px' />
<span :style='{marginLeft:"8px"}'>{{ $t('MSG_REVIEW_ACTIVITY') }}</span>
</div>
<q-space />
<div class='row' :style='{lineHeight:"32px"}'>
<span><strong>{{ _activity?.title }}</strong></span>
</div>
</div>
<q-separator />
<div v-if='_activity' :style='{marginTop:"24px"}'>
<activity-card :activity='(_activity as Activity)' />
</div>
<q-separator />
<div :style='{marginTop: "24px"}'>
<q-input v-model='reason' type='textarea' :label='$t("MSG_REVIEW_REASON")' :disable='reviewed' />
</div>
<div :style='{marginTop: "24px"}' class='row'>
<q-btn :label='$t("MSG_APPROVE")' :style='{marginRight:"16px",color: _review?.approved ? "blue" : ""}' @click='onApproveClick' :disable='reviewed' />
<q-btn :label='$t("MSG_REJECT")' :style='{color: _review && !_review?.approved ? "red" : ""}' @click='onRejectClick' :disable='reviewed' />
</div>
</div>
<q-space />
</div>
</template>

<script lang='ts' setup>
import { useReviewStore } from 'src/stores/review'
import { computed, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Cookies } from 'quasar'
import { provideApolloClient, useMutation } from '@vue/apollo-composable'
import gql from 'graphql-tag'
import { getClientOptions } from 'src/apollo'
import { ApolloClient } from '@apollo/client/core'
import { targetChain } from 'src/stores/chain'
import { useUserStore } from 'src/stores/user'
import { Activity, useActivityStore } from 'src/stores/activity'

import ActivityCard from './ActivityCard.vue'

interface Query {
activityId: number
}

const route = useRoute()
const activityId = computed(() => (route.query as unknown as Query).activityId)
const activity = useActivityStore()
const _activity = computed(() => activity.activity(Number(activityId.value)))
const review = useReviewStore()
const activityApplication = computed(() => review.activity(Number(activityId.value)))
const options = /* await */ getClientOptions(/* {app, router ...} */)
const apolloClient = new ApolloClient(options)
const router = useRouter()
const user = useUserStore()
const account = computed(() => user.account)
const reviewed = computed(() => review.activityReviewed(Number(activityId.value), account.value))
const _review = computed(() => review.activityReview(Number(activityId.value), account.value))
const reason = ref(_review.value?.reason || 'I supper like this activity, it will promote liquidity of Linera')
const port = computed(() => Cookies.get('service-port'))

const onApproveClick = async () => {
if (!activityApplication.value || !reason.value.length) {
return
}

const { mutate, onDone, onError } = provideApolloClient(apolloClient)(() => useMutation(gql`
mutation approveActivity($activityId: Int!, $reason: String!) {
approveActivity(activityId: $activityId, reason: $reason)
}
`))
onDone(() => {
// TODO
})
onError((error) => {
console.log(error)
})
await mutate({
activityId,
reason: reason.value,
endpoint: 'review',
chainId: targetChain.value
})
void router.push({
path: '/',
query: {
port: port.value
}
})
}

const onRejectClick = async () => {
if (!activityApplication.value || !reason.value.length) {
return
}

const { mutate, onDone, onError } = provideApolloClient(apolloClient)(() => useMutation(gql`
mutation rejectActivity ($activityId: Int!, $reason: String!) {
rejectActivity(activityId: $activityId, reason: $reason)
}
`))
onDone(() => {
// TODO
})
onError((error) => {
console.log(error)
})
await mutate({
activityId,
reason: reason.value,
endpoint: 'review',
chainId: targetChain.value
})
void router.push({
path: '/dashboard',
query: {
tab: 'review-activities',
port: port.value
}
})
}

const onBackClick = () => {
void router.push({
path: '/dashboard',
query: {
tab: 'review-activities',
port: port.value
}
})
}

</script>
5 changes: 5 additions & 0 deletions webui/src/pages/DashboardPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<q-tab v-if='reviewer' name='review-contents' label='Review Content' />
<q-tab v-if='reviewer' name='review-assets' label='Review Asset' />
<q-tab v-if='reviewer' name='review-reviewers' label='Review Reviewer' />
<q-tab v-if='reviewer' name='review-activities' label='Review Activity' />
<q-tab v-if='!reviewer' name='apply-reviewer' label='Apply Reviewer' />
<q-tab name='foundation' label='Foundation' />
<q-tab name='activity' label='Activity' />
Expand Down Expand Up @@ -77,6 +78,9 @@
<q-tab-panel name='review-reviewers'>
<review-reviewers />
</q-tab-panel>
<q-tab-panel name='review-activities'>
<review-activities />
</q-tab-panel>
<q-tab-panel name='credits'>
<user-balance />
</q-tab-panel>
Expand Down Expand Up @@ -135,6 +139,7 @@ import ContentApplicationList from 'src/components/ContentApplicationList.vue'
import AssetApplicationList from 'src/components/AssetApplicationList.vue'
import FoundationPage from 'src/components/FoundationPage.vue'
import ActivityPage from 'src/components/ActivityPage.vue'
import ReviewActivities from 'src/components/ReviewActivities.vue'

interface Query {
tab: string
Expand Down
7 changes: 7 additions & 0 deletions webui/src/pages/ReviewActivity.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<template>
<review-activity />
</template>

<script lang='ts' setup>
import ReviewActivity from 'src/components/ReviewActivity.vue'
</script>
1 change: 1 addition & 0 deletions webui/src/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const routes: RouteRecordRaw[] = [
{ path: 'reviewcontent', component: () => import('pages/ReviewContent.vue') },
{ path: 'reviewasset', component: () => import('pages/ReviewAsset.vue') },
{ path: 'reviewreviewer', component: () => import('pages/ReviewReviewer.vue') },
{ path: 'reviewactivity', component: () => import('pages/ReviewActivity.vue') },
{ path: 'content', component: () => import('pages/ContentPage.vue') },
{ path: 'create/activity', component: () => import('pages/CreateActivity.vue') },
{ path: 'activities', component: () => import('pages/ActivitiesPage.vue') },
Expand Down
16 changes: 16 additions & 0 deletions webui/src/stores/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export const useReviewStore = defineStore('review', {
return this.contentApplications.get(cid)
}
},
activity (): (id: number) => Activity | undefined {
return (id: number) => {
return this.activityApplications.get(id)
}
},
contents (): (author?: string) => Array<Content> {
return (author?: string) => {
const contents = [] as Array<Content>
Expand Down Expand Up @@ -137,6 +142,17 @@ export const useReviewStore = defineStore('review', {
const asset = this.reviewerApplications.get(cid)
return asset?.reviewers[owner]
}
},
activityReviewed (): (id: number, owner: string) => boolean {
return (id: number, owner: string) => {
return Object.keys(this.activityApplications.get(id)?.reviewers || {})?.find((el) => el === owner) !== undefined
}
},
activityReview (): (id: number, owner: string) => Review | undefined {
return (id: number, owner: string) => {
const activity = this.activityApplications.get(id)
return activity?.reviewers[owner]
}
}
},
actions: {}
Expand Down

0 comments on commit 3acf790

Please sign in to comment.