App.vue
1 <script setup> 2 import { onMounted, ref, computed, inject } from 'vue' 3 import { useRequestsStore } from '@/stores/requests' 4 import { RouterView, useRoute } from 'vue-router' 5 import Balance from '@/components/Balance.vue' 6 import BlockNumber from '@/components/BlockNumber.vue' 7 import ToastNotification from '@/components/toasts/ToastNotification.vue' 8 import AppNav from '@/components/AppNav.vue' 9 import ContractEventAlerts from '@/components/ContractEventAlerts.vue' 10 import { initDrawers, initDismisses } from 'flowbite' 11 import NavBreadcrumb from '@/components/NavBreadcrumb.vue' 12 import { storeToRefs } from 'pinia' 13 import NetworkConnectionState from './components/NetworkConnectionState.vue' 14 import serializer from '@/stores/serializer' 15 import { generateUniqueId } from '@/utils/ids' 16 import { useEventsStore } from './stores/events' 17 18 const eventsStore = useEventsStore() 19 const requestsStore = useRequestsStore() 20 const { loading } = storeToRefs(requestsStore) 21 const { events } = storeToRefs(eventsStore) 22 const codexApi = inject('codexApi') 23 const ethProvider = inject('ethProvider') 24 const route = useRoute() 25 26 window.name = generateUniqueId() 27 28 onMounted(() => { 29 initDrawers() 30 initDismisses() 31 requestsStore.$hydrate() 32 requestsStore.refetchRequestStates().then(() => { 33 requestsStore.fetchPastRequests() 34 }) 35 eventsStore.listenForNewEvents() 36 }) 37 38 async function detectRunningCodexNode() { 39 try { 40 let response = await codexApi.spr() 41 return response.ok 42 } catch (e) { 43 return false 44 } 45 } 46 47 async function detectRunningCodexDevnet() { 48 try { 49 await ethProvider.getNetwork.bind(ethProvider)() 50 return true 51 } catch (e) { 52 return false 53 } 54 } 55 const hideThumbnails = ref(false) 56 function onToggleHideThumbnails(override) { 57 if (override !== undefined) { 58 hideThumbnails.value = override 59 } else { 60 hideThumbnails.value = !hideThumbnails.value 61 } 62 } 63 const enableModeration = computed(() => { 64 return route.path.includes('moderate') || route.query.enableModeration === true 65 }) 66 </script> 67 68 <template> 69 <div class="flex flex-col h-full min-w-96 bg-white dark:bg-gray-900"> 70 <header class="sticky top-0 z-10 w-full text-center border-b p-4 flex-none"> 71 <AppNav 72 :hideThumbnails="hideThumbnails" 73 :enableModeration="enableModeration" 74 @toggle-hide-thumbnails="onToggleHideThumbnails" 75 /> 76 </header> 77 <main class="grow flex flex-col mx-auto max-w-screen-xl w-full p-4"> 78 <NavBreadcrumb class="mb-4"></NavBreadcrumb> 79 <RouterView :hideThumbnails="hideThumbnails" /> 80 </main> 81 <footer class="w-full sticky bottom-0 border-t p-4 mt-4 flex-none flex justify-between"> 82 <div class="flex flex-col space-y-1"> 83 <Balance /> 84 <BlockNumber /> 85 </div> 86 <div class="flex flex-col space-y-3"> 87 <NetworkConnectionState 88 :connectionTest="detectRunningCodexNode" 89 text="Codex node" 90 ></NetworkConnectionState> 91 <NetworkConnectionState 92 :connectionTest="detectRunningCodexDevnet" 93 text="Codex devnet" 94 ></NetworkConnectionState> 95 </div> 96 </footer> 97 <div id="toast-container" class="fixed bottom-5 right-5 flex flex-col space-y-2"> 98 <ToastNotification 99 v-if="loading.recent" 100 text="Loading recent storage requests..." 101 ></ToastNotification> 102 <ToastNotification 103 v-if="loading.states" 104 text="Loading latest request states..." 105 ></ToastNotification> 106 </div> 107 </div> 108 </template> 109 110 <style> 111 body { 112 @apply bg-white dark:bg-gray-900; 113 } 114 header, 115 footer, 116 main { 117 @apply min-w-96 bg-white dark:bg-gray-900; 118 } 119 header, 120 footer { 121 @apply border-gray-200 dark:border-gray-600 dark:text-white; 122 } 123 </style>