forked from jsnbuchanan/crowd-funder-for-time-pwa
allow viewing and deletion of an image
This commit is contained in:
@@ -22,6 +22,8 @@ tasks :
|
|||||||
- put the image URL in the claim
|
- put the image URL in the claim
|
||||||
- Rates - images erased?
|
- Rates - images erased?
|
||||||
- image not associated with JWT ULID since that's assigned later
|
- image not associated with JWT ULID since that's assigned later
|
||||||
|
- remove previous image
|
||||||
|
- send image type (eg. portrait, give, project)
|
||||||
|
|
||||||
- ask to detect location & record it in settings
|
- ask to detect location & record it in settings
|
||||||
- if personal location is set, show potential local affiliations
|
- if personal location is set, show potential local affiliations
|
||||||
|
|||||||
31
src/App.vue
31
src/App.vue
@@ -148,6 +148,37 @@
|
|||||||
class="w-full"
|
class="w-full"
|
||||||
role="alert"
|
role="alert"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-if="notification.type === 'confirm'"
|
||||||
|
class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
|
||||||
|
>
|
||||||
|
<div class="w-full px-6 py-6 text-slate-900 text-center">
|
||||||
|
<p class="text-lg mb-4">
|
||||||
|
{{ notification.title }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button
|
||||||
|
@click="
|
||||||
|
notification.onYes();
|
||||||
|
close(notification.id);
|
||||||
|
"
|
||||||
|
class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
@click="close(notification.id)"
|
||||||
|
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="notification.type === 'notification-permission'"
|
v-if="notification.type === 'notification-permission'"
|
||||||
class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
|
class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
|
||||||
|
|||||||
@@ -39,4 +39,5 @@ export interface NotificationIface {
|
|||||||
type: string; // "toast" | "info" | "success" | "warning" | "danger"
|
type: string; // "toast" | "info" | "success" | "warning" | "danger"
|
||||||
title: string;
|
title: string;
|
||||||
text: string;
|
text: string;
|
||||||
|
onYes?: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,12 +52,23 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-center mb-4 mt-4">
|
<div class="flex justify-center mb-4 mt-4">
|
||||||
<router-link
|
<span v-if="imageUrl">
|
||||||
:to="{ name: 'gifted-photo' }"
|
Includes Image:
|
||||||
class="bg-blue-500 text-white px-1.5 py-1 rounded-md"
|
<a :href="imageUrl" target="_blank" class="text-blue-500 ml-4">View</a>
|
||||||
>
|
<fa
|
||||||
<fa icon="camera" class="fa-fw" />
|
icon="trash-can"
|
||||||
</router-link>
|
@click="confirmDeleteImage"
|
||||||
|
class="text-red-500 fa-fw ml-8"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'gifted-photo' }"
|
||||||
|
class="bg-blue-500 text-white px-1.5 py-1 rounded-md"
|
||||||
|
>
|
||||||
|
<fa icon="camera" class="fa-fw" />
|
||||||
|
</router-link>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div 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" />
|
||||||
@@ -88,13 +99,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
|
||||||
import { NotificationIface } from "@/constants/app";
|
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "@/constants/app";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import TopMessage from "@/components/TopMessage.vue";
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { db } from "@/db/index";
|
import { db } from "@/db/index";
|
||||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
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";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
@@ -113,6 +125,7 @@ export default class GiftedDetails extends Vue {
|
|||||||
givenToUser = false;
|
givenToUser = false;
|
||||||
giverDid: string | undefined;
|
giverDid: string | undefined;
|
||||||
giverName = "";
|
giverName = "";
|
||||||
|
imageUrl = "";
|
||||||
isTrade = false;
|
isTrade = false;
|
||||||
message = "";
|
message = "";
|
||||||
offerId = "";
|
offerId = "";
|
||||||
@@ -126,6 +139,7 @@ export default class GiftedDetails extends Vue {
|
|||||||
this.description = this.$route.query.description as string;
|
this.description = this.$route.query.description as string;
|
||||||
this.giverDid = this.$route.query.giverDid as string;
|
this.giverDid = this.$route.query.giverDid as string;
|
||||||
this.giverName = this.$route.query.giverName as string;
|
this.giverName = this.$route.query.giverName as string;
|
||||||
|
this.imageUrl = localStorage.getItem("imageUrl") || "";
|
||||||
this.message = this.$route.query.message as string;
|
this.message = this.$route.query.message as string;
|
||||||
this.offerId = this.$route.query.offerId as string;
|
this.offerId = this.$route.query.offerId as string;
|
||||||
this.projectId = this.$route.query.projectId as string;
|
this.projectId = this.$route.query.projectId as string;
|
||||||
@@ -173,6 +187,57 @@ export default class GiftedDetails extends Vue {
|
|||||||
this.$router.back();
|
this.$router.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
confirmDeleteImage() {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "modal",
|
||||||
|
type: "confirm",
|
||||||
|
title: "Are you sure you want to delete the image?",
|
||||||
|
text: "",
|
||||||
|
onYes: this.deleteImage,
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteImage() {
|
||||||
|
const identity = await libsUtil.getIdentity(this.activeDid);
|
||||||
|
const token = await accessToken(identity);
|
||||||
|
const response = await this.axios.delete(
|
||||||
|
DEFAULT_IMAGE_API_SERVER + "/image/" + encodeURIComponent(this.imageUrl),
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (response.status === 204) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "success",
|
||||||
|
title: "Deleted",
|
||||||
|
text: "That image record was deleted.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error("Error deleting image:", response);
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error",
|
||||||
|
text: "There was an error deleting the image.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
localStorage.removeItem("imageUrl");
|
||||||
|
this.imageUrl = "";
|
||||||
|
}
|
||||||
|
|
||||||
async confirm() {
|
async confirm() {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,12 +46,7 @@
|
|||||||
Camera "resolution" doesn't change how it shows on screen but rather stretches the result, eg the following which just stretches it vertically:
|
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 }"
|
:resolution="{ width: 375, height: 812 }"
|
||||||
-->
|
-->
|
||||||
<camera
|
<camera facingMode="environment" autoplay ref="camera">
|
||||||
facingMode="environment"
|
|
||||||
autoplay
|
|
||||||
ref="camera"
|
|
||||||
class="relative h-full"
|
|
||||||
>
|
|
||||||
<div class="absolute bottom-0 w-full flex justify-center pb-4">
|
<div class="absolute bottom-0 w-full flex justify-center pb-4">
|
||||||
<!-- Button -->
|
<!-- Button -->
|
||||||
<button
|
<button
|
||||||
@@ -157,6 +152,7 @@ export default class GiftedPhoto extends Vue {
|
|||||||
formData,
|
formData,
|
||||||
{ headers },
|
{ headers },
|
||||||
);
|
);
|
||||||
|
this.uploading = false;
|
||||||
|
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
@@ -167,7 +163,7 @@ export default class GiftedPhoto extends Vue {
|
|||||||
},
|
},
|
||||||
3000,
|
3000,
|
||||||
);
|
);
|
||||||
console.log("Sent. Response:", response.data);
|
localStorage.setItem("imageUrl", response.data.url as string);
|
||||||
this.$router.back();
|
this.$router.back();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error uploading the image", error);
|
console.error("Error uploading the image", error);
|
||||||
|
|||||||
Reference in New Issue
Block a user