diff --git a/src/main.js b/src/main.js
index 5f615b2..acfcef7 100644
--- a/src/main.js
+++ b/src/main.js
@@ -2,6 +2,7 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import uniqueId from '@/plugins/UniqueIdPlugin'
import App from '@/App.vue'
@@ -15,7 +16,10 @@ import './index.css'
const app = createApp(App)
-app.use(createPinia())
+const pinia = createPinia()
+pinia.use(piniaPluginPersistedstate)
+
+app.use(pinia)
app.use(router)
const environments = {
localhost: {
diff --git a/src/router/index.js b/src/router/index.js
index 18ff99c..321a475 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
import RequestsView from '../views/RequestsView.vue'
import RequestView from '../views/RequestView.vue'
import NotFoundView from '../views/NotFoundView.vue'
+import ModerateView from '../views/ModerateView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -29,6 +30,11 @@ const router = createRouter({
path: '/404',
name: 'NotFound',
component: NotFoundView
+ },
+ {
+ path: '/moderate',
+ name: 'Moderate',
+ component: ModerateView
}
]
})
diff --git a/src/stores/requests.js b/src/stores/requests.js
index f604bb1..a0aee6c 100644
--- a/src/stores/requests.js
+++ b/src/stores/requests.js
@@ -4,286 +4,370 @@ import { slotId } from '../utils/ids'
import { arrayToObject, requestState } from '@/utils/requests'
import { slotState } from '@/utils/slots'
-export const useRequestsStore = defineStore('request', () => {
- // let fetched = false
- const marketplace = inject('marketplace')
- const ethProvider = inject('ethProvider')
- let {
- StorageRequested,
- RequestFulfilled,
- RequestCancelled,
- RequestFailed,
- SlotFilled,
- SlotFreed
- } = marketplace.filters
- const requests = ref(new Map()) // key: requestId, val: {request, state, slots: [{slotId, slotIdx, state}]}
- // const slots = ref(new Map()) // key: slotId, val: {requestId, slotIdx, state}
- // const blockNumbers = ref(new Set()) // includes blocks that had events
- // const storageRequestedEvents = ref([]) // {blockNumber, requestId}
- // const slotFilledEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
- // const slotFreedEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
- // const requestFulfilledEvents = ref([]) // {blockNumber, requestId}
- // const requestCancelledEvents = ref([]) // {blockNumber, requestId}
- // const requestFailedEvents = ref([]) // {blockNumber, requestId}
- // const requestFinishedEvents = ref([]) // {blockNumber, requestId}
- const loading = ref(false)
- const blocks = ref(new Map())
- // const request = computed(() => count.value * 2)
+class RequestNotFoundError extends Error {
+ constructor(requestId, ...params) {
+ // Pass remaining arguments (including vendor specific ones) to parent constructor
+ super(...params)
- // onStorageRequested => add request to requests ref, along with slots
- // => add to storageRequestedEvents {blockNumber, requestId}
- // => add blockNumber to blockNumbers
- // onRequestFulfilled => update requests[requestId].state with marketplace.getRequestState(requestId)
- // => add to requestStartedEvents {blockNumber, requestId}
- // => add blockNumber to blockNumbers
- // onRequestCancelled => update requests[requestId].state with marketplace.getRequestState(requestId)
- // => add to requestCancelledEvents {blockNumber, requestId}
- // => add blockNumber to blockNumbers
- // onRequestFailed => update requests[requestId].state with marketplace.getRequestState(requestId)
- // => add to requestFailedEvents {blockNumber, requestId}
- // => add blockNumber to blockNumbers
- // onRequestFinished => update requests[requestId].state with marketplace.getRequestState(requestId)
- // => add to requestFinishedEvents {blockNumber, requestId}
- // => add blockNumber to blockNumbers
- // onSlotFilled => update request.slots[slotId].state with getSlotState
- // => add to slotFilledEvents {blockNumber, slotId, slotIdx}
- // => add blockNumber to blockNumbers
- // onSlotFreed => update slots[slotId].state with getSlotState
- // => add to slotFreedEvents {blockNumber, slotId, slotIdx}
- // => add blockNumber to blockNumbers
-
- const getRequestState = async (requestId) => {
- let stateIdx = await marketplace.requestState(requestId)
- return requestState[stateIdx]
- }
-
- const getSlotState = async (slotId) => {
- let stateIdx = await marketplace.slotState(slotId)
- return slotState[stateIdx]
- }
-
- const getSlots = async (requestId, numSlots) => {
- console.log(`fetching ${numSlots} slots`)
- let start = Date.now()
- let slots = []
- for (let slotIdx = 0; slotIdx < numSlots; slotIdx++) {
- let id = slotId(requestId, slotIdx)
- const startSlotState = Date.now()
- let state = await getSlotState(id)
- console.log(`fetched slot state in ${(Date.now() - startSlotState) / 1000}s`)
- const startGetHost = Date.now()
- let provider = await marketplace.getHost(id)
- console.log(`fetched slot provider in ${(Date.now() - startGetHost) / 1000}s`)
- slots.push({ slotId: id, slotIdx, state, provider })
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(this, RequestNotFoundError)
}
- console.log(`fetched ${numSlots} slots in ${(Date.now() - start) / 1000}s`)
- return slots
- // blockNumbers.value.add(blockNumber)
- }
- const getBlock = async (blockHash) => {
- if (blocks.value.has(blockHash)) {
- return blocks.value.get(blockHash)
- } else {
- let block = await ethProvider.getBlock(blockHash)
- blocks.value.set(blockHash, block)
- return block
+ this.name = 'RequestNotFoundError'
+ // Custom debugging information
+ this.requestId = requestId
+ }
+}
+
+export const useRequestsStore = defineStore(
+ 'requests',
+ () => {
+ // let fetched = false
+ const marketplace = inject('marketplace')
+ const ethProvider = inject('ethProvider')
+ let {
+ StorageRequested,
+ RequestFulfilled,
+ RequestCancelled,
+ RequestFailed,
+ SlotFilled,
+ SlotFreed
+ } = marketplace.filters
+ const requests = ref({}) // key: requestId, val: {request, state, slots: [{slotId, slotIdx, state}]}
+ // const slots = ref(new Map()) // key: slotId, val: {requestId, slotIdx, state}
+ // const blockNumbers = ref(new Set()) // includes blocks that had events
+ // const storageRequestedEvents = ref([]) // {blockNumber, requestId}
+ // const slotFilledEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
+ // const slotFreedEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
+ // const requestFulfilledEvents = ref([]) // {blockNumber, requestId}
+ // const requestCancelledEvents = ref([]) // {blockNumber, requestId}
+ // const requestFailedEvents = ref([]) // {blockNumber, requestId}
+ // const requestFinishedEvents = ref([]) // {blockNumber, requestId}
+ const loading = ref(false)
+ const fetched = ref(false) // indicates if past events were fetched
+ const blocks = ref({})
+
+ // const request = computed(() => count.value * 2)
+
+ // onStorageRequested => add request to requests ref, along with slots
+ // => add to storageRequestedEvents {blockNumber, requestId}
+ // => add blockNumber to blockNumbers
+ // onRequestFulfilled => update requests[requestId].state with marketplace.getRequestState(requestId)
+ // => add to requestStartedEvents {blockNumber, requestId}
+ // => add blockNumber to blockNumbers
+ // onRequestCancelled => update requests[requestId].state with marketplace.getRequestState(requestId)
+ // => add to requestCancelledEvents {blockNumber, requestId}
+ // => add blockNumber to blockNumbers
+ // onRequestFailed => update requests[requestId].state with marketplace.getRequestState(requestId)
+ // => add to requestFailedEvents {blockNumber, requestId}
+ // => add blockNumber to blockNumbers
+ // onRequestFinished => update requests[requestId].state with marketplace.getRequestState(requestId)
+ // => add to requestFinishedEvents {blockNumber, requestId}
+ // => add blockNumber to blockNumbers
+ // onSlotFilled => update request.slots[slotId].state with getSlotState
+ // => add to slotFilledEvents {blockNumber, slotId, slotIdx}
+ // => add blockNumber to blockNumbers
+ // onSlotFreed => update slots[slotId].state with getSlotState
+ // => add to slotFreedEvents {blockNumber, slotId, slotIdx}
+ // => add blockNumber to blockNumbers
+
+ const getRequestState = async (requestId) => {
+ let stateIdx = await marketplace.requestState(requestId)
+ return requestState[stateIdx]
}
- }
- async function addRequest(requestId, blockHash) {
- let state = await getRequestState(requestId)
- let block = await getBlock(blockHash)
- let reqExisting = requests.value.get(requestId) // just in case it already exists
- let request = {
- ...reqExisting,
- state,
- requestedAt: block.timestamp,
- requestFinishedId: null,
- detailsFetched: false
+ const getSlotState = async (slotId) => {
+ let stateIdx = await marketplace.slotState(slotId)
+ return slotState[stateIdx]
}
- requests.value.set(requestId, request)
- return request
- }
- async function fetchPastRequests() {
- // query past events
- console.log('fetching past requests')
- loading.value = true
- try {
- let events = await marketplace.queryFilter(StorageRequested)
- console.log('got ', events.length, ' StorageRequested events')
- events.forEach(async (event, i) => {
- console.log('getting details for StorageRequested event ', i)
- let start = Date.now()
- let { requestId, ask, expiry } = event.args
- let { blockHash, blockNumber } = event
- await addRequest(requestId, blockHash)
- console.log(`got details for ${i} in ${(Date.now() - start) / 1000} seconds`)
- if (i === events.length - 1) {
+ const getSlots = async (requestId, numSlots) => {
+ console.log(`fetching ${numSlots} slots`)
+ let start = Date.now()
+ let slots = []
+ for (let slotIdx = 0; slotIdx < numSlots; slotIdx++) {
+ let id = slotId(requestId, slotIdx)
+ const startSlotState = Date.now()
+ let state = await getSlotState(id)
+ console.log(`fetched slot state in ${(Date.now() - startSlotState) / 1000}s`)
+ const startGetHost = Date.now()
+ let provider = await marketplace.getHost(id)
+ console.log(`fetched slot provider in ${(Date.now() - startGetHost) / 1000}s`)
+ slots.push({ slotId: id, slotIdx, state, provider })
+ }
+ console.log(`fetched ${numSlots} slots in ${(Date.now() - start) / 1000}s`)
+ return slots
+ // blockNumbers.value.add(blockNumber)
+ }
+
+ const getBlock = async (blockHash) => {
+ if (Object.keys(blocks.value).includes(blockHash)) {
+ return blocks.value[blockHash]
+ } else {
+ let block = await ethProvider.getBlock(blockHash)
+ blocks.value[blockHash] = block
+ return block
+ }
+ }
+
+ async function addRequest(requestId, blockHash) {
+ let state = await getRequestState(requestId)
+ let block = await getBlock(blockHash)
+ let reqExisting = requests.value[requestId] || {} // just in case it already exists
+ let request = {
+ ...reqExisting,
+ state,
+ requestedAt: block.timestamp,
+ requestFinishedId: null,
+ detailsFetched: false,
+ moderated: 'pending'
+ }
+ requests.value[requestId] = request
+ return request
+ }
+
+ async function fetchPastRequests() {
+ // query past events
+ if (fetched.value) {
+ console.log('skipping fetching past requests, already fetched')
+ return
+ }
+ console.log('fetching past requests')
+ loading.value = true
+ try {
+ let events = await marketplace.queryFilter(StorageRequested)
+ console.log('got ', events.length, ' StorageRequested events')
+ events.forEach(async (event, i) => {
+ console.log('getting details for StorageRequested event ', i)
+ let start = Date.now()
+ let { requestId, ask, expiry } = event.args
+ let { blockHash, blockNumber } = event
+ await addRequest(requestId, blockHash)
+ console.log(`got details for ${i} in ${(Date.now() - start) / 1000} seconds`)
+ if (i === events.length - 1) {
+ loading.value = false
+ fetched.value = true
+ }
+ })
+ if (events.length === 0) {
loading.value = false
+ fetched.value = true
}
- })
- if (events.length === 0) {
+ } catch (error) {
+ console.error(`failed to load past contract events: ${error.message}`)
+ }
+ }
+
+ async function fetchRequest(requestId) {
+ let start = Date.now()
+ console.log('fetching request ', requestId)
+ const preFetched = requests.value[requestId] || {}
+ if (preFetched?.detailsFetched) {
+ return
+ }
+ loading.value = true
+ try {
+ let arrRequest = await marketplace.getRequest(requestId)
+ let request = arrayToObject(arrRequest)
+ let slots = await getSlots(requestId, request.ask.slots)
+ const reqExisting = requests.value[requestId] || {}
+ requests.value[requestId] = {
+ ...reqExisting, // state, requestedAt, requestFinishedId (null)
+ ...request,
+ slots,
+ detailsFetched: true
+ }
+ } catch (error) {
+ console.error(`failed to load slots for request ${requestId}: ${error}`)
+ throw error
+ } finally {
+ console.log(`fetched request in ${(Date.now() - start) / 1000}s`)
loading.value = false
}
- } catch (error) {
- console.error(`failed to load past contract events: ${error.message}`)
}
- }
- async function fetchRequest(requestId) {
- let start = Date.now()
- console.log('fetching request ', requestId)
- const preFetched = requests.value.get(requestId)
- if (preFetched?.detailsFetched) {
- return
+ function updateRequestState(requestId, newState) {
+ if (!Object.keys(requests.value).includes(requestId)) {
+ throw new RequestNotFoundError(requestId, `Request not found`)
+ }
+ let { state, ...rest } = requests.value[requestId]
+ state = newState
+ requests.value[requestId] = { state, ...rest }
}
- loading.value = true
- try {
- let arrRequest = await marketplace.getRequest(requestId)
- let request = arrayToObject(arrRequest)
- let slots = await getSlots(requestId, request.ask.slots)
- const reqExisting = requests.value.get(requestId)
- requests.value.set(requestId, {
- ...reqExisting, // state, requestedAt, requestFinishedId (null)
- ...request,
- slots,
- detailsFetched: true
+
+ function updateRequestFinishedId(requestId, newRequestFinishedId) {
+ if (!Object.keys(requests.value).includes(requestId)) {
+ throw new RequestNotFoundError(requestId, `Request not found`)
+ }
+ let { requestFinishedId, ...rest } = requests.value[requestId]
+ requestFinishedId = newRequestFinishedId
+ requests.value[requestId] = { requestFinishedId, ...rest }
+ }
+
+ function updateRequestSlotState(requestId, slotIdx, newState) {
+ if (!Object.keys(requests.value).includes(requestId)) {
+ throw new RequestNotFoundError(requestId, `Request not found`)
+ }
+ let { slots, ...rest } = requests.value[requestId]
+ slots = slots.map((slot) => {
+ if (slot.slotIdx == slotIdx) {
+ slot.state = newState
+ }
})
- } catch (error) {
- console.error(`failed to load slots for request ${requestId}: ${error}`)
- throw error
- } finally {
- console.log(`fetched request in ${(Date.now() - start) / 1000}s`)
- loading.value = false
+ requests.value[requestId] = { slots, ...rest }
+ }
+
+ function waitForRequestFinished(requestId, duration, onRequestFinished) {
+ return setTimeout(async () => {
+ try {
+ updateRequestState(requestId, 'Finished')
+ updateRequestFinishedId(requestId, null)
+ } catch (error) {
+ if (error instanceof RequestNotFoundError) {
+ await fetchRequest(requestId)
+ }
+ }
+ if (onRequestFinished) {
+ let blockNumber = await ethProvider.getBlockNumber()
+ onRequestFinished(blockNumber, requestId)
+ }
+ }, duration)
+ }
+
+ function cancelWaitForRequestFinished(requestId) {
+ if (!Object.keys(requests.value).includes(requestId)) {
+ throw new RequestNotFoundError(requestId, `Request not found`)
+ }
+ let { requestFinishedId } = requests.value[requestId]
+ if (requestFinishedId) {
+ clearTimeout(requestFinishedId)
+ }
+ }
+
+ async function listenForNewEvents(
+ onStorageRequested,
+ onRequestFulfilled,
+ onRequestCancelled,
+ onRequestFailed,
+ onRequestFinished,
+ onSlotFreed,
+ onSlotFilled
+ ) {
+ marketplace.on(StorageRequested, async (requestId, ask, expiry, event) => {
+ let { blockNumber, blockHash } = event.log
+ const request = addRequest(requestId, blockHash)
+
+ // callback
+ if (onStorageRequested) {
+ onStorageRequested(blockNumber, requestId, request.state)
+ }
+ })
+
+ marketplace.on(RequestFulfilled, async (requestId, event) => {
+ let requestOnChain = await marketplace.getRequest(requestId)
+ let ask = requestOnChain[1]
+ let duration = ask[1]
+ // set request state to finished at the end of the request -- there's no
+ // other way to know when a request finishes
+ console.log('request ', requestOnChain)
+ let requestFinishedId = waitForRequestFinished(requestId, duration, onRequestFinished)
+ updateRequestState(requestId, 'Fulfilled')
+ updateRequestFinishedId(requestId, requestFinishedId)
+
+ let { blockNumber } = event.log
+ if (onRequestFulfilled) {
+ onRequestFulfilled(blockNumber, requestId)
+ }
+ })
+ marketplace.on(RequestCancelled, async (requestId, event) => {
+ try {
+ updateRequestState(requestId, 'Cancelled')
+ } catch (error) {
+ if (error instanceof RequestNotFoundError) {
+ await fetchRequest(requestId)
+ }
+ }
+
+ let { blockNumber } = event.log
+ if (onRequestCancelled) {
+ onRequestCancelled(blockNumber, requestId)
+ }
+ })
+ marketplace.on(RequestFailed, async (requestId, event) => {
+ try {
+ updateRequestState(requestId, 'Failed')
+ cancelWaitForRequestFinished(requestId)
+ } catch (error) {
+ if (error instanceof RequestNotFoundError) {
+ await fetchRequest(requestId)
+ }
+ }
+
+ let { blockNumber } = event.log
+ if (onRequestFailed) {
+ onRequestFailed(blockNumber, requestId)
+ }
+ })
+ marketplace.on(SlotFreed, async (requestId, slotIdx, event) => {
+ try {
+ updateRequestSlotState(requestId, slotIdx, 'Freed')
+ } catch (error) {
+ if (error instanceof RequestNotFoundError) {
+ await fetchRequest(requestId)
+ }
+ }
+
+ let { blockNumber } = event.log
+ if (onSlotFreed) {
+ onSlotFreed(blockNumber, requestId, slotIdx)
+ }
+ })
+ marketplace.on(SlotFilled, async (requestId, slotIdx, event) => {
+ try {
+ updateRequestSlotState(requestId, slotIdx, 'Filled')
+ } catch (error) {
+ if (error instanceof RequestNotFoundError) {
+ await fetchRequest(requestId)
+ }
+ }
+
+ let { blockNumber } = event.log
+ if (onSlotFilled) {
+ onSlotFilled(blockNumber, requestId, slotIdx)
+ }
+ })
+ }
+
+ return {
+ requests,
+ // slots,
+ // blockNumbers,
+ // storageRequestedEvents,
+ // slotFilledEvents,
+ // slotFreedEvents,
+ // requestStartedEvents,
+ // requestCancelledEvents,
+ // requestFailedEvents,
+ // requestFinishedEvents,
+ fetchPastRequests,
+ fetchRequest,
+ listenForNewEvents,
+ loading,
+ fetched
+ }
+ },
+ {
+ persist: {
+ serializer: {
+ serialize: (state) => {
+ return JSON.stringify(state, (_, v) => (typeof v === 'bigint' ? v.toString() : v))
+ },
+ deserialize: (serialized) => {
+ // TODO: deserialize bigints properly
+ return JSON.parse(serialized)
+ }
+ }
}
}
-
- function updateRequestState(requestId, newState) {
- let { state, ...rest } = requests.value.get(requestId)
- state = newState
- requests.value.set(requestId, { state, ...rest })
- }
-
- function updateRequestFinishedId(requestId, newRequestFinishedId) {
- let { requestFinishedId, ...rest } = requests.value.get(requestId)
- requestFinishedId = newRequestFinishedId
- requests.value.set(requestId, { requestFinishedId, ...rest })
- }
-
- function updateRequestSlotState(requestId, slotIdx, newState) {
- let { slots, ...rest } = requests.value.get(requestId)
- slots = slots.map((slot) => {
- if (slot.slotIdx == slotIdx) {
- slot.state = newState
- }
- })
- requests.value.set(requestId, { slots, ...rest })
- }
-
- function waitForRequestFinished(requestId, duration, onRequestFinished) {
- return setTimeout(async () => {
- updateRequestState(requestId, 'Finished')
- updateRequestFinishedId(requestId, null)
- if (onRequestFinished) {
- let blockNumber = await ethProvider.getBlockNumber()
- onRequestFinished(blockNumber, requestId)
- }
- }, duration)
- }
-
- function cancelWaitForRequestFinished(requestId) {
- let { requestFinishedId } = requests.value.get(requestId)
- if (requestFinishedId) {
- clearTimeout(requestFinishedId)
- }
- }
-
- async function listenForNewEvents(
- onStorageRequested,
- onRequestFulfilled,
- onRequestCancelled,
- onRequestFailed,
- onRequestFinished,
- onSlotFreed,
- onSlotFilled
- ) {
- marketplace.on(StorageRequested, async (requestId, ask, expiry, event) => {
- let { blockNumber, blockHash } = event.log
- const request = addRequest(requestId, blockHash)
-
- // callback
- if (onStorageRequested) {
- onStorageRequested(blockNumber, requestId, request.state)
- }
- })
-
- marketplace.on(RequestFulfilled, async (requestId, event) => {
- let requestOnChain = await marketplace.getRequest(requestId)
- let ask = requestOnChain[1]
- let duration = ask[1]
- // set request state to finished at the end of the request -- there's no
- // other way to know when a request finishes
- console.log('request ', requestOnChain)
- let requestFinishedId = waitForRequestFinished(requestId, duration, onRequestFinished)
- updateRequestState(requestId, 'Fulfilled')
- updateRequestFinishedId(requestId, requestFinishedId)
-
- let { blockNumber } = event.log
- if (onRequestFulfilled) {
- onRequestFulfilled(blockNumber, requestId)
- }
- })
- marketplace.on(RequestCancelled, async (requestId, event) => {
- updateRequestState(requestId, 'Cancelled')
-
- let { blockNumber } = event.log
- if (onRequestCancelled) {
- onRequestCancelled(blockNumber, requestId)
- }
- })
- marketplace.on(RequestFailed, async (requestId, event) => {
- updateRequestState(requestId, 'Failed')
- cancelWaitForRequestFinished(requestId)
-
- let { blockNumber } = event.log
- if (onRequestFailed) {
- onRequestFailed(blockNumber, requestId)
- }
- })
- marketplace.on(SlotFreed, async (requestId, slotIdx, event) => {
- updateRequestSlotState(requestId, slotIdx, 'Freed')
-
- let { blockNumber } = event.log
- if (onSlotFreed) {
- onSlotFreed(blockNumber, requestId, slotIdx)
- }
- })
- marketplace.on(SlotFilled, async (requestId, slotIdx, event) => {
- updateRequestSlotState(requestId, slotIdx, 'Filled')
-
- let { blockNumber } = event.log
- if (onSlotFilled) {
- onSlotFilled(blockNumber, requestId, slotIdx)
- }
- })
- }
-
- return {
- requests,
- // slots,
- // blockNumbers,
- // storageRequestedEvents,
- // slotFilledEvents,
- // slotFreedEvents,
- // requestStartedEvents,
- // requestCancelledEvents,
- // requestFailedEvents,
- // requestFinishedEvents,
- fetchPastRequests,
- fetchRequest,
- listenForNewEvents,
- loading
- }
-})
+)
diff --git a/src/utils/requests.js b/src/utils/requests.js
index 4350f5d..f7a7881 100644
--- a/src/utils/requests.js
+++ b/src/utils/requests.js
@@ -41,6 +41,12 @@ export function getStateColour(state) {
}
}
+export const moderatedState = {
+ pending: { text: 'Pending 🤷♂️', color: 'gray' },
+ approved: { text: 'Approved ✅', color: 'green' },
+ banned: { text: 'NSFW! 🫣', color: 'red' }
+}
+
export const requestState = [
'New', // [default] waiting to fill slots
'Fulfilled', // all slots filled, accepting regular proofs
diff --git a/src/views/ModerateView.vue b/src/views/ModerateView.vue
new file mode 100644
index 0000000..9a79787
--- /dev/null
+++ b/src/views/ModerateView.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/src/views/RequestView.vue b/src/views/RequestView.vue
index e77a0f3..112fde8 100644
--- a/src/views/RequestView.vue
+++ b/src/views/RequestView.vue
@@ -20,7 +20,7 @@ async function fetch(requestId) {
router.push({ name: 'NotFound' })
}
}
- request.value = requests.value.get(requestId)
+ request.value = requests.value[requestId]
}
const hasRequest = computed(() => {
@@ -47,6 +47,11 @@ if (loading.value) {
-
+
diff --git a/yarn.lock b/yarn.lock
index 7ab236d..d46544f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2076,6 +2076,11 @@ pify@^2.3.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+pinia-plugin-persistedstate@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz#66780602aecd6c7b152dd7e3ddc249a1f7a13fe5"
+ integrity sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==
+
pinia@^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.1.7.tgz#4cf5420d9324ca00b7b4984d3fbf693222115bbc"