Teams integration: webhook messaging + configuración en Settings + plugin-http
- @tauri-apps/plugin-http instalado (npm + Cargo.toml + capabilities) - src-tauri/src/main.rs: registrado tauri_plugin_http::init() - services/teams.ts: servicio para enviar mensajes Teams via webhook soporta Tauri plugin y browser fetch con fallback automático incluye notifyHUCreated, notifyBlockerLogged, sendTestMessage - SettingsView: nueva sección Teams con input de webhook URL + botón test - ChartAreaInteractive.vue: removido import no usado (@unovis/vue)
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import { storage } from '@/services/storage'
|
||||
|
||||
const STORAGE_KEY = 'teams_webhook_url'
|
||||
|
||||
export function getWebhookUrl(): string {
|
||||
return storage.get(STORAGE_KEY) || ''
|
||||
}
|
||||
|
||||
export function setWebhookUrl(url: string): void {
|
||||
storage.set(STORAGE_KEY, url)
|
||||
}
|
||||
|
||||
export function hasWebhook(): boolean {
|
||||
return !!getWebhookUrl()
|
||||
}
|
||||
|
||||
interface TeamsMessage {
|
||||
title?: string
|
||||
text: string
|
||||
themeColor?: string
|
||||
sections?: {
|
||||
activityTitle?: string
|
||||
activitySubtitle?: string
|
||||
facts?: { name: string; value: string }[]
|
||||
text?: string
|
||||
}[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía un mensaje a Teams via webhook.
|
||||
* Formato: https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook
|
||||
* Soporta tanto Tauri (plugin-http) como browser (fetch).
|
||||
*/
|
||||
export async function sendToTeams(message: TeamsMessage): Promise<boolean> {
|
||||
const webhookUrl = getWebhookUrl()
|
||||
if (!webhookUrl) {
|
||||
console.warn('[Teams] No hay webhook configurado')
|
||||
return false
|
||||
}
|
||||
|
||||
const payload = {
|
||||
'@type': 'MessageCard',
|
||||
'@context': 'http://schema.org/extensions',
|
||||
summary: message.title || message.text.slice(0, 50),
|
||||
title: message.title,
|
||||
text: message.text,
|
||||
themeColor: message.themeColor || '0078D4',
|
||||
sections: message.sections || [],
|
||||
}
|
||||
|
||||
try {
|
||||
// Intentar usar Tauri plugin HTTP primero
|
||||
if (typeof window !== 'undefined' && (window as any).__TAURI_INTERNALS__) {
|
||||
const { fetch } = await import('@tauri-apps/plugin-http')
|
||||
const res = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
if (!res.ok) {
|
||||
console.error(`[Teams] Error HTTP ${res.status}`)
|
||||
return false
|
||||
}
|
||||
console.log('[Teams] Mensaje enviado via Tauri plugin')
|
||||
return true
|
||||
}
|
||||
|
||||
// Fallback browser fetch
|
||||
const res = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
if (!res.ok) {
|
||||
console.error(`[Teams] Error HTTP ${res.status}`)
|
||||
return false
|
||||
}
|
||||
console.log('[Teams] Mensaje enviado via browser fetch')
|
||||
return true
|
||||
} catch (e: any) {
|
||||
console.error('[Teams] Error al enviar mensaje:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía una notificación de HU creada.
|
||||
*/
|
||||
export async function notifyHUCreated(projectName: string, huTitle: string, huUrl?: string): Promise<boolean> {
|
||||
return sendToTeams({
|
||||
title: '🆕 Nueva HU creada',
|
||||
text: `**Proyecto:** ${projectName}`,
|
||||
themeColor: '0078D4',
|
||||
sections: [{
|
||||
facts: [
|
||||
{ name: 'HU', value: huTitle },
|
||||
{ name: 'Proyecto', value: projectName },
|
||||
{ name: 'URL', value: huUrl || window.location.href },
|
||||
],
|
||||
}],
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía una notificación de bloqueo/impedimento.
|
||||
*/
|
||||
export async function notifyBlockerLogged(
|
||||
projectName: string,
|
||||
huTitle: string,
|
||||
category: string,
|
||||
description: string,
|
||||
hoursLost: number,
|
||||
): Promise<boolean> {
|
||||
return sendToTeams({
|
||||
title: '⛔ Bloqueo registrado',
|
||||
text: `**Proyecto:** ${projectName}`,
|
||||
themeColor: 'FF4444',
|
||||
sections: [{
|
||||
facts: [
|
||||
{ name: 'HU', value: huTitle },
|
||||
{ name: 'Categoría', value: category },
|
||||
{ name: 'Descripción', value: description },
|
||||
{ name: 'Horas perdidas', value: `${hoursLost}h` },
|
||||
],
|
||||
}],
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía un mensaje de prueba.
|
||||
*/
|
||||
export async function sendTestMessage(): Promise<boolean> {
|
||||
return sendToTeams({
|
||||
title: '🔔 Prueba de integración',
|
||||
text: 'Este es un mensaje de prueba desde **Alpha**.\n\nSi ves esto, la integración con Teams funciona correctamente.',
|
||||
themeColor: '00FF00',
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user