Browse Source

make the photo show in a pop-up dialog

photo-upload
Trent Larson 6 months ago
parent
commit
251986d2bc
  1. 1
      .env.development
  2. 10
      project.task.yaml
  3. 2
      src/components/GiftedDialog.vue
  4. 121
      src/components/GiftedPhotoDialog.vue
  5. 6
      src/router/index.ts
  6. 35
      src/views/GiftedDetails.vue

1
.env.development

@ -2,4 +2,5 @@
# this won't resolve as a URL on production; it's a URN only found in the test system # this won't resolve as a URL on production; it's a URN only found in the test system
VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK
VUE_APP_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000
VUE_APP_DEFAULT_IMAGE_API_SERVER=http://localhost:3001 VUE_APP_DEFAULT_IMAGE_API_SERVER=http://localhost:3001

10
project.task.yaml

@ -14,12 +14,10 @@ tasks :
- .2 list the "show more" contacts alphabetically - .2 list the "show more" contacts alphabetically
- 32 image on give : - 32 image on give :
- send image type (eg. portrait, give, project) - ping endpoint
- upload to a public readable place at correct hosting location - limits endpoint
- remove previous image when editing - upload a photo from elsewhere
- on gift details, if project then show, otherwise mark "gift for you" - go-live - create cert for new image domain, set up haproxy redirect
- ping endpoint
- limits endpoint
- 08 image on profile - 08 image on profile

2
src/components/GiftedDialog.vue

@ -25,7 +25,7 @@
</div> </div>
<input <input
type="number" type="number"
class="border border-r-0 border-slate-400 px-2 py-2 text-center" class="border border-r-0 border-slate-400 px-2 py-2 text-center w-20"
v-model="amountInput" v-model="amountInput"
/> />
<div <div

121
src/views/GiftedPhoto.vue → src/components/GiftedPhotoDialog.vue

