import & update selected contacts
This commit is contained in:
179
src/views/ContactImportView.vue
Normal file
179
src/views/ContactImportView.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<QuickNav selected="Contacts"></QuickNav>
|
||||
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
||||
<!-- Heading -->
|
||||
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
||||
Contact Import
|
||||
</h1>
|
||||
|
||||
<div v-if="sameCount > 0">
|
||||
{{ sameCount }} contact{{ sameCount == 1 ? "" : "s" }} are the same as
|
||||
existing contacts.
|
||||
</div>
|
||||
|
||||
<!-- Results List -->
|
||||
<ul v-if="contactsImporting.length > 0" class="border-t border-slate-300">
|
||||
<li
|
||||
v-for="(contact, index) in contactsImporting"
|
||||
:key="contact.did"
|
||||
>
|
||||
<div
|
||||
v-if="
|
||||
!contactsExisting[contact.did] ||
|
||||
!R.isEmpty(contactDifferences[contact.did])
|
||||
"
|
||||
class="grow overflow-hidden border-b border-slate-300 pt-2.5 pb-4"
|
||||
>
|
||||
<h2 class="text-base font-semibold">
|
||||
<input type="checkbox" v-model="contactsSelected[index]" />
|
||||
{{ contact.name || AppString.NO_CONTACT_NAME }}
|
||||
-
|
||||
<span v-if="contactsExisting[contact.did]" class="text-orange-500"
|
||||
>Existing</span
|
||||
>
|
||||
<span v-else class="text-green-500">New</span>
|
||||
</h2>
|
||||
<div class="text-sm truncate">
|
||||
{{ contact.did }}
|
||||
</div>
|
||||
<div v-if="contactDifferences[contact.did]">
|
||||
<div>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<div class="font-bold">Field</div>
|
||||
<div class="font-bold">Old Value</div>
|
||||
<div class="font-bold">New Value</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="(value, contactField) in contactDifferences[contact.did]"
|
||||
:key="contactField"
|
||||
class="grid grid-cols-3 border"
|
||||
>
|
||||
<div class="border p-1">{{ contactField }}</div>
|
||||
<div class="border p-1">{{ value.old }}</div>
|
||||
<div class="border p-1">{{ value.new }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<fa icon="spinner" v-if="importing" class="animate-spin" />
|
||||
<button
|
||||
v-else
|
||||
class="text-sm 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-2 py-1.5 rounded-l-md"
|
||||
@click="importContacts"
|
||||
>
|
||||
Import Selected Contacts
|
||||
</button>
|
||||
</ul>
|
||||
<p v-else>There are no contacts to import.</p>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import * as R from "ramda";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { Router } from "vue-router";
|
||||
|
||||
import { AppString, NotificationIface } from "@/constants/app";
|
||||
import { db } from "@/db/index";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
import * as libsUtil from "@/libs/util";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import EntityIcon from "@/components/EntityIcon.vue";
|
||||
import GiftedDialog from "@/components/GiftedDialog.vue";
|
||||
import OfferDialog from "@/components/OfferDialog.vue";
|
||||
|
||||
@Component({
|
||||
components: { GiftedDialog, EntityIcon, OfferDialog, QuickNav },
|
||||
})
|
||||
export default class ContactImportView extends Vue {
|
||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||
|
||||
AppString = AppString;
|
||||
libsUtil = libsUtil;
|
||||
R = R;
|
||||
|
||||
contactsExisting: Record<string, Contact> = {}; // user's contacts already in the system, keyed by DID
|
||||
contactsImporting: Array<Contact> = []; // contacts from the import
|
||||
contactsSelected: Array<boolean> = []; // whether each contact in contactsImporting is selected
|
||||
contactDifferences: Record<
|
||||
string,
|
||||
Record<string, { new: string; old: string }>
|
||||
> = {}; // for existing contacts, it shows the difference between imported and existing contacts for each key
|
||||
importing = false;
|
||||
sameCount = 0;
|
||||
|
||||
async created() {
|
||||
// Retrieve the imported contacts from the query parameter
|
||||
const importedContacts =
|
||||
((this.$route as Router).query["contacts"] as string) || "[]";
|
||||
this.contactsImporting = JSON.parse(importedContacts);
|
||||
this.contactsSelected = new Array(this.contactsImporting.length).fill(
|
||||
false,
|
||||
);
|
||||
|
||||
await db.open();
|
||||
const baseContacts = await db.contacts.toArray();
|
||||
// set the existing contacts, keyed by DID, if they exist in contactsImporting
|
||||
for (let i = 0; i < this.contactsImporting.length; i++) {
|
||||
const contactIn = this.contactsImporting[i];
|
||||
const existingContact = baseContacts.find(
|
||||
(contact) => contact.did === contactIn.did,
|
||||
);
|
||||
if (existingContact) {
|
||||
this.contactsExisting[contactIn.did] = existingContact;
|
||||
|
||||
const differences: Record<string, { new: string; old: string }> = {};
|
||||
Object.keys(contactIn).forEach((key) => {
|
||||
if (contactIn[key] !== existingContact[key]) {
|
||||
differences[key] = {
|
||||
old: existingContact[key],
|
||||
new: contactIn[key],
|
||||
};
|
||||
}
|
||||
});
|
||||
this.contactDifferences[contactIn.did] = differences;
|
||||
if (R.isEmpty(differences)) {
|
||||
this.sameCount++;
|
||||
}
|
||||
} else {
|
||||
// automatically import new data
|
||||
this.contactsSelected[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async importContacts() {
|
||||
this.importing = true;
|
||||
let importedCount = 0,
|
||||
updatedCount = 0;
|
||||
for (let i = 0; i < this.contactsImporting.length; i++) {
|
||||
if (this.contactsSelected[i]) {
|
||||
const contact = R.clone(this.contactsImporting[i]); // cloning to avoid the problem with a Proxy object
|
||||
const existingContact = this.contactsExisting[contact.did];
|
||||
if (existingContact) {
|
||||
await db.contacts.update(contact.did, contact);
|
||||
updatedCount++;
|
||||
} else {
|
||||
await db.contacts.add(contact);
|
||||
importedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.importing = false;
|
||||
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Import Success",
|
||||
text:
|
||||
`${importedCount} contact${importedCount == 1 ? "" : "s"} imported.` +
|
||||
(updatedCount ? ` ${updatedCount} updated.` : ""),
|
||||
},
|
||||
3000,
|
||||
);
|
||||
(this.$router as Router).push({ name: "contacts" });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user