You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							844 lines
						
					
					
						
							28 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							844 lines
						
					
					
						
							28 KiB
						
					
					
				
								<template>
							 | 
						|
								  <QuickNav />
							 | 
						|
								  <!-- CONTENT -->
							 | 
						|
								  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
							 | 
						|
								    <!-- Breadcrumb -->
							 | 
						|
								    <div id="ViewBreadcrumb" class="mb-8">
							 | 
						|
								      <h1 class="text-lg text-center font-light relative px-7">
							 | 
						|
								        <!-- Back -->
							 | 
						|
								        <button
							 | 
						|
								          @click="$router.go(-1)"
							 | 
						|
								          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
							 | 
						|
								        >
							 | 
						|
								          <fa icon="chevron-left" class="fa-fw" />
							 | 
						|
								        </button>
							 | 
						|
								        Verifiable Claim Details
							 | 
						|
								      </h1>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- Details -->
							 | 
						|
								    <div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
							 | 
						|
								      <div class="block flex gap-4 overflow-hidden">
							 | 
						|
								        <div class="overflow-hidden">
							 | 
						|
								          <h2 class="text-md font-bold">
							 | 
						|
								            {{ capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType) }}
							 | 
						|
								            <button
							 | 
						|
								              v-if="
							 | 
						|
								                veriClaim.claimType === 'GiveAction' &&
							 | 
						|
								                veriClaim.issuer === activeDid
							 | 
						|
								              "
							 | 
						|
								              @click="onClickEditClaim"
							 | 
						|
								              title="Edit"
							 | 
						|
								            >
							 | 
						|
								              <fa icon="pen" class="text-sm text-blue-500 ml-2 mb-1"></fa>
							 | 
						|
								            </button>
							 | 
						|
								          </h2>
							 | 
						|
								          <div class="text-sm">
							 | 
						|
								            <div>
							 | 
						|
								              {{ veriClaim.id }}
							 | 
						|
								              <button
							 | 
						|
								                @click="
							 | 
						|
								                  libsUtil.doCopyTwoSecRedo(
							 | 
						|
								                    veriClaim.id as string,
							 | 
						|
								                    () => (showIdCopy = !showIdCopy),
							 | 
						|
								                  )
							 | 
						|
								                "
							 | 
						|
								                class="ml-2 mr-2"
							 | 
						|
								              >
							 | 
						|
								                <fa icon="copy" class="text-slate-400 fa-fw" />
							 | 
						|
								              </button>
							 | 
						|
								              <span v-show="showIdCopy">Copied ID</span>
							 | 
						|
								            </div>
							 | 
						|
								            <div>
							 | 
						|
								              <fa icon="message" class="fa-fw text-slate-400" />
							 | 
						|
								              {{ veriClaim.claim?.description }}
							 | 
						|
								            </div>
							 | 
						|
								            <div>
							 | 
						|
								              <fa icon="user" class="fa-fw text-slate-400" />
							 | 
						|
								              {{ veriClaim.issuer }}
							 | 
						|
								              <span v-if="!serverUtil.isEmptyOrHiddenDid(veriClaim.issuer)">
							 | 
						|
								                <button
							 | 
						|
								                  @click="
							 | 
						|
								                    libsUtil.doCopyTwoSecRedo(
							 | 
						|
								                      veriClaim.issuer as string,
							 | 
						|
								                      () => (showDidCopy = !showDidCopy),
							 | 
						|
								                    )
							 | 
						|
								                  "
							 | 
						|
								                  class="ml-2 mr-2"
							 | 
						|
								                >
							 | 
						|
								                  <fa icon="copy" class="text-slate-400 fa-fw" />
							 | 
						|
								                </button>
							 | 
						|
								                <span v-show="showDidCopy">Copied DID</span>
							 | 
						|
								              </span>
							 | 
						|
								            </div>
							 | 
						|
								            <div>
							 | 
						|
								              <fa icon="calendar" class="fa-fw text-slate-400" />
							 | 
						|
								              {{ veriClaim.issuedAt?.replace(/T/, " ").replace(/Z/, " UTC") }}
							 | 
						|
								            </div>
							 | 
						|
								
							 | 
						|
								            <!-- Fullfills Links -->
							 | 
						|
								
							 | 
						|
								            <!-- fullfills links for a give -->
							 | 
						|
								            <div v-if="detailsForGive?.fulfillsPlanHandleId">
							 | 
						|
								              <router-link
							 | 
						|
								                :to="
							 | 
						|
								                  '/project/' +
							 | 
						|
								                  encodeURIComponent(detailsForGive?.fulfillsPlanHandleId)
							 | 
						|
								                "
							 | 
						|
								                class="text-blue-500 mt-2"
							 | 
						|
								              >
							 | 
						|
								                Fulfills a bigger plan...
							 | 
						|
								              </router-link>
							 | 
						|
								            </div>
							 | 
						|
								            <!-- if there's another, it's probably fulfilling an offer, too -->
							 | 
						|
								            <div
							 | 
						|
								              v-if="
							 | 
						|
								                detailsForGive?.fulfillsType &&
							 | 
						|
								                detailsForGive?.fulfillsType !== 'PlanAction' &&
							 | 
						|
								                detailsForGive?.fulfillsHandleId
							 | 
						|
								              "
							 | 
						|
								            >
							 | 
						|
								              <!-- router-link to /claim/ only changes URL path -->
							 | 
						|
								              <a
							 | 
						|
								                @click="
							 | 
						|
								                  showDifferentClaimPage(detailsForGive?.fulfillsHandleId)
							 | 
						|
								                "
							 | 
						|
								                class="text-blue-500 mt-4"
							 | 
						|
								              >
							 | 
						|
								                Fulfills
							 | 
						|
								                {{
							 | 
						|
								                  capitalizeAndInsertSpacesBeforeCaps(
							 | 
						|
								                    detailsForGive.fulfillsType,
							 | 
						|
								                  )
							 | 
						|
								                }}...
							 | 
						|
								              </a>
							 | 
						|
								            </div>
							 | 
						|
								
							 | 
						|
								            <!-- fullfills links for an offer -->
							 | 
						|
								            <div v-if="detailsForOffer?.fulfillsPlanHandleId">
							 | 
						|
								              <router-link
							 | 
						|
								                :to="
							 | 
						|
								                  '/project/' +
							 | 
						|
								                  encodeURIComponent(detailsForOffer?.fulfillsPlanHandleId)
							 | 
						|
								                "
							 | 
						|
								                class="text-blue-500 mt-4"
							 | 
						|
								              >
							 | 
						|
								                Offered to a bigger plan...
							 | 
						|
								              </router-link>
							 | 
						|
								            </div>
							 | 
						|
								          </div>
							 | 
						|
								        </div>
							 | 
						|
								      </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div class="flex columns-3">
							 | 
						|
								      <button
							 | 
						|
								        class="col-span-1 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
							 | 
						|
								        v-if="
							 | 
						|
								          libsUtil.isGiveRecordTheUserCanConfirm(
							 | 
						|
								            veriClaim,
							 | 
						|
								            activeDid,
							 | 
						|
								            confirmerIdList,
							 | 
						|
								          )
							 | 
						|
								        "
							 | 
						|
								        @click="confirmConfirmClaim()"
							 | 
						|
								      >
							 | 
						|
								        Confirm
							 | 
						|
								        <fa icon="circle-check" class="ml-2 text-white cursor-pointer" />
							 | 
						|
								      </button>
							 | 
						|
								
							 | 
						|
								      <span class="px-4 py-2">
							 | 
						|
								        <router-link
							 | 
						|
								          v-if="libsUtil.isGiveAction(veriClaim)"
							 | 
						|
								          :to="'/confirm-gift/' + encodeURIComponent(veriClaim.id)"
							 | 
						|
								          class="col-span-1 text-blue-500"
							 | 
						|
								        >
							 | 
						|
								          Confirmation Details...
							 | 
						|
								        </router-link>
							 | 
						|
								      </span>
							 | 
						|
								
							 | 
						|
								      <button
							 | 
						|
								        v-if="libsUtil.canFulfillOffer(veriClaim)"
							 | 
						|
								        @click="openFulfillGiftDialog()"
							 | 
						|
								        class="col-span-1 block w-fit text-center text-md bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md"
							 | 
						|
								      >
							 | 
						|
								        Affirm Delivery
							 | 
						|
								        <fa icon="hand-holding-heart" class="ml-2 text-white cursor-pointer" />
							 | 
						|
								      </button>
							 | 
						|
								    </div>
							 | 
						|
								    <GiftedDialog ref="customGiveDialog" />
							 | 
						|
								
							 | 
						|
								    <div v-if="libsUtil.isGiveAction(veriClaim)">
							 | 
						|
								      <h2 class="font-bold uppercase text-xl mt-8 mb-2">Confirmations</h2>
							 | 
						|
								
							 | 
						|
								      <span v-if="totalConfirmers() === 0">Nobody has confirmed this.</span>
							 | 
						|
								      <span v-else-if="totalConfirmers() === 1">
							 | 
						|
								        One person has confirmed this.
							 | 
						|
								      </span>
							 | 
						|
								      <span v-else> {{ totalConfirmers() }} people have confirmed this. </span>
							 | 
						|
								
							 | 
						|
								      <div v-if="totalConfirmers() > 0">
							 | 
						|
								        <div
							 | 
						|
								          v-if="
							 | 
						|
								            confirmerIdList.length === 0 && confsVisibleToIdList.length === 0
							 | 
						|
								          "
							 | 
						|
								        >
							 | 
						|
								          Nobody that you know confirmed this claim, nor do they have any
							 | 
						|
								          confirmers in their network.
							 | 
						|
								        </div>
							 | 
						|
								
							 | 
						|
								        <div
							 | 
						|
								          v-if="confirmerIdList.length === 0 && confsVisibleToIdList.length > 0"
							 | 
						|
								        >
							 | 
						|
								          <!-- Only show if this person has links to confirmers (below). -->
							 | 
						|
								          Nobody that you know has issued or confirmed this claim.
							 | 
						|
								        </div>
							 | 
						|
								        <div v-if="confirmerIdList.length > 0">
							 | 
						|
								          The following people have issued or confirmed this claim.
							 | 
						|
								          <ul class="ml-4">
							 | 
						|
								            <li
							 | 
						|
								              v-for="confirmerId in confirmerIdList"
							 | 
						|
								              :key="confirmerId"
							 | 
						|
								              class="list-disc ml-4"
							 | 
						|
								            >
							 | 
						|
								              <div class="flex gap-4">
							 | 
						|
								                <div class="grow overflow-hidden">
							 | 
						|
								                  <div class="text-sm">
							 | 
						|
								                    {{ didInfo(confirmerId) }}
							 | 
						|
								                    <span v-if="!serverUtil.isEmptyOrHiddenDid(confirmerId)">
							 | 
						|
								                      <button
							 | 
						|
								                        @click="
							 | 
						|
								                          copyToClipboard(
							 | 
						|
								                            'The DID of ' + confirmerId,
							 | 
						|
								                            confirmerId,
							 | 
						|
								                          )
							 | 
						|
								                        "
							 | 
						|
								                      >
							 | 
						|
								                        <fa icon="copy" class="text-slate-400 fa-fw" />
							 | 
						|
								                      </button>
							 | 
						|
								                    </span>
							 | 
						|
								                  </div>
							 | 
						|
								                </div>
							 | 
						|
								              </div>
							 | 
						|
								            </li>
							 | 
						|
								          </ul>
							 | 
						|
								        </div>
							 | 
						|
								
							 | 
						|
								        <!--
							 | 
						|
								         Never need to show this message:
							 | 
						|
								         "Nobody that you know can see someone who has confirmed this claim."
							 | 
						|
								
							 | 
						|
								         If there is nobody in the confirmerIdList then we'll show the combined "nobody" message.
							 | 
						|
								         If there is somebody in the confirmerIdList then that's all they need to show.
							 | 
						|
								         -->
							 | 
						|
								
							 | 
						|
								        <!-- Now show anyone linked to confirmers. -->
							 | 
						|
								        <div v-if="confsVisibleToIdList.length > 0">
							 | 
						|
								          The following people can connect you with people who have issued or
							 | 
						|
								          confirmed this claim.
							 | 
						|
								          <ul class="ml-4">
							 | 
						|
								            <li
							 | 
						|
								              v-for="confsVisibleTo in confsVisibleToIdList"
							 | 
						|
								              :key="confsVisibleTo"
							 | 
						|
								              class="list-disc ml-4"
							 | 
						|
								            >
							 | 
						|
								              <div class="flex gap-4">
							 | 
						|
								                <div class="grow overflow-hidden">
							 | 
						|
								                  <div class="text-sm">
							 | 
						|
								                    {{ didInfo(confsVisibleTo) }}
							 | 
						|
								                    <span v-if="!serverUtil.isEmptyOrHiddenDid(confsVisibleTo)">
							 | 
						|
								                      <button
							 | 
						|
								                        @click="
							 | 
						|
								                          copyToClipboard(
							 | 
						|
								                            'The DID of ' + confsVisibleTo,
							 | 
						|
								                            confsVisibleTo,
							 | 
						|
								                          )
							 | 
						|
								                        "
							 | 
						|
								                      >
							 | 
						|
								                        <fa icon="copy" class="text-slate-400 fa-fw" />
							 | 
						|
								                      </button>
							 | 
						|
								                    </span>
							 | 
						|
								                  </div>
							 | 
						|
								                </div>
							 | 
						|
								              </div>
							 | 
						|
								            </li>
							 | 
						|
								          </ul>
							 | 
						|
								        </div>
							 | 
						|
								      </div>
							 | 
						|
								
							 | 
						|
								      <!-- explain if user cannot confirm -->
							 | 
						|
								      <!-- Note that these conditions are mirrored in userCanConfirm(). -->
							 | 
						|
								      <div v-if="confirmerIdList.includes(activeDid)">
							 | 
						|
								        You have confirmed this claim.
							 | 
						|
								      </div>
							 | 
						|
								      <div v-else-if="veriClaim.issuer == activeDid">
							 | 
						|
								        You cannot confirm this because you issued this claim, so you already
							 | 
						|
								        count as confirming it.
							 | 
						|
								      </div>
							 | 
						|
								      <div v-else-if="serverUtil.containsHiddenDid(veriClaim.claim)">
							 | 
						|
								        You cannot confirm this because it contains hidden identifiers.
							 | 
						|
								      </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div>
							 | 
						|
								      <h2 class="font-bold uppercase text-xl mt-8 mb-2">
							 | 
						|
								        {{ serverUtil.containsHiddenDid(veriClaim) ? "Visible " : "" }}Details
							 | 
						|
								      </h2>
							 | 
						|
								      <div
							 | 
						|
								        v-if="
							 | 
						|
								          serverUtil.containsHiddenDid(veriClaim) &&
							 | 
						|
								          R.isEmpty(veriClaimDidsVisible)
							 | 
						|
								        "
							 | 
						|
								        class="mb-2"
							 | 
						|
								      >
							 | 
						|
								        Some of the details are not visible to you; they show as "HIDDEN". They
							 | 
						|
								        are not visible to any of your direct contacts, either.
							 | 
						|
								        <span v-if="canShare">
							 | 
						|
								          If you'd like to ask any of your contacts to take a look and see if
							 | 
						|
								          their contacts can see more details,
							 | 
						|
								          <a @click="onClickShareClaim()" class="text-blue-500"
							 | 
						|
								            >click to send them this info</a
							 | 
						|
								          >
							 | 
						|
								          and see if they are willing to make an introduction. They are surely
							 | 
						|
								          connected to someone; if you don't know who to ask, you might try the
							 | 
						|
								          person who registered you.
							 | 
						|
								        </span>
							 | 
						|
								        <span v-else>
							 | 
						|
								          If you'd like to ask any of your contacts to take a look and see if
							 | 
						|
								          their contacts can see more details,
							 | 
						|
								          <a
							 | 
						|
								            @click="copyToClipboard('This page location', windowLocation)"
							 | 
						|
								            class="text-blue-500"
							 | 
						|
								            >share this page with them</a
							 | 
						|
								          >
							 | 
						|
								          and see if they are willing to make an introduction.
							 | 
						|
								        </span>
							 | 
						|
								      </div>
							 | 
						|
								
							 | 
						|
								      <div v-if="!R.isEmpty(veriClaimDidsVisible)">
							 | 
						|
								        Some of the details are not visible to you but they are visible to some
							 | 
						|
								        of your contacts.
							 | 
						|
								        <span v-if="canShare">
							 | 
						|
								          If you'd like an introduction,
							 | 
						|
								          <a @click="onClickShareClaim()" class="text-blue-500"
							 | 
						|
								            >click to share the information with them and ask if they'll tell
							 | 
						|
								            you more about the participants.</a
							 | 
						|
								          >
							 | 
						|
								        </span>
							 | 
						|
								        <span v-else>
							 | 
						|
								          If you'd like an introduction,
							 | 
						|
								          <a
							 | 
						|
								            @click="copyToClipboard('Location', windowLocation)"
							 | 
						|
								            class="text-blue-500"
							 | 
						|
								            >share this page with them and ask if they'll tell you more about
							 | 
						|
								            about the participants.</a
							 | 
						|
								          >
							 | 
						|
								        </span>
							 | 
						|
								
							 | 
						|
								        <div
							 | 
						|
								          v-for="(visibleDidPath, index) of Object.keys(veriClaimDidsVisible)"
							 | 
						|
								          :key="index"
							 | 
						|
								          class="list-disc p-4"
							 | 
						|
								        >
							 | 
						|
								          <div class="text-sm">
							 | 
						|
								            <fa icon="minus" class="fa-fw" />
							 | 
						|
								            The {{ visibleDidPath }} is visible to:
							 | 
						|
								          </div>
							 | 
						|
								          <div class="ml-12 p-1">
							 | 
						|
								            <ul>
							 | 
						|
								              <li
							 | 
						|
								                v-for="(visDid, idx2) of veriClaimDidsVisible[visibleDidPath]"
							 | 
						|
								                :key="idx2"
							 | 
						|
								                class="list-disc"
							 | 
						|
								              >
							 | 
						|
								                <div class="text-sm mt-2">
							 | 
						|
								                  <span>
							 | 
						|
								                    {{ didInfo(visDid) }}
							 | 
						|
								                    <span v-if="!serverUtil.isEmptyOrHiddenDid(visDid)">
							 | 
						|
								                      <button
							 | 
						|
								                        @click="copyToClipboard('The DID of ' + visDid, visDid)"
							 | 
						|
								                      >
							 | 
						|
								                        <fa icon="copy" class="text-slate-400 fa-fw" />
							 | 
						|
								                      </button>
							 | 
						|
								                    </span>
							 | 
						|
								                    <span v-if="veriClaim.publicUrls?.[visDid]"
							 | 
						|
								                      >, found at
							 | 
						|
								                      <fa icon="globe" class="fa-fw text-slate-400" /> <a
							 | 
						|
								                        :href="veriClaim.publicUrls?.[visDid]"
							 | 
						|
								                        class="text-blue-500"
							 | 
						|
								                        >{{
							 | 
						|
								                          veriClaim.publicUrls[visDid].substring(
							 | 
						|
								                            veriClaim.publicUrls[visDid].indexOf("//") + 2,
							 | 
						|
								                          )
							 | 
						|
								                        }}
							 | 
						|
								                      </a>
							 | 
						|
								                    </span>
							 | 
						|
								                  </span>
							 | 
						|
								                </div>
							 | 
						|
								              </li>
							 | 
						|
								            </ul>
							 | 
						|
								          </div>
							 | 
						|
								        </div>
							 | 
						|
								      </div>
							 | 
						|
								      <span v-if="isEditedGlobalId" class="mt-2">
							 | 
						|
								        This record is an edited version. The latest version is here.
							 | 
						|
								      </span>
							 | 
						|
								      <br />
							 | 
						|
								      <button @click="showVeriClaimDump = !showVeriClaimDump" class="ml-2">
							 | 
						|
								        Details
							 | 
						|
								        <fa v-if="showVeriClaimDump" icon="chevron-up" class="text-blue-400" />
							 | 
						|
								        <fa v-else icon="chevron-down" class="text-blue-400" />
							 | 
						|
								      </button>
							 | 
						|
								      <!-- Keep the dump contents directly between > and < to avoid weird spacing. -->
							 | 
						|
								      <pre
							 | 
						|
								        v-if="showVeriClaimDump"
							 | 
						|
								        class="text-sm overflow-x-scroll px-4 py-3 bg-slate-100 rounded-md"
							 | 
						|
								        >{{ veriClaimDump }}</pre
							 | 
						|
								      >
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <h2 class="font-bold uppercase text-xl mt-8 mb-2">Full Claim</h2>
							 | 
						|
								    <p class="mb-4">
							 | 
						|
								      The full claim includes the claim as it was originally issued, including
							 | 
						|
								      the signature (ie. the proof of issuance by that person).
							 | 
						|
								    </p>
							 | 
						|
								    <div v-if="!fullClaim">
							 | 
						|
								      <p v-if="fullClaimMessage" class="mb-4">
							 | 
						|
								        {{ fullClaimMessage }}
							 | 
						|
								      </p>
							 | 
						|
								      <button
							 | 
						|
								        v-else
							 | 
						|
								        class="block w-full text-center text-md uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2"
							 | 
						|
								        @click="showFullClaim(veriClaim.id as string)"
							 | 
						|
								      >
							 | 
						|
								        Load Full Claim Details
							 | 
						|
								      </button>
							 | 
						|
								    </div>
							 | 
						|
								    <div v-else>
							 | 
						|
								      <pre>{{ fullClaimDump }}</pre>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <a
							 | 
						|
								      :href="apiServer + '/api/claim/' + veriClaim.id"
							 | 
						|
								      target="_blank"
							 | 
						|
								      class="block w-full text-center text-md uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2"
							 | 
						|
								    >
							 | 
						|
								      View on the Public Server
							 | 
						|
								    </a>
							 | 
						|
								  </section>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script lang="ts">
							 | 
						|
								import { AxiosError } from "axios";
							 | 
						|
								import * as yaml from "js-yaml";
							 | 
						|
								import * as R from "ramda";
							 | 
						|
								import { Component, Vue } from "vue-facing-decorator";
							 | 
						|
								import { Router } from "vue-router";
							 | 
						|
								import { useClipboard } from "@vueuse/core";
							 | 
						|
								
							 | 
						|
								import GiftedDialog from "@/components/GiftedDialog.vue";
							 | 
						|
								import { NotificationIface } from "@/constants/app";
							 | 
						|
								import { accountsDB, db } from "@/db/index";
							 | 
						|
								import { Contact } from "@/db/tables/contacts";
							 | 
						|
								import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
							 | 
						|
								import * as serverUtil from "@/libs/endorserServer";
							 | 
						|
								import * as libsUtil from "@/libs/util";
							 | 
						|
								import QuickNav from "@/components/QuickNav.vue";
							 | 
						|
								import { Account } from "@/db/tables/accounts";
							 | 
						|
								import {
							 | 
						|
								  GenericCredWrapper,
							 | 
						|
								  GiverReceiverInputInfo,
							 | 
						|
								  OfferVerifiableCredential,
							 | 
						|
								} from "@/libs/endorserServer";
							 | 
						|
								
							 | 
						|
								@Component({
							 | 
						|
								  components: { GiftedDialog, QuickNav },
							 | 
						|
								})
							 | 
						|
								export default class ClaimView extends Vue {
							 | 
						|
								  $notify!: (notification: NotificationIface, timeout?: number) => void;
							 | 
						|
								
							 | 
						|
								  activeDid = "";
							 | 
						|
								  allMyDids: Array<string> = [];
							 | 
						|
								  allContacts: Array<Contact> = [];
							 | 
						|
								  apiServer = "";
							 | 
						|
								
							 | 
						|
								  canShare = false;
							 | 
						|
								  confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
							 | 
						|
								  confsVisibleErrorMessage = "";
							 | 
						|
								  confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer
							 | 
						|
								  detailsForGive = null;
							 | 
						|
								  detailsForOffer = null;
							 | 
						|
								  fullClaim = null;
							 | 
						|
								  fullClaimDump = "";
							 | 
						|
								  fullClaimMessage = "";
							 | 
						|
								  isEditedGlobalId = false;
							 | 
						|
								  numConfsNotVisible = 0; // number of hidden DIDs in the confirmerIdList, minus the issuer if they aren't visible
							 | 
						|
								  showDidCopy = false;
							 | 
						|
								  showIdCopy = false;
							 | 
						|
								  showVeriClaimDump = false;
							 | 
						|
								  veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
							 | 
						|
								  veriClaimDump = "";
							 | 
						|
								  veriClaimDidsVisible = {};
							 | 
						|
								  windowLocation = window.location.href;
							 | 
						|
								
							 | 
						|
								  R = R;
							 | 
						|
								  yaml = yaml;
							 | 
						|
								  libsUtil = libsUtil;
							 | 
						|
								  serverUtil = serverUtil;
							 | 
						|
								
							 | 
						|
								  resetThisValues() {
							 | 
						|
								    this.confirmerIdList = [];
							 | 
						|
								    this.confsVisibleErrorMessage = "";
							 | 
						|
								    this.confsVisibleToIdList = [];
							 | 
						|
								    this.detailsForGive = null;
							 | 
						|
								    this.detailsForOffer = null;
							 | 
						|
								    this.fullClaim = null;
							 | 
						|
								    this.fullClaimDump = "";
							 | 
						|
								    this.fullClaimMessage = "";
							 | 
						|
								    this.isEditedGlobalId = false;
							 | 
						|
								    this.numConfsNotVisible = 0;
							 | 
						|
								    this.veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
							 | 
						|
								    this.veriClaimDump = "";
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  async created() {
							 | 
						|
								    await db.open();
							 | 
						|
								    const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings;
							 | 
						|
								    this.activeDid = settings?.activeDid || "";
							 | 
						|
								    this.apiServer = settings?.apiServer || "";
							 | 
						|
								    this.allContacts = await db.contacts.toArray();
							 | 
						|
								
							 | 
						|
								    await accountsDB.open();
							 | 
						|
								    const accounts = accountsDB.accounts;
							 | 
						|
								    const accountsArr: Array<Account> = await accounts?.toArray();
							 | 
						|
								    this.allMyDids = accountsArr.map((acc) => acc.did);
							 | 
						|
								
							 | 
						|
								    const pathParam = window.location.pathname.substring("/claim/".length);
							 | 
						|
								    let claimId;
							 | 
						|
								    if (pathParam) {
							 | 
						|
								      claimId = decodeURIComponent(pathParam);
							 | 
						|
								      await this.loadClaim(claimId, this.activeDid);
							 | 
						|
								    } else {
							 | 
						|
								      this.$notify(
							 | 
						|
								        {
							 | 
						|
								          group: "alert",
							 | 
						|
								          type: "danger",
							 | 
						|
								          title: "Error",
							 | 
						|
								          text: "No claim ID was provided.",
							 | 
						|
								        },
							 | 
						|
								        -1,
							 | 
						|
								      );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // When Chrome compatibility is fixed https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API#api.navigator.canshare
							 | 
						|
								    // then use this truer check: navigator.canShare && navigator.canShare()
							 | 
						|
								    this.canShare = !!navigator.share;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  // insert a space before any capital letters except the initial letter
							 | 
						|
								  // (and capitalize initial letter, just in case)
							 | 
						|
								  capitalizeAndInsertSpacesBeforeCaps(text: string) {
							 | 
						|
								    return !text
							 | 
						|
								      ? ""
							 | 
						|
								      : text[0].toUpperCase() + text.substr(1).replace(/([A-Z])/g, " $1");
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  totalConfirmers() {
							 | 
						|
								    return (
							 | 
						|
								      this.numConfsNotVisible +
							 | 
						|
								      this.confirmerIdList.length +
							 | 
						|
								      this.confsVisibleToIdList.length
							 | 
						|
								    );
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  // Isn't there a better way to make this available to the template?
							 | 
						|
								  didInfo(did: string) {
							 | 
						|
								    return serverUtil.didInfo(
							 | 
						|
								      did,
							 | 
						|
								      this.activeDid,
							 | 
						|
								      this.allMyDids,
							 | 
						|
								      this.allContacts,
							 | 
						|
								    );
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  async loadClaim(claimId: string, userDid: string) {
							 | 
						|
								    const urlPath = libsUtil.isGlobalUri(claimId)
							 | 
						|
								      ? "/api/claim/byHandle/"
							 | 
						|
								      : "/api/claim/";
							 | 
						|
								    const url = this.apiServer + urlPath + encodeURIComponent(claimId);
							 | 
						|
								    const headers = await serverUtil.getHeaders(userDid);
							 | 
						|
								
							 | 
						|
								    try {
							 | 
						|
								      const resp = await this.axios.get(url, { headers });
							 | 
						|
								      if (resp.status === 200) {
							 | 
						|
								        this.veriClaim = resp.data;
							 | 
						|
								        this.veriClaimDump = yaml.dump(this.veriClaim);
							 | 
						|
								        this.veriClaimDidsVisible = libsUtil.findAllVisibleToDids(
							 | 
						|
								          this.veriClaim,
							 | 
						|
								          true,
							 | 
						|
								        );
							 | 
						|
								      } else {
							 | 
						|
								        // actually, axios typically throws an error so we never get here
							 | 
						|
								        console.error("Error getting claim:", resp);
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "danger",
							 | 
						|
								            title: "Error",
							 | 
						|
								            text: "There was a problem retrieving that claim.",
							 | 
						|
								          },
							 | 
						|
								          -1,
							 | 
						|
								        );
							 | 
						|
								        return;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      this.isEditedGlobalId = !this.veriClaim.handleId.endsWith(claimId);
							 | 
						|
								
							 | 
						|
								      // retrieve more details on Give, Offer, or Plan
							 | 
						|
								      if (this.veriClaim.claimType === "GiveAction") {
							 | 
						|
								        const giveUrl =
							 | 
						|
								          this.apiServer +
							 | 
						|
								          "/api/v2/report/gives?handleId=" +
							 | 
						|
								          encodeURIComponent(this.veriClaim.handleId as string);
							 | 
						|
								        const giveHeaders = await serverUtil.getHeaders(userDid);
							 | 
						|
								        const giveResp = await this.axios.get(giveUrl, {
							 | 
						|
								          headers: giveHeaders,
							 | 
						|
								        });
							 | 
						|
								        if (giveResp.status === 200) {
							 | 
						|
								          this.detailsForGive = giveResp.data.data[0];
							 | 
						|
								        } else {
							 | 
						|
								          console.error("Error getting detailed give info:", giveResp);
							 | 
						|
								        }
							 | 
						|
								      } else if (this.veriClaim.claimType === "Offer") {
							 | 
						|
								        const offerUrl =
							 | 
						|
								          this.apiServer +
							 | 
						|
								          "/api/v2/report/offers?handleId=" +
							 | 
						|
								          encodeURIComponent(this.veriClaim.handleId as string);
							 | 
						|
								        const offerHeaders = await serverUtil.getHeaders(userDid);
							 | 
						|
								        const offerResp = await this.axios.get(offerUrl, {
							 | 
						|
								          headers: offerHeaders,
							 | 
						|
								        });
							 | 
						|
								        if (offerResp.status === 200) {
							 | 
						|
								          this.detailsForOffer = offerResp.data.data[0];
							 | 
						|
								        } else {
							 | 
						|
								          console.error("Error getting detailed offer info:", offerResp);
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      // retrieve the list of confirmers
							 | 
						|
								      const confirmUrl =
							 | 
						|
								        this.apiServer +
							 | 
						|
								        "/api/report/issuersWhoClaimedOrConfirmed?claimId=" +
							 | 
						|
								        encodeURIComponent(serverUtil.stripEndorserPrefix(claimId));
							 | 
						|
								      const confirmHeaders = await serverUtil.getHeaders(userDid);
							 | 
						|
								      const response = await this.axios.get(confirmUrl, {
							 | 
						|
								        headers: confirmHeaders,
							 | 
						|
								      });
							 | 
						|
								      if (response.status === 200) {
							 | 
						|
								        const resultList1 = response.data.result || [];
							 | 
						|
								        //const publicUrls = resultList.publicUrls || [];
							 | 
						|
								        delete resultList1.publicUrls;
							 | 
						|
								        const resultList2 = R.reject(serverUtil.isHiddenDid, resultList1);
							 | 
						|
								        const resultList3 = R.reject(
							 | 
						|
								          (did: string) => did === this.veriClaim.issuer,
							 | 
						|
								          resultList2,
							 | 
						|
								        );
							 | 
						|
								        this.confirmerIdList = resultList3;
							 | 
						|
								        this.numConfsNotVisible = resultList1.length - resultList2.length;
							 | 
						|
								        if (resultList3.length === resultList2.length) {
							 | 
						|
								          // the issuer was not in the "visible" list so they must be hidden
							 | 
						|
								          // so subtract them from the non-visible confirmers count
							 | 
						|
								          this.numConfsNotVisible = this.numConfsNotVisible - 1;
							 | 
						|
								        }
							 | 
						|
								        this.confsVisibleToIdList =
							 | 
						|
								          response.data.result.resultVisibleToDids || [];
							 | 
						|
								      } else {
							 | 
						|
								        this.confsVisibleErrorMessage =
							 | 
						|
								          "Had problems retrieving confirmations.";
							 | 
						|
								      }
							 | 
						|
								    } catch (error: unknown) {
							 | 
						|
								      const serverError = error as AxiosError;
							 | 
						|
								      console.error("Error retrieving claim:", serverError);
							 | 
						|
								      this.$notify(
							 | 
						|
								        {
							 | 
						|
								          group: "alert",
							 | 
						|
								          type: "danger",
							 | 
						|
								          title: "Error",
							 | 
						|
								          text: "Something went wrong retrieving claim data.",
							 | 
						|
								        },
							 | 
						|
								        -1,
							 | 
						|
								      );
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  async showFullClaim(claimId: string) {
							 | 
						|
								    const url =
							 | 
						|
								      this.apiServer + "/api/claim/full/" + encodeURIComponent(claimId);
							 | 
						|
								    const headers = await serverUtil.getHeaders(this.activeDid);
							 | 
						|
								
							 | 
						|
								    try {
							 | 
						|
								      const resp = await this.axios.get(url, { headers });
							 | 
						|
								      if (resp.status === 200) {
							 | 
						|
								        this.fullClaim = resp.data;
							 | 
						|
								        this.fullClaimDump = yaml.dump(this.fullClaim);
							 | 
						|
								      } else {
							 | 
						|
								        // actually, axios typically throws an error so we never get here
							 | 
						|
								        console.error("Error getting full claim:", resp);
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "danger",
							 | 
						|
								            title: "Error",
							 | 
						|
								            text: "There was a problem getting that claim. See logs for more info.",
							 | 
						|
								          },
							 | 
						|
								          -1,
							 | 
						|
								        );
							 | 
						|
								      }
							 | 
						|
								    } catch (error: unknown) {
							 | 
						|
								      console.error("Error retrieving full claim:", error);
							 | 
						|
								      const serverError = error as AxiosError;
							 | 
						|
								      if (serverError.response?.status === 403) {
							 | 
						|
								        this.fullClaimMessage =
							 | 
						|
								          "You are not authorized to view the full contents of this claim." +
							 | 
						|
								          " To see all the details, ask the issuer to allow you to see their claims." +
							 | 
						|
								          " If you cannot see the issuer's DID, ask someone in the Confirmations section above." +
							 | 
						|
								          " If there are no connections, you will have to ask people in your" +
							 | 
						|
								          " network for their help, some other way; send them to this page and" +
							 | 
						|
								          " see if they can make a connection for you.";
							 | 
						|
								      } else {
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "danger",
							 | 
						|
								            title: "Error",
							 | 
						|
								            text: "Something went wrong retrieving that claim. See logs for more info.",
							 | 
						|
								          },
							 | 
						|
								          -1,
							 | 
						|
								        );
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  confirmConfirmClaim() {
							 | 
						|
								    this.$notify(
							 | 
						|
								      {
							 | 
						|
								        group: "modal",
							 | 
						|
								        type: "confirm",
							 | 
						|
								        title: "Confirm",
							 | 
						|
								        text: "Do you personally confirm that this is true?",
							 | 
						|
								        onYes: async () => {
							 | 
						|
								          await this.confirmClaim();
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      -1,
							 | 
						|
								    );
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  // similar code is found in ProjectViewView
							 | 
						|
								  async confirmClaim() {
							 | 
						|
								    // similar logic is found in endorser-mobile
							 | 
						|
								    const goodClaim = serverUtil.removeSchemaContext(
							 | 
						|
								      serverUtil.removeVisibleToDids(
							 | 
						|
								        serverUtil.addLastClaimOrHandleAsIdIfMissing(
							 | 
						|
								          this.veriClaim.claim,
							 | 
						|
								          this.veriClaim.id,
							 | 
						|
								          this.veriClaim.handleId,
							 | 
						|
								        ),
							 | 
						|
								      ),
							 | 
						|
								    );
							 | 
						|
								    const confirmationClaim: serverUtil.GenericVerifiableCredential = {
							 | 
						|
								      "@context": "https://schema.org",
							 | 
						|
								      "@type": "AgreeAction",
							 | 
						|
								      object: goodClaim,
							 | 
						|
								    };
							 | 
						|
								    const result = await serverUtil.createAndSubmitClaim(
							 | 
						|
								      confirmationClaim,
							 | 
						|
								      this.activeDid,
							 | 
						|
								      this.apiServer,
							 | 
						|
								      this.axios,
							 | 
						|
								    );
							 | 
						|
								    if (result.type === "success") {
							 | 
						|
								      this.$notify(
							 | 
						|
								        {
							 | 
						|
								          group: "alert",
							 | 
						|
								          type: "success",
							 | 
						|
								          title: "Success",
							 | 
						|
								          text: "Confirmation submitted.",
							 | 
						|
								        },
							 | 
						|
								        5000,
							 | 
						|
								      );
							 | 
						|
								    } else {
							 | 
						|
								      console.error("Got error submitting the confirmation:", result);
							 | 
						|
								      this.$notify(
							 | 
						|
								        {
							 | 
						|
								          group: "alert",
							 | 
						|
								          type: "danger",
							 | 
						|
								          title: "Error",
							 | 
						|
								          text: "There was a problem submitting the confirmation. See logs for more info.",
							 | 
						|
								        },
							 | 
						|
								        -1,
							 | 
						|
								      );
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  showDifferentClaimPage(claimId: string) {
							 | 
						|
								    const route = {
							 | 
						|
								      path: "/claim/" + encodeURIComponent(claimId),
							 | 
						|
								    };
							 | 
						|
								    (this.$router as Router).push(route).then(async () => {
							 | 
						|
								      this.resetThisValues();
							 | 
						|
								      await this.loadClaim(claimId, this.activeDid);
							 | 
						|
								    });
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  openFulfillGiftDialog() {
							 | 
						|
								    const giver: GiverReceiverInputInfo = {
							 | 
						|
								      did: libsUtil.offerGiverDid(
							 | 
						|
								        this.veriClaim as GenericCredWrapper<OfferVerifiableCredential>,
							 | 
						|
								      ),
							 | 
						|
								    };
							 | 
						|
								    (this.$refs.customGiveDialog as GiftedDialog).open(
							 | 
						|
								      giver,
							 | 
						|
								      undefined,
							 | 
						|
								      this.veriClaim.handleId,
							 | 
						|
								      "Offer fulfilled by " + (giver?.name || "someone not named"),
							 | 
						|
								    );
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  copyToClipboard(name: string, text: string) {
							 | 
						|
								    useClipboard()
							 | 
						|
								      .copy(text)
							 | 
						|
								      .then(() => {
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "toast",
							 | 
						|
								            title: "Copied",
							 | 
						|
								            text: (name || "That") + " was copied to the clipboard.",
							 | 
						|
								          },
							 | 
						|
								          2000,
							 | 
						|
								        );
							 | 
						|
								      });
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  onClickShareClaim() {
							 | 
						|
								    window.navigator.share({
							 | 
						|
								      title: "Help Connect Me",
							 | 
						|
								      text: "I'm trying to find the full details of this claim. Can you help me?",
							 | 
						|
								      url: this.windowLocation,
							 | 
						|
								    });
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  onClickEditClaim() {
							 | 
						|
								    const route = {
							 | 
						|
								      name: "gifted-details",
							 | 
						|
								      query: {
							 | 
						|
								        prevCredToEdit: JSON.stringify(this.veriClaim),
							 | 
						|
								        destinationPathAfter:
							 | 
						|
								          "/claim/" + encodeURIComponent(this.veriClaim.handleId),
							 | 
						|
								      },
							 | 
						|
								    };
							 | 
						|
								    (this.$router as Router).push(route);
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								
							 |