chore: Remove unused files in contact (#10570)

This commit is contained in:
Sivin Varghese
2024-12-12 08:59:24 +05:30
committed by GitHub
parent 99c699ea34
commit 86d37622c8
32 changed files with 10 additions and 3803 deletions

View File

@@ -1,109 +0,0 @@
<script>
import Modal from 'dashboard/components/Modal.vue';
import { useVuelidate } from '@vuelidate/core';
import { required, minLength } from '@vuelidate/validators';
export default {
components: {
Modal,
},
props: {
show: {
type: Boolean,
default: false,
},
isCreating: {
type: Boolean,
default: false,
},
},
emits: ['create', 'cancel', 'update:show'],
setup() {
return { v$: useVuelidate() };
},
data() {
return {
attributeValue: '',
attributeName: '',
};
},
validations: {
attributeName: {
required,
minLength: minLength(2),
},
},
computed: {
localShow: {
get() {
return this.show;
},
set(value) {
this.$emit('update:show', value);
},
},
attributeNameError() {
if (this.v$.attributeName.$error) {
return this.$t('CUSTOM_ATTRIBUTES.FORM.NAME.ERROR');
}
return '';
},
},
methods: {
addCustomAttribute() {
this.$emit('create', {
attributeValue: this.attributeValue,
attributeName: this.attributeName || '',
});
this.reset();
this.$emit('cancel');
},
onClose() {
this.reset();
this.$emit('cancel');
},
reset() {
this.attributeValue = '';
this.attributeName = '';
},
},
};
</script>
<template>
<Modal v-model:show="localShow" :on-close="onClose">
<woot-modal-header
:header-title="$t('CUSTOM_ATTRIBUTES.ADD.TITLE')"
:header-content="$t('CUSTOM_ATTRIBUTES.ADD.DESC')"
/>
<form class="w-full" @submit.prevent="addCustomAttribute">
<woot-input
v-model="attributeName"
:class="{ error: v$.attributeName.$error }"
class="w-full"
:error="attributeNameError"
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
@blur="v$.attributeName.$touch"
@input="v$.attributeName.$touch"
/>
<woot-input
v-model="attributeValue"
class="w-full"
:label="$t('CUSTOM_ATTRIBUTES.FORM.VALUE.LABEL')"
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.VALUE.PLACEHOLDER')"
/>
<div class="flex items-center justify-end gap-2 px-0 py-2">
<woot-button
:is-disabled="v$.attributeName.$invalid || isCreating"
:is-loading="isCreating"
>
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
</woot-button>
<woot-button variant="clear" @click.prevent="onClose">
{{ $t('CUSTOM_ATTRIBUTES.FORM.CANCEL') }}
</woot-button>
</div>
</form>
</Modal>
</template>

View File

@@ -1,131 +0,0 @@
<script>
import EmojiOrIcon from 'shared/components/EmojiOrIcon.vue';
export default {
components: {
EmojiOrIcon,
},
props: {
label: { type: String, required: true },
icon: { type: String, default: '' },
emoji: { type: String, default: '' },
value: { type: [String, Number], default: '' },
showEdit: { type: Boolean, default: false },
},
emits: ['update'],
data() {
return {
isEditing: false,
editedValue: this.value,
};
},
methods: {
focusInput() {
this.$refs.inputfield.focus();
},
onEdit() {
this.isEditing = true;
this.$nextTick(() => {
this.focusInput();
});
},
onUpdate() {
this.isEditing = false;
this.$emit('update', this.editedValue);
},
},
};
</script>
<template>
<div class="contact-attribute">
<div class="title-wrap">
<h4 class="text-sm title">
<div class="title--icon">
<EmojiOrIcon :icon="icon" :emoji="emoji" />
</div>
{{ label }}
</h4>
</div>
<div v-show="isEditing">
<div class="mb-2 w-full flex items-center">
<input
ref="inputfield"
v-model="editedValue"
type="text"
class="!h-8 ltr:rounded-r-none rtl:rounded-l-none !mb-0 !text-sm"
autofocus="true"
@keyup.enter="onUpdate"
/>
<div>
<woot-button
size="small"
icon="ion-checkmark"
class="rounded-l-none rtl:rounded-r-none"
@click="onUpdate"
/>
</div>
</div>
</div>
<div
v-show="!isEditing"
class="value--view"
:class="{ 'is-editable': showEdit }"
>
<p class="value">
{{ value || '---' }}
</p>
<woot-button
v-if="showEdit"
variant="clear link"
size="small"
color-scheme="secondary"
icon="edit"
class-names="edit-button"
@click="onEdit"
/>
</div>
</div>
</template>
<style lang="scss" scoped>
.contact-attribute {
margin-bottom: var(--space-small);
}
.title-wrap {
display: flex;
align-items: center;
margin-bottom: var(--space-mini);
}
.title {
display: flex;
align-items: center;
margin: 0;
}
.title--icon {
width: var(--space-two);
}
.edit-button {
display: none;
}
.value--view {
display: flex;
&.is-editable:hover {
.value {
background: var(--color-background);
}
.edit-button {
display: block;
}
}
}
.value {
display: inline-block;
min-width: var(--space-mega);
border-radius: var(--border-radius-small);
word-break: break-all;
margin: 0 var(--space-smaller) 0 var(--space-normal);
padding: var(--space-micro) var(--space-smaller);
}
</style>

View File

@@ -1,115 +0,0 @@
<script>
import Attribute from './ContactAttribute.vue';
export default {
components: { Attribute },
props: {
contact: {
type: Object,
default: () => ({}),
},
},
emits: ['update', 'createAttribute'],
computed: {
additionalAttributes() {
return this.contact.additional_attributes || {};
},
company() {
const { company = {} } = this.contact;
return company;
},
customAttributes() {
const { custom_attributes: customAttributes = {} } = this.contact;
return customAttributes;
},
customAttributekeys() {
return Object.keys(this.customAttributes).filter(key => {
const value = this.customAttributes[key];
return value !== null && value !== undefined;
});
},
},
methods: {
onEmailUpdate(value) {
this.$emit('update', { email: value });
},
onPhoneUpdate(value) {
this.$emit('update', { phone_number: value });
},
onLocationUpdate(value) {
this.$emit('update', { location: value });
},
handleCustomCreate() {
this.$emit('createAttribute');
},
onCustomAttributeUpdate(key, value) {
this.$emit('update', { custom_attributes: { [key]: value } });
},
},
};
</script>
<template>
<div class="contact-fields">
<h3 class="text-lg title">
{{ $t('CONTACTS_PAGE.FIELDS') }}
</h3>
<Attribute
:label="$t('CONTACT_PANEL.EMAIL_ADDRESS')"
icon="mail"
emoji=""
:value="contact.email"
show-edit
@update="onEmailUpdate"
/>
<Attribute
:label="$t('CONTACT_PANEL.PHONE_NUMBER')"
icon="call"
emoji=""
:value="contact.phone_number"
show-edit
@update="onPhoneUpdate"
/>
<Attribute
v-if="additionalAttributes.location"
:label="$t('CONTACT_PANEL.LOCATION')"
icon="map"
emoji="🌍"
:value="additionalAttributes.location"
show-edit
@update="onLocationUpdate"
/>
<div
v-for="attribute in customAttributekeys"
:key="attribute"
class="custom-attribute--row"
>
<Attribute
:label="attribute"
icon="chevron-right"
:value="customAttributes[attribute]"
show-edit
@update="value => onCustomAttributeUpdate(attribute, value)"
/>
</div>
<woot-button
size="small"
variant="link"
icon="add"
@click="handleCustomCreate"
>
{{ $t('CUSTOM_ATTRIBUTES.ADD.TITLE') }}
</woot-button>
</div>
</template>
<style scoped lang="scss">
.contact-fields {
margin-top: var(--space-medium);
}
.title {
margin-bottom: var(--space-normal);
}
</style>

View File

@@ -1,106 +0,0 @@
<script>
import EditContact from 'dashboard/routes/dashboard/conversation/contact/EditContact.vue';
import NewConversation from 'dashboard/routes/dashboard/conversation/contact/NewConversation.vue';
import AddCustomAttribute from 'dashboard/modules/contact/components/AddCustomAttribute.vue';
import ContactIntro from './ContactIntro.vue';
import ContactFields from './ContactFields.vue';
export default {
components: {
AddCustomAttribute,
ContactFields,
ContactIntro,
EditContact,
NewConversation,
},
props: {
contact: {
type: Object,
default: () => ({}),
},
},
data() {
return {
showCustomAttributeModal: false,
showEditModal: false,
showConversationModal: false,
};
},
computed: {
enableNewConversation() {
return this.contact && this.contact.id;
},
},
methods: {
toggleCustomAttributeModal() {
this.showCustomAttributeModal = !this.showCustomAttributeModal;
},
toggleEditModal() {
this.showEditModal = !this.showEditModal;
},
toggleConversationModal() {
this.showConversationModal = !this.showConversationModal;
},
createCustomAttribute(data) {
const { id } = this.contact;
const { attributeValue, attributeName } = data;
const updatedFields = {
id,
custom_attributes: {
[attributeName]: attributeValue,
},
};
this.updateContact(updatedFields);
},
updateField(data) {
const { id } = this.contact;
const updatedFields = {
id,
...data,
};
this.updateContact(updatedFields);
},
updateContact(contactItem) {
this.$store.dispatch('contacts/update', contactItem);
},
},
};
</script>
<template>
<div class="panel">
<ContactIntro
:contact="contact"
@message="toggleConversationModal"
@edit="toggleEditModal"
/>
<ContactFields
:contact="contact"
@update="updateField"
@create-attribute="toggleCustomAttributeModal"
/>
<EditContact
v-if="showEditModal"
:show="showEditModal"
:contact="contact"
@cancel="toggleEditModal"
/>
<NewConversation
v-if="enableNewConversation"
:show="showConversationModal"
:contact="contact"
@cancel="toggleConversationModal"
/>
<AddCustomAttribute
:show="showCustomAttributeModal"
@cancel="toggleCustomAttributeModal"
@create="createCustomAttribute"
/>
</div>
</template>
<style scoped lang="scss">
.panel {
padding: var(--space-normal) var(--space-normal);
}
</style>

View File

@@ -1,50 +0,0 @@
<script>
import { mapGetters } from 'vuex';
import NoteList from './components/NoteList.vue';
export default {
components: {
NoteList,
},
props: {
contactId: {
type: Number,
required: true,
},
},
computed: {
...mapGetters({ uiFlags: 'contactNotes/getUIFlags' }),
notes() {
return this.$store.getters['contactNotes/getAllNotesByContact'](
this.contactId
);
},
},
mounted() {
this.fetchContactNotes();
},
methods: {
fetchContactNotes() {
const { contactId } = this;
if (contactId) this.$store.dispatch('contactNotes/get', { contactId });
},
onAdd(content) {
const { contactId } = this;
this.$store.dispatch('contactNotes/create', { content, contactId });
},
onDelete(noteId) {
const { contactId } = this;
this.$store.dispatch('contactNotes/delete', { noteId, contactId });
},
},
};
</script>
<template>
<NoteList
:is-fetching="uiFlags.isFetching"
:notes="notes"
@add="onAdd"
@delete="onDelete"
/>
</template>

View File

@@ -1,62 +0,0 @@
<script setup>
import { ref, computed } from 'vue';
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
const emit = defineEmits(['add']);
const noteContent = ref('');
const buttonDisabled = computed(() => noteContent.value === '');
const onAdd = () => {
if (noteContent.value !== '') {
emit('add', noteContent.value);
}
noteContent.value = '';
};
const keyboardEvents = {
'$mod+Enter': {
action: () => onAdd(),
allowOnFocusedInput: true,
},
};
useKeyboardEvents(keyboardEvents);
</script>
<template>
<div
class="flex flex-col flex-grow p-4 mb-2 overflow-hidden bg-white border border-solid rounded-md shadow-sm border-slate-75 dark:border-slate-700 dark:bg-slate-900 text-slate-700 dark:text-slate-100"
>
<WootMessageEditor
v-model="noteContent"
class="input--note"
:placeholder="$t('NOTES.ADD.PLACEHOLDER')"
:enable-suggestions="false"
/>
<div class="flex justify-end w-full">
<woot-button
color-scheme="warning"
:title="$t('NOTES.ADD.TITLE')"
:is-disabled="buttonDisabled"
@click="onAdd"
>
{{ $t('NOTES.ADD.BUTTON') }} {{ '(⌘⏎)' }}
</woot-button>
</div>
</div>
</template>
<style lang="scss" scoped>
.input--note {
&::v-deep .ProseMirror-menubar {
padding: 0;
margin-top: var(--space-minus-small);
}
&::v-deep .ProseMirror-woot-style {
max-height: 22.5rem;
}
}
</style>

View File

@@ -1,139 +0,0 @@
<script>
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
import { dynamicTime } from 'shared/helpers/timeHelper';
export default {
components: {
Thumbnail,
},
props: {
id: {
type: Number,
default: 0,
},
note: {
type: String,
default: '',
},
user: {
type: Object,
default: () => {},
},
createdAt: {
type: Number,
default: 0,
},
},
emits: ['delete'],
setup() {
const { formatMessage } = useMessageFormatter();
return {
formatMessage,
};
},
data() {
return {
showDeleteModal: false,
};
},
computed: {
readableTime() {
return dynamicTime(this.createdAt);
},
noteAuthor() {
return this.user || {};
},
noteAuthorName() {
return this.noteAuthor.name || this.$t('APP_GLOBAL.DELETED_USER');
},
},
methods: {
toggleDeleteModal() {
this.showDeleteModal = !this.showDeleteModal;
},
onDelete() {
this.$emit('delete', this.id);
},
confirmDeletion() {
this.onDelete();
this.closeDelete();
},
closeDelete() {
this.showDeleteModal = false;
},
},
};
</script>
<template>
<div
class="flex flex-col flex-grow p-4 mb-2 overflow-hidden bg-white border border-solid rounded-md shadow-sm border-slate-75 dark:border-slate-700 dark:bg-slate-900 text-slate-700 dark:text-slate-100 note-wrap"
>
<div class="flex items-end justify-between gap-1 text-xs">
<div class="flex items-center">
<Thumbnail
:title="noteAuthorName"
:src="noteAuthor.thumbnail"
:username="noteAuthorName"
size="20px"
/>
<div class="my-0 mx-1 p-0.5 flex flex-row gap-1">
<span class="font-medium text-slate-800 dark:text-slate-100">
{{ noteAuthorName }}
</span>
<span class="text-slate-700 dark:text-slate-100">
{{ $t('NOTES.LIST.LABEL') }}
</span>
<span class="font-medium text-slate-700 dark:text-slate-100">
{{ readableTime }}
</span>
</div>
</div>
<div class="flex invisible actions">
<woot-button
v-tooltip="$t('NOTES.CONTENT_HEADER.DELETE')"
variant="smooth"
size="tiny"
icon="delete"
color-scheme="secondary"
@click="toggleDeleteModal"
/>
</div>
<woot-delete-modal
v-if="showDeleteModal"
v-model:show="showDeleteModal"
:on-close="closeDelete"
:on-confirm="confirmDeletion"
:title="$t('DELETE_NOTE.CONFIRM.TITLE')"
:message="$t('DELETE_NOTE.CONFIRM.MESSAGE')"
:confirm-text="$t('DELETE_NOTE.CONFIRM.YES')"
:reject-text="$t('DELETE_NOTE.CONFIRM.NO')"
/>
</div>
<p
v-dompurify-html="formatMessage(note || '')"
class="mt-4 note__content"
/>
</div>
</template>
<style lang="scss" scoped>
// For RTL direction view
.app-rtl--wrapper {
.note__content {
::v-deep {
p {
unicode-bidi: plaintext;
}
}
}
}
.note-wrap:hover {
.actions {
@apply visible;
}
}
</style>

View File

@@ -1,61 +0,0 @@
<script>
import AddNote from './AddNote.vue';
import ContactNote from './ContactNote.vue';
import Spinner from 'shared/components/Spinner.vue';
export default {
components: {
AddNote,
ContactNote,
Spinner,
},
props: {
notes: {
type: Array,
default: () => [],
},
isFetching: {
type: Boolean,
default: false,
},
},
emits: ['add', 'edit', 'delete'],
methods: {
onAddNote(value) {
this.$emit('add', value);
},
onEditNote(value) {
this.$emit('edit', value);
},
onDeleteNote(value) {
this.$emit('delete', value);
},
},
};
</script>
<template>
<div>
<AddNote @add="onAddNote" />
<ContactNote
v-for="note in notes"
:id="note.id"
:key="note.id"
:note="note.content"
:user="note.user"
:created-at="note.created_at"
@edit="onEditNote"
@delete="onDeleteNote"
/>
<div v-if="isFetching" class="text-center p-4 text-base">
<Spinner size="" />
<span>{{ $t('NOTES.FETCHING_NOTES') }}</span>
</div>
<div v-else-if="!notes.length" class="text-center p-4 text-base">
<span>{{ $t('NOTES.NOT_AVAILABLE') }}</span>
</div>
</div>
</template>