@ -1,15 +1,14 @@
<template> <template>
<!-- CONTENT --> <div v-if="visible" class="dialog-overlay">
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb --> <!-- Breadcrumb -->
<div class="mb-8"> <div class="dialog">
<!-- Back --> <!-- Back -->
<div class="text-lg text-center font-light relative px-7"> <div class="text-lg text-center font-light relative px-7">
<h1 <h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1" class="text-lg text-center px-2 py-1 absolute -right-2 -top-1"
@click="$router.back()" @click="close()"
> >
<fa icon="chevron-left" class="fa-fw"></fa> <fa icon="xmark" class="fa-fw"></fa>
</h1> </h1>
</div> </div>
@ -19,46 +18,46 @@
<span v-else-if="blob"> Look Good? </span> <span v-else-if="blob"> Look Good? </span>
<span v-else> Say "Cheese"! </span> <span v-else> Say "Cheese"! </span>
</h1> </h1>
</div>
<div v-if="uploading" class="flex justify-center"> <div v-if="uploading" class="flex justify-center">
<fa icon="spinner" class="fa-spin fa-3x text-center block" /> <fa icon="spinner" class="fa-spin fa-3x text-center block" />
</div>
<div v-else-if="blob">
<div class="flex justify-around">
<button
@click="uploadImage"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded-full"
>
<span>Upload</span>
</button>
<button
@click="retryImage"
class="bg-slate-500 hover:bg-slate-700 text-white font-bold py-2 px-2 rounded-full"
>
<span>Retry</span>
</button>
</div> </div>
<img :src="URL.createObjectURL(blob)" class="mt-2 w-full" /> <div v-else-if="blob">
</div> <div class="flex justify-around">
<div v-else>
<!--
Camera "resolution" doesn't change how it shows on screen but rather stretches the result, eg the following which just stretches it vertically:
:resolution="{ width: 375, height: 812 }"
-->
<camera facingMode="environment" autoplay ref="camera">
<div class="absolute bottom-0 w-full flex justify-center pb-4">
<!-- Button -->
<button <button
@click="takeImage" @click="uploadImage"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded-full" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded-full"
> >
<fa icon="camera" class="fa-fw"></fa> <span>Upload</span>
</button>
<button
@click="retryImage"
class="bg-slate-500 hover:bg-slate-700 text-white font-bold py-2 px-2 rounded-full"
>
<span>Retry</span>
</button> </button>
</div> </div>
</camera> <img :src="URL.createObjectURL(blob)" class="mt-2 w-full" />
</div>
<div v-else>
<!--
Camera "resolution" doesn't change how it shows on screen but rather stretches the result, eg the following which just stretches it vertically:
:resolution="{ width: 375, height: 812 }"
-->
<camera facingMode="environment" autoplay ref="camera">
<div class="absolute bottom-0 w-full flex justify-center pb-4">
<!-- Button -->
<button
@click="takeImage"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded-full"
>
<fa icon="camera" class="fa-fw"></fa>
</button>
</div>
</camera>
</div>
</div> </div>
</section> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -73,12 +72,14 @@ import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";
@Component({ components: { Camera } }) @Component({ components: { Camera } })
export default class GiftedPhoto extends Vue { export default class GiftedPhotoDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
activeDid = ""; activeDid = "";
blob: Blob | null = null; blob: Blob | null = null;
setImage: (arg: string) => void = () => {};
uploading = false; uploading = false;
visible = false;
URL = window.URL || window.webkitURL; URL = window.URL || window.webkitURL;
@ -102,6 +103,16 @@ export default class GiftedPhoto extends Vue {
} }
} }
open(setImageFn: (arg: string) => void) {
this.visible = true;
this.setImage = setImageFn;
}
close() {
this.visible = false;
this.blob = null;
}
async takeImage(/* payload: MouseEvent */) { async takeImage(/* payload: MouseEvent */) {
const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>; const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>;
this.blob = await cameraComponent?.snapshot(); // png is default; if that changes, change extension in formData.append this.blob = await cameraComponent?.snapshot(); // png is default; if that changes, change extension in formData.append
@ -145,7 +156,7 @@ export default class GiftedPhoto extends Vue {
this.uploading = false; this.uploading = false;
return; return;
} }
formData.append("image", this.blob, "snapshot.png"); formData.append("image", this.blob, "snapshot.png"); // png is set in snapshot()
formData.append("claimType", "GiveAction"); formData.append("claimType", "GiveAction");
try { try {
const response = await axios.post( const response = await axios.post(
@ -155,10 +166,9 @@ export default class GiftedPhoto extends Vue {
); );
this.uploading = false; this.uploading = false;
// we won't give a notification here because the user will be taken back to finish this.visible = false;
this.blob = null;
localStorage.setItem("imageUrl", response.data.url as string); this.setImage(response.data.url as string);
this.$router.back();
} catch (error) { } catch (error) {
console.error("Error uploading the image", error); console.error("Error uploading the image", error);
this.$notify( this.$notify(
@ -176,3 +186,26 @@ export default class GiftedPhoto extends Vue {
} }
} }
</script> </script>
<style>
.dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
padding: 1.5rem;
}
.dialog {
background-color: white;
padding: 1rem;
border-radius: 0.5rem;
width: 100%;
max-width: 700px;
}
</style>

6
src/router/index.ts

@ -92,12 +92,6 @@ const routes: Array<RouteRecordRaw> = [
/* webpackChunkName: "gifted-details" */ "../views/GiftedDetails.vue" /* webpackChunkName: "gifted-details" */ "../views/GiftedDetails.vue"
), ),
}, },
{
path: "/gifted-photo",
name: "gifted-photo",
component: () =>
import(/* webpackChunkName: "gifted-photo" */ "../views/GiftedPhoto.vue"),
},
{ {
path: "/help", path: "/help",
name: "help", name: "help",

35
src/views/GiftedDetails.vue

@ -40,7 +40,7 @@
</div> </div>
<input <input
type="number" type="number"
class="border border-r-0 border-slate-400 px-2 py-2 text-center" class="border border-r-0 border-slate-400 px-2 py-2 text-center w-20"
v-model="amountInput" v-model="amountInput"
/> />
<div <div
@ -55,25 +55,26 @@
<label class="text-sm">This is given to a project</label> <label class="text-sm">This is given to a project</label>
</div> </div>
<div class="flex justify-center mb-4 mt-4"> <div class="flex justify-center mt-4">
<span v-if="imageUrl"> <span v-if="imageUrl" class="flex justify-between">
Includes Image: <a :href="imageUrl" target="_blank" class="text-blue-500 ml-4">
<a :href="imageUrl" target="_blank" class="text-blue-500 ml-4">View</a> <img :src="imageUrl" class="h-24 rounded-xl" />
</a>
<fa <fa
icon="trash-can" icon="trash-can"
@click="confirmDeleteImage" @click="confirmDeleteImage"
class="text-red-500 fa-fw ml-8" class="text-red-500 fa-fw ml-8 mt-10"
/> />
</span> </span>
<span v-else> <span v-else>
<router-link <fa
:to="{ name: 'gifted-photo' }" icon="camera"
class="bg-blue-500 text-white px-1.5 py-1 rounded-md" class="bg-blue-500 text-white px-2 py-2 rounded-md"
> @click="openPhotoDialog"
<fa icon="camera" class="fa-fw" /> />
</router-link>
</span> </span>
</div> </div>
<GiftedPhotoDialog ref="photoDialog" />
<div v-if="!projectId" class="mt-4"> <div v-if="!projectId" class="mt-4">
<input type="checkbox" class="h-6 w-6 mr-2" v-model="givenToUser" /> <input type="checkbox" class="h-6 w-6 mr-2" v-model="givenToUser" />
@ -114,9 +115,13 @@ import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
import { createAndSubmitGive } from "@/libs/endorserServer"; import { createAndSubmitGive } from "@/libs/endorserServer";
import * as libsUtil from "@/libs/util"; import * as libsUtil from "@/libs/util";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";
import GiftedDialog from "@/components/GiftedDialog.vue";
import GiftedPhotoDialog from "@/components/GiftedPhotoDialog.vue";
@Component({ @Component({
components: { components: {
GiftedDialog,
GiftedPhotoDialog,
QuickNav, QuickNav,
TopMessage, TopMessage,
}, },
@ -198,6 +203,12 @@ export default class GiftedDetails extends Vue {
this.$router.back(); this.$router.back();
} }
openPhotoDialog() {
(this.$refs.photoDialog as GiftedPhotoDialog).open((imgUrl) => {
this.imageUrl = imgUrl;
});
}
confirmDeleteImage() { confirmDeleteImage() {
this.$notify( this.$notify(
{ {

Loading…
Cancel
Save