Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/src/db/interfaces/MiningSources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export interface ImapMiningSourceCredentials {
host: string;
port: number;
tls: boolean;
smtpHost?: string;
smtpPort?: number;
smtpSecure?: boolean;
}

export type OAuthMiningSourceProvider = 'azure' | 'google';
Expand Down
1 change: 1 addition & 0 deletions backend/src/routes/mining.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default function initializeMiningRoutes(
const authMiddleware = initializeAuthMiddleware(authResolver);

router.post('/mine/sources/imap', authMiddleware, createImapMiningSource);
router.put('/mine/sources/imap', authMiddleware, createImapMiningSource);

router.post(
'/mine/sources/:provider',
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/components/mining/ContactInformationSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@
:contacts-to-treat="[contact.email]"
:disable-export="isExportDisabled"
/>
<Button
icon="pi pi-trash"
:label="$t('common.remove')"
severity="danger"
@click="showRemoveConfirmationDialog = true"
/>
</template>
<template v-else>
<Button
Expand Down
38 changes: 18 additions & 20 deletions frontend/src/components/mining/table/MiningTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -814,9 +814,16 @@
<InputText v-model="filterModel.value" />
</template>
<template #body="{ data }">
<div>
<div v-if="data.location" class="flex items-center gap-1">
<NormalizedLocation :normalized-location="data.location_normalized" />
{{ data.location }}
<span class="truncate">{{ data.location }}</span>
</div>
<div
v-else
class="flex items-center gap-1 text-surface-400 dark:text-surface-500"
>
<NormalizedLocation />
<span class="truncate text-xs italic">-</span>
</div>
</template>
</Column>
Expand Down Expand Up @@ -1487,26 +1494,17 @@ function scheduleIdleContactsPrefetch() {
onBeforeMount(() => {
isLoading.value = true;
});
onNuxtReady(() => {
onNuxtReady(async () => {
$screenStore.init();
$contactsStore.visibleColumns = [
'contacts',
'name',
'same_as',
'telephone',
'image',
'location',
...(origin === 'contacts' && $screenStore.width > 550
? ['temperature']
: []),
...($screenStore.width > 700 ? ['tags'] : []),
...($screenStore.width > 800 ? ['status'] : []),
];
});
$filtersStore.initializeTableFilters(origin);
$contactsStore.initializeVisibleColumns(getDefaultVisibleColumns(), origin);

onBeforeMount(() => {
isLoading.value = true;
});
if (contactsLoadingStrategy.value === 'immediate') {
await loadContactsData();
} else {
isLoading.value = false;
scheduleIdleContactsPrefetch();
}
onNuxtReady(async () => {
$screenStore.init();
$filtersStore.initializeTableFilters(origin);
Expand Down
111 changes: 109 additions & 2 deletions frontend/src/pages/sources.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,43 @@
/>
</div>

<Dialog
v-model:visible="showEditSmtpDialog"
modal
:header="t('edit_smtp')"
:style="{ width: '30rem' }"
>
<div class="flex flex-col gap-3">
<div class="text-surface-600 text-sm">
{{ editingSource?.email }}
</div>
<div class="w-full flex flex-col gap-1">
<label for="smtp_host">{{ t('smtp_host') }}</label>
<InputText v-model="editSmtpHost" class="w-full" />
</div>
<div class="w-full flex flex-col gap-1">
<label for="smtp_port">{{ t('smtp_port') }}</label>
<InputNumber v-model="editSmtpPort" show-buttons class="w-full" />
</div>
<div class="flex flex-row items-center gap-2">
<Checkbox v-model="editSmtpSecure" :binary="true" />
<label>{{ t('smtp_secure') }}</label>
</div>
<div class="flex justify-end gap-2 mt-2">
<Button
:label="$t('common.cancel')"
severity="secondary"
@click="showEditSmtpDialog = false"
/>
<Button
:label="$t('common.save')"
:loading="savingSmtp"
@click="saveSmtpSettings"
/>
</div>
</div>
</Dialog>

<div
v-if="
$leadminer.isLoadingMiningSources && !$leadminer.miningSources.length
Expand Down Expand Up @@ -148,6 +185,14 @@
:value="t(getSourceStatusBadge(source).labelKey)"
:severity="getSourceStatusBadge(source).severity"
/>
<Button
v-if="source.type === 'imap'"
size="small"
outlined
icon="pi pi-pencil"
:label="t('edit_smtp')"
@click="openEditSmtpDialog(source)"
/>
</div>
</div>

Expand Down Expand Up @@ -294,6 +339,13 @@ const showAddSourceDialog = ref(false);
const imapSourceModel = ref<MiningSource>();
const showAddSourceImapDialog = ref(false);

const showEditSmtpDialog = ref(false);
const editingSource = ref<MiningSource | null>(null);
const editSmtpHost = ref('');
const editSmtpPort = ref(587);
const editSmtpSecure = ref(true);
const savingSmtp = ref(false);

async function addGoogleSource() {
showAddSourceDialog.value = false;
try {
Expand Down Expand Up @@ -411,6 +463,49 @@ async function confirmDelete() {
}
}

function openEditSmtpDialog(source: MiningSource) {
editingSource.value = source;
editSmtpHost.value = source.smtpHost || '';
editSmtpPort.value = source.smtpPort || 587;
editSmtpSecure.value = source.smtpSecure ?? true;
showEditSmtpDialog.value = true;
}

async function saveSmtpSettings() {
if (!editingSource.value) return;
savingSmtp.value = true;
try {
await $api('/mine/sources/imap', {
method: 'PUT',
body: {
email: editingSource.value.email,
host: editSmtpHost.value,
port: editSmtpPort.value,
secure: editSmtpSecure.value,
password: '',
},
});
editingSource.value.smtpHost = editSmtpHost.value;
editingSource.value.smtpPort = editSmtpPort.value;
editingSource.value.smtpSecure = editSmtpSecure.value;
showEditSmtpDialog.value = false;
$toast.add({
severity: 'success',
summary: t('smtp_updated'),
life: 3000,
});
} catch (error) {
$toast.add({
severity: 'error',
summary: t('smtp_update_failed'),
detail: (error as Error).message,
life: 4500,
});
} finally {
savingSmtp.value = false;
}
}

async function togglePassiveMining(source: MiningSource, value: boolean) {
try {
await updatePassiveMining(source.email, source.type, value);
Expand Down Expand Up @@ -610,7 +705,13 @@ onMounted(async () => {
"stop_mining_failed": "Unable to stop mining",
"total_contacts": "Contacts (Total)",
"last_mining": "Last mining",
"contacts": "contacts"
"contacts": "contacts",
"edit_smtp": "Edit SMTP",
"smtp_host": "SMTP Host",
"smtp_port": "SMTP Port",
"smtp_secure": "TLS/SSL",
"smtp_updated": "SMTP settings updated",
"smtp_update_failed": "Unable to update SMTP settings"
},
"fr": {
"sources": "Sources",
Expand Down Expand Up @@ -666,7 +767,13 @@ onMounted(async () => {
"stop_mining_failed": "Impossible de stopper le minage",
"total_contacts": "Contacts (Total)",
"last_mining": "Dernier minage",
"contacts": "contacts"
"contacts": "contacts",
"edit_smtp": "Modifier SMTP",
"smtp_host": "Hôte SMTP",
"smtp_port": "Port SMTP",
"smtp_secure": "TLS/SSL",
"smtp_updated": "Paramètres SMTP mis à jour",
"smtp_update_failed": "Impossible de mettre à jour les paramètres SMTP"
}
}
</i18n>
3 changes: 3 additions & 0 deletions frontend/src/types/mining.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export interface MiningSource {
totalContacts?: number;
totalFromLastMining?: number;
lastMiningDate?: string;
smtpHost?: string;
smtpPort?: number;
smtpSecure?: boolean;
}

export interface MiningProgress {
Expand Down
Loading
Loading