mirror of
https://github.com/logos-storage/ethcc-demo.git
synced 2026-01-05 06:33:12 +00:00
Add storage request detail view
This commit is contained in:
parent
6a55e88fc5
commit
552cc2705b
12
src/App.vue
12
src/App.vue
@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useEventsStore } from '@/stores/events'
|
||||
import { onBeforeMount, onMounted, ref } from 'vue'
|
||||
import { useRequestsStore } from '@/stores/requests'
|
||||
import { RouterView } from 'vue-router'
|
||||
import Balance from '@/components/Balance.vue'
|
||||
import BlockNumber from '@/components/BlockNumber.vue'
|
||||
@ -10,7 +10,7 @@ import { initDrawers } from 'flowbite'
|
||||
|
||||
const alerts = ref([])
|
||||
const id = ref(0)
|
||||
const eventsStore = useEventsStore()
|
||||
const requestsStore = useRequestsStore()
|
||||
|
||||
function addAlert(type, event, state) {
|
||||
alerts.value.push({
|
||||
@ -35,9 +35,11 @@ function addSlotAlert(type, event, state) {
|
||||
})
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {})
|
||||
|
||||
onMounted(async () => {
|
||||
await requestsStore.fetch()
|
||||
initDrawers()
|
||||
await eventsStore.fetchPastEvents()
|
||||
|
||||
function onStorageRequested(blockNumber, requestId, request, state) {
|
||||
alerts.value.push({
|
||||
@ -104,7 +106,7 @@ onMounted(async () => {
|
||||
state: 'Filled'
|
||||
})
|
||||
}
|
||||
await eventsStore.listenForNewEvents(
|
||||
await requestsStore.listenForNewEvents(
|
||||
onStorageRequested,
|
||||
onRequestFulfilled,
|
||||
onRequestCancelled,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { inject, ref, onMounted } from 'vue'
|
||||
import { inject, ref, onMounted, computed } from 'vue'
|
||||
import { initModals } from 'flowbite'
|
||||
import SpinnerLoading from '@/components/SpinnerLoading.vue'
|
||||
|
||||
@ -13,10 +13,8 @@ defineOptions({
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
// Required string
|
||||
cid: {
|
||||
type: String,
|
||||
required: true
|
||||
type: [String, undefined]
|
||||
},
|
||||
localOnly: {
|
||||
// only try downloading from the local node
|
||||
@ -25,8 +23,12 @@ const props = defineProps({
|
||||
},
|
||||
alt: String
|
||||
})
|
||||
const hidden = computed(() => props.cid === undefined)
|
||||
|
||||
onMounted(async () => {
|
||||
if (hidden.value) {
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
@ -52,7 +54,7 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-center">
|
||||
<div v-if="!hidden" class="text-center">
|
||||
<SpinnerLoading v-if="loading" />
|
||||
<div v-else-if="error" v-bind="$attrs" class="dark:bg-orange-700 dark:text-orange-200">
|
||||
<svg
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { initModals } from 'flowbite'
|
||||
import { useEventsStore } from '@/stores/events'
|
||||
import { useRequestsStore } from '@/stores/requests'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const eventsStore = useEventsStore()
|
||||
const requestsStore = useRequestsStore()
|
||||
|
||||
// const ethProvider = inject('ethProvider')
|
||||
// const marketplace = inject('marketplace')
|
||||
@ -45,8 +45,8 @@ const eventsStore = useEventsStore()
|
||||
// })
|
||||
// }
|
||||
// onMounted(async () => {
|
||||
// await eventsStore.fetchPastEvents()
|
||||
// await eventsStore.listenForNewEvents()
|
||||
// await requestsStore.fetch()
|
||||
// await requestsStore.listenForNewEvents()
|
||||
// })
|
||||
// let storageRequestedFilter = marketplace.filters.StorageRequested
|
||||
// marketplace.on(storageRequestedFilter, async (requestId, ask, expiry, event) => {
|
||||
@ -103,14 +103,14 @@ const eventsStore = useEventsStore()
|
||||
|
||||
// })
|
||||
// console.log(await ethProvider.getBlockNumber())
|
||||
const { requests } = storeToRefs(eventsStore)
|
||||
const { requests } = storeToRefs(requestsStore)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <span>asdf{{ blockNumber.value }}</span> -->
|
||||
<!-- <span>Yo yo yo yo yo {{ blockNumber }}</span> -->
|
||||
<ul class="requests">
|
||||
<!-- <li v-for="(request, idx) in eventsStore.requests" :key="{requestId}"> WORKS! -->
|
||||
<!-- <li v-for="(request, idx) in requestsStore.requests" :key="{requestId}"> WORKS! -->
|
||||
<li v-for="([requestId, { request, state }], idx) in requests" :key="{ requestId }">
|
||||
{{ idx }}.
|
||||
<div>CID: {{ request[2][0] }}</div>
|
||||
|
||||
97
src/components/StorageRequest.vue
Normal file
97
src/components/StorageRequest.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { price } from '@/utils/requests'
|
||||
|
||||
import CodexImage from '@/components/CodexImage.vue'
|
||||
import { shortHex } from '@/utils/ids'
|
||||
|
||||
const props = defineProps({
|
||||
requestId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
request: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const totalPrice = computed(() => price(props.request))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex">
|
||||
<CodexImage class="flex-2" :cid="props.request.content.cid"></CodexImage>
|
||||
<div class="py-8 px-4 mx-auto max-w-2xl lg:py-16">
|
||||
<h2 class="mb-2 text-xl font-semibold leading-none text-gray-900 md:text-2xl dark:text-white">
|
||||
{{ shortHex(requestId) }}
|
||||
</h2>
|
||||
<p class="mb-4 text-xl font-extrabold leading-none text-gray-900 md:text-2xl dark:text-white">
|
||||
{{ totalPrice }} CDX
|
||||
</p>
|
||||
<dl>
|
||||
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">Dataset CID</dt>
|
||||
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
|
||||
{{ request.content.cid }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="flex items-center space-x-6">
|
||||
<div>
|
||||
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">Expiry</dt>
|
||||
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
|
||||
{{ request.expiry }}s
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">Duration</dt>
|
||||
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
|
||||
{{ request.ask.duration }}s
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="flex items-center space-x-4">
|
||||
<button
|
||||
type="button"
|
||||
class="text-white inline-flex items-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="mr-1 -ml-1 w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z"
|
||||
></path>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center text-white bg-red-600 hover:bg-red-700 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-red-500 dark:hover:bg-red-600 dark:focus:ring-red-900"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="w-5 h-5 mr-1.5 -ml-1"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -1,13 +1,15 @@
|
||||
<script setup>
|
||||
import { inject, ref, onMounted, computed } from 'vue'
|
||||
import { initModals } from 'flowbite'
|
||||
import { useEventsStore } from '@/stores/events'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRequestsStore } from '@/stores/requests'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import CodexImage from '@/components/CodexImage.vue'
|
||||
import { shortHex } from '@/utils/ids'
|
||||
|
||||
const eventsStore = useEventsStore()
|
||||
const { requests } = storeToRefs(eventsStore)
|
||||
const requestsStore = useRequestsStore()
|
||||
const { requests } = storeToRefs(requestsStore)
|
||||
const router = useRouter()
|
||||
|
||||
function getStateColour(state) {
|
||||
if (state === 'New') {
|
||||
@ -119,9 +121,13 @@ function getStateColour(state) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative overflow-x-auto overflow-y-auto max-h-screen shadow-md sm:rounded-lg">
|
||||
<div
|
||||
class="relative overflow-x-auto overflow-y-auto max-h-screen shadow-md sm:rounded-lg border-t border-gray-50"
|
||||
>
|
||||
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
<thead
|
||||
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"
|
||||
>
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3">RequestID</th>
|
||||
<th scope="col" class="px-6 py-3">CID</th>
|
||||
@ -131,9 +137,10 @@ function getStateColour(state) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="([requestId, { request, state }], idx) in requests"
|
||||
v-for="([requestId, { content, state }], idx) in requests"
|
||||
:key="{ requestId }"
|
||||
class="bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-600"
|
||||
class="cursor-pointer bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-600"
|
||||
@click="router.push(`/request/${requestId}`)"
|
||||
>
|
||||
<th
|
||||
scope="row"
|
||||
@ -141,19 +148,15 @@ function getStateColour(state) {
|
||||
>
|
||||
<CodexImage
|
||||
:local-only="!['New', 'Fulfilled'].includes(state)"
|
||||
:cid="request[2][0]"
|
||||
:cid="content.cid"
|
||||
class="w-10 h-10 rounded-full mt-1"
|
||||
/>
|
||||
<!-- class="w-10 h-10 rounded-full"
|
||||
src="/docs/images/people/profile-picture-4.jpg"
|
||||
alt="Jese image"
|
||||
/> -->
|
||||
<div class="ps-3">
|
||||
<div class="text-base font-semibold">{{ shortHex(requestId) }}</div>
|
||||
<div class="font-normal text-gray-500">leslie@flowbite.com</div>
|
||||
</div>
|
||||
</th>
|
||||
<td class="px-6 py-4">{{ shortHex(request[2][0]) }}</td>
|
||||
<td class="px-6 py-4">{{ shortHex(content.cid) }}</td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center">
|
||||
<div :class="`h-2.5 w-2.5 rounded-full ${getStateColour(state)} me-2`"></div>
|
||||
@ -165,189 +168,13 @@ function getStateColour(state) {
|
||||
<a
|
||||
href="#"
|
||||
type="button"
|
||||
data-modal-show="editUserModal"
|
||||
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
|
||||
>Edit user</a
|
||||
>View details</a
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Edit user modal -->
|
||||
<div
|
||||
id="editUserModal"
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
class="fixed top-0 left-0 right-0 z-50 items-center justify-center hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full"
|
||||
>
|
||||
<div class="relative w-full max-w-2xl max-h-full">
|
||||
<!-- Modal content -->
|
||||
<form class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||
<!-- Modal header -->
|
||||
<div class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">Details</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
|
||||
data-modal-hide="editUserModal"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 14 14"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">Close modal</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Modal body -->
|
||||
<div class="p-6 space-y-6">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="first-name"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>First Name</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
name="first-name"
|
||||
id="first-name"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Bonnie"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="last-name"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>Last Name</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
name="last-name"
|
||||
id="last-name"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Green"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="email"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>Email</label
|
||||
>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="example@company.com"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="phone-number"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>Phone Number</label
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
name="phone-number"
|
||||
id="phone-number"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="e.g. +(12)3456 789"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="department"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>Department</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
name="department"
|
||||
id="department"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Development"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="company"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>Company</label
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
name="company"
|
||||
id="company"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="123456"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="current-password"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>Current Password</label
|
||||
>
|
||||
<input
|
||||
type="password"
|
||||
name="current-password"
|
||||
id="current-password"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="••••••••"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label
|
||||
for="new-password"
|
||||
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
>New Password</label
|
||||
>
|
||||
<input
|
||||
type="password"
|
||||
name="new-password"
|
||||
id="new-password"
|
||||
class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="••••••••"
|
||||
required=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal footer -->
|
||||
<div
|
||||
class="flex items-center p-6 space-x-3 rtl:space-x-reverse border-t border-gray-200 rounded-b dark:border-gray-600"
|
||||
>
|
||||
<button
|
||||
type="submit"
|
||||
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
|
||||
>
|
||||
Save all
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import RequestsView from '../views/RequestsView.vue'
|
||||
import RequestView from '../views/RequestView.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@ -16,6 +17,12 @@ const router = createRouter({
|
||||
// this generates a separate chunk (About.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('../views/SlotsView.vue')
|
||||
},
|
||||
{
|
||||
path: '/request/:requestId',
|
||||
name: 'request',
|
||||
component: RequestView,
|
||||
props: true // pass :requestId to props in RequestView
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { ref, computed, inject } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { slotId } from '../utils/ids'
|
||||
import { arrayToObject } from '@/utils/requests'
|
||||
|
||||
export const useEventsStore = defineStore('events', () => {
|
||||
export const useRequestsStore = defineStore('request', () => {
|
||||
// let fetched = false
|
||||
const marketplace = inject('marketplace')
|
||||
const ethProvider = inject('ethProvider')
|
||||
let {
|
||||
@ -24,6 +26,8 @@ export const useEventsStore = defineStore('events', () => {
|
||||
// const requestFailedEvents = ref([]) // {blockNumber, requestId}
|
||||
// const requestFinishedEvents = ref([]) // {blockNumber, requestId}
|
||||
const loading = ref(false)
|
||||
const fetched = ref(false)
|
||||
// const request = computed(() => count.value * 2)
|
||||
|
||||
// onStorageRequested => add request to requests ref, along with slots
|
||||
// => add to storageRequestedEvents {blockNumber, requestId}
|
||||
@ -59,10 +63,8 @@ export const useEventsStore = defineStore('events', () => {
|
||||
return requestState[stateIdx]
|
||||
}
|
||||
|
||||
const getSlots = async (requestId, request) => {
|
||||
const getSlots = async (requestId, numSlots) => {
|
||||
// storageRequestedEvents.value.push({ blockNumber, requestId })
|
||||
let ask = request[1]
|
||||
let numSlots = ask[0]
|
||||
let slots = []
|
||||
for (let i = 0; i < numSlots; i++) {
|
||||
let id = slotId(requestId, i)
|
||||
@ -73,7 +75,11 @@ export const useEventsStore = defineStore('events', () => {
|
||||
// blockNumbers.value.add(blockNumber)
|
||||
}
|
||||
|
||||
async function fetchPastEvents() {
|
||||
async function fetch() {
|
||||
// if (fetched) {
|
||||
// // allow multiple calls without re-fetching
|
||||
// return
|
||||
// }
|
||||
// query past events
|
||||
loading.value = true
|
||||
try {
|
||||
@ -81,11 +87,12 @@ export const useEventsStore = defineStore('events', () => {
|
||||
pastRequests.forEach(async (event) => {
|
||||
let { requestId, ask, expiry } = event.args
|
||||
// let { blockNumber } = event
|
||||
let request = await marketplace.getRequest(requestId)
|
||||
let arrRequest = await marketplace.getRequest(requestId)
|
||||
let request = arrayToObject(arrRequest)
|
||||
let state = await getRequestState(requestId)
|
||||
let slots = getSlots(requestId, request)
|
||||
let slots = await getSlots(requestId, request.ask.slots)
|
||||
requests.value.set(requestId, {
|
||||
request,
|
||||
...request,
|
||||
state,
|
||||
slots,
|
||||
requestFinishedId: null
|
||||
@ -95,6 +102,7 @@ export const useEventsStore = defineStore('events', () => {
|
||||
console.error(`failed to load past contract events: ${error.message}`)
|
||||
} finally {
|
||||
loading.value = false
|
||||
fetched.value = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +225,6 @@ export const useEventsStore = defineStore('events', () => {
|
||||
// function increment() {
|
||||
// count.value++
|
||||
// }
|
||||
|
||||
return {
|
||||
requests,
|
||||
// slots,
|
||||
@ -229,8 +236,9 @@ export const useEventsStore = defineStore('events', () => {
|
||||
// requestCancelledEvents,
|
||||
// requestFailedEvents,
|
||||
// requestFinishedEvents,
|
||||
fetchPastEvents,
|
||||
fetch,
|
||||
listenForNewEvents,
|
||||
loading
|
||||
loading,
|
||||
fetched
|
||||
}
|
||||
})
|
||||
30
src/utils/requests.js
Normal file
30
src/utils/requests.js
Normal file
@ -0,0 +1,30 @@
|
||||
export function arrayToObject(arrRequest) {
|
||||
let { client, ask, content, expiry, nonce } = arrRequest
|
||||
let { slots, slotSize, duration, proofProbability, reward, collateral, maxSlotLoss } = ask
|
||||
let { cid, merkleRoot } = content
|
||||
return {
|
||||
client,
|
||||
ask: {
|
||||
slots,
|
||||
slotSize,
|
||||
duration,
|
||||
proofProbability,
|
||||
reward,
|
||||
collateral,
|
||||
maxSlotLoss
|
||||
},
|
||||
content: {
|
||||
cid,
|
||||
merkleRoot
|
||||
},
|
||||
expiry,
|
||||
nonce
|
||||
}
|
||||
}
|
||||
|
||||
export function price(request) {
|
||||
if (!request) {
|
||||
return 0
|
||||
}
|
||||
return request.ask.reward * request.ask.duration * request.ask.slots
|
||||
}
|
||||
27
src/views/RequestView.vue
Normal file
27
src/views/RequestView.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRequestsStore } from '@/stores/requests'
|
||||
import { useRoute } from 'vue-router'
|
||||
import StorageRequest from '@/components/StorageRequest.vue'
|
||||
import SkeletonLoading from '@/components/SkeletonLoading.vue'
|
||||
|
||||
const requestsStore = useRequestsStore()
|
||||
const { requests, loading, fetched } = storeToRefs(requestsStore)
|
||||
const isLoading = computed(() =>
|
||||
!fetched.value ||
|
||||
loading.value ||
|
||||
!requests.value ||
|
||||
requests.value.size === 0 ||
|
||||
!requests.value.has(route.params.requestId)
|
||||
)
|
||||
const request = computed(() => requests?.value?.get(route.params.requestId) )
|
||||
const route = useRoute()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<SkeletonLoading v-if="isLoading" type="image" />
|
||||
<StorageRequest v-else :requestId="route.params.requestId" :request="request" />
|
||||
</div>
|
||||
</template>
|
||||
@ -1,16 +1,20 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEventsStore } from '@/stores/events'
|
||||
import { useRequestsStore } from '@/stores/requests'
|
||||
import StorageRequests from '@/components/StorageRequests.vue'
|
||||
import SkeletonLoading from '@/components/SkeletonLoading.vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const eventsStore = useEventsStore()
|
||||
const { loading } = storeToRefs(eventsStore)
|
||||
const requestsStore = useRequestsStore()
|
||||
const { loading, fetched, requests } = storeToRefs(requestsStore)
|
||||
const isLoading = computed(
|
||||
() => loading.value || !fetched.value || !requests.value || requests.value?.size === 0
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<SkeletonLoading v-if="loading" type="image" />
|
||||
<SkeletonLoading v-if="isLoading" type="text" />
|
||||
<StorageRequests v-else />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user