feat: Separar paginas generador y qr en diferentes proyectos
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
VITE_SUPABASE_ANON_KEY=J5JS7HG...
|
||||||
|
VITE_SUPABASE_URL=https://tudominio
|
||||||
|
VITE_WEBHOOK_TOKEN=6d4g56d4fgd...
|
||||||
|
VITE_N8N_WEBHOOK_URL=https://tudominio/webhook/carnet
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>glm-card-generator</title>
|
<title>glm-card-generator</title>
|
||||||
<script type="module" crossorigin src="/empleado-id/assets/index-Ef45i7N1.js"></script>
|
<script type="module" crossorigin src="/empleado-id/assets/index-hkdwba_S.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/empleado-id/assets/index-OsvWWXE6.css">
|
<link rel="stylesheet" crossorigin href="/empleado-id/assets/index-DZLLXZoS.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { BrowserRouter, Routes, Route, Navigate, useLocation } from "react-route
|
|||||||
import { supabase } from "./services/supabase";
|
import { supabase } from "./services/supabase";
|
||||||
import { useEffect, useState, createContext, useContext } from "react";
|
import { useEffect, useState, createContext, useContext } from "react";
|
||||||
import Login from "./components/Login";
|
import Login from "./components/Login";
|
||||||
import EmployeeCard from "./components/EmployeeCard";
|
|
||||||
import IdCardGenerator from "./Generator";
|
import IdCardGenerator from "./Generator";
|
||||||
import "./components/Login.css";
|
import "./components/Login.css";
|
||||||
|
|
||||||
@@ -157,16 +156,6 @@ export default function App() {
|
|||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
|
||||||
path="/empleado-id/:employeeNumber"
|
|
||||||
element={
|
|
||||||
<ProtectedRoute>
|
|
||||||
<EmployeeCard />
|
|
||||||
</ProtectedRoute>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route path="*" element={<Navigate to="/empleado-id/" replace />} />
|
<Route path="*" element={<Navigate to="/empleado-id/" replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { useState, useRef, useEffect } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
import './Generator.css';
|
import './Generator.css';
|
||||||
import { renderQRCode, downloadIDCards, downloadBulkIDCards, getXLSXLib, clientTemplates } from './script/script.jsx';
|
import { renderQRCode, downloadIDCards, downloadBulkIDCards, getXLSXLib, clientTemplates } from './script/script.jsx';
|
||||||
import { uploadEmployeePhoto, saveClienteProyecto } from './services/storage.js';
|
import { saveClienteProyecto } from './services/storage.js';
|
||||||
import { supabase } from "./services/supabase";
|
|
||||||
|
|
||||||
// Convierte datos binarios recibidos (base64, buffer, array de bytes) en un Blob URL local de forma robusta
|
// Convierte datos binarios recibidos (base64, buffer, array de bytes) en un Blob URL local de forma robusta
|
||||||
const convertBinaryToBlobUrl = (data) => {
|
const convertBinaryToBlobUrl = (data) => {
|
||||||
@@ -175,17 +174,6 @@ export default function IdCardGenerator() {
|
|||||||
// 1) Guardar cédula + cliente_proyecto en carnet_empleados_creados_glm
|
// 1) Guardar cédula + cliente_proyecto en carnet_empleados_creados_glm
|
||||||
await saveClienteProyecto(cleanCedula, clienteProyectoValue);
|
await saveClienteProyecto(cleanCedula, clienteProyectoValue);
|
||||||
|
|
||||||
// 2) Subir foto al storage
|
|
||||||
const customFile = new File([blobData], `${cleanCedula}.jpg`, { type: 'image/jpeg' });
|
|
||||||
const remoteStorageUrl = await uploadEmployeePhoto(cleanCedula, customFile);
|
|
||||||
|
|
||||||
// 3) Guardar URL de foto
|
|
||||||
if (remoteStorageUrl) {
|
|
||||||
await supabase.rpc("save_employee_photo", {
|
|
||||||
p_employee_number: cleanCedula,
|
|
||||||
p_photo_url: remoteStorageUrl
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// silent
|
// silent
|
||||||
}
|
}
|
||||||
@@ -317,17 +305,44 @@ export default function IdCardGenerator() {
|
|||||||
|
|
||||||
const triggerDownload = async () => {
|
const triggerDownload = async () => {
|
||||||
if (!validateForm()) return;
|
if (!validateForm()) return;
|
||||||
setDownloadStatus({ processing: true, text: '🔄 Descargando...' });
|
|
||||||
try {
|
|
||||||
await saveClienteProyecto(employeeId, selectedClient);
|
|
||||||
|
|
||||||
if (photoFile) {
|
setDownloadStatus({ processing: true, text: '🔄 Descargando...' });
|
||||||
const photoUrl = await uploadEmployeePhoto(employeeId, photoFile);
|
|
||||||
await supabase.rpc("save_employee_photo", {
|
try {
|
||||||
p_employee_number: employeeId,
|
// Enviar binario (base64) + employeeId como JSON al webhook n8n
|
||||||
p_photo_url: photoUrl
|
const N8N_WEBHOOK_URL = import.meta.env.VITE_N8N_WEBHOOK_URL;
|
||||||
|
const TOKEN_SECRETO = import.meta.env.VITE_WEBHOOK_TOKEN;
|
||||||
|
|
||||||
|
let photoBase64 = null;
|
||||||
|
if (photoSrc && photoSrc.startsWith('blob:')) {
|
||||||
|
const response = await fetch(photoSrc);
|
||||||
|
if (response.ok) {
|
||||||
|
const blob = await response.blob();
|
||||||
|
photoBase64 = await new Promise((resolve) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => resolve(reader.result.split(',')[1]);
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
data: photoBase64,
|
||||||
|
employeeId: employeeId
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(N8N_WEBHOOK_URL, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': TOKEN_SECRETO
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`El servidor de n8n rechazó la petición (Código: ${response.status})`);
|
||||||
|
}
|
||||||
|
|
||||||
await downloadIDCards({
|
await downloadIDCards({
|
||||||
name, role, selectedClient, language, photoSrc,
|
name, role, selectedClient, language, photoSrc,
|
||||||
@@ -335,6 +350,12 @@ export default function IdCardGenerator() {
|
|||||||
qrCanvas: qrCanvasRef.current,
|
qrCanvas: qrCanvasRef.current,
|
||||||
onStateChange: setDownloadStatus
|
onStateChange: setDownloadStatus
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Guardar cédula + cliente_proyecto en carnet_empleados_creados_glm al completar descarga
|
||||||
|
const cleanCedula = String(employeeId || '').replace(/[-\s]/g, '');
|
||||||
|
if (cleanCedula) {
|
||||||
|
await saveClienteProyecto(cleanCedula, selectedClient);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err.message);
|
alert(err.message);
|
||||||
setDownloadStatus({ processing: false, text: '⬇ Descargar' });
|
setDownloadStatus({ processing: false, text: '⬇ Descargar' });
|
||||||
@@ -552,4 +573,4 @@ export default function IdCardGenerator() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { StrictMode } from 'react'
|
import { StrictMode } from 'react'
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import './index.css'
|
|
||||||
import App from './App.jsx'
|
import App from './App.jsx'
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(
|
createRoot(document.getElementById('root')).render(
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export async function renderQRCode(employeeId, canvasElement) {
|
|||||||
document.body.appendChild(tmp);
|
document.body.appendChild(tmp);
|
||||||
|
|
||||||
new QRCodeLib(tmp, {
|
new QRCodeLib(tmp, {
|
||||||
text: `http://digitalcompass.agency/empleado?id=${cleanId}`,
|
text: `https://digitalcompass.agency/empleado?id=${cleanId}`,
|
||||||
width: 55,
|
width: 55,
|
||||||
height: 55,
|
height: 55,
|
||||||
colorDark: '#000000',
|
colorDark: '#000000',
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
VITE_SUPABASE_URL=https://tudominio
|
||||||
|
VITE_SUPABASE_ANON_KEY=J5JS7HG...
|
||||||
-9
File diff suppressed because one or more lines are too long
-1
@@ -1 +0,0 @@
|
|||||||
body{background:#f5f5f5;margin:0;font-family:Arial,sans-serif}.page{padding:40px}.employee-card{background:#fff;border-radius:12px;width:350px;max-width:100%;margin:auto;overflow:hidden;box-shadow:0 10px 30px #0000001a}.header{color:#fff;text-align:center;padding:20px;font-size:28px;font-weight:700}.content{text-align:center;padding:30px}.label{color:#666;margin-top:16px;font-size:14px}.value{font-size:18px;font-weight:700}.employee-photo{object-fit:cover;border:4px solid #e5e5e5;border-radius:50%;width:170px;height:170px;margin:0 auto 25px;display:block}.employee-photo-placeholder{color:#777;background:#f0f0f0;border:4px solid #e5e5e5;border-radius:50%;justify-content:center;align-items:center;width:170px;height:170px;margin:0 auto 25px;font-weight:700;display:flex}
|
|
||||||
+19
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
body{background:#f5f5f5;margin:0;font-family:Arial,sans-serif}.page{justify-content:center;align-items:center;min-height:10vh;padding:40px;display:flex}.page.loading,.page.not-found{text-align:center;min-height:10vh}.page.loading h2,.page.not-found h1{color:#333;margin:0}.page.not-found h1{color:#ef4444}.employee-card{background:#fff;border-radius:12px;width:350px;max-width:100%;margin:auto;overflow:hidden;box-shadow:0 10px 30px #0000001a}.header{color:#fff;text-align:center;padding:20px;font-size:28px;font-weight:700}.content{text-align:center;padding:30px}.label{color:#666;margin-top:16px;font-size:14px}.value{font-size:18px;font-weight:700}.employee-photo{object-fit:cover;border:4px solid #e5e5e5;border-radius:50%;width:170px;height:170px;margin:0 auto 25px;display:block}.employee-photo-placeholder{color:#777;background:#f0f0f0;border:4px solid #e5e5e5;border-radius:50%;justify-content:center;align-items:center;width:170px;height:170px;margin:0 auto 25px;font-weight:700;display:flex}
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 9.3 KiB |
Vendored
-24
@@ -1,24 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<symbol id="bluesky-icon" viewBox="0 0 16 17">
|
|
||||||
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
|
|
||||||
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="discord-icon" viewBox="0 0 20 19">
|
|
||||||
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="documentation-icon" viewBox="0 0 21 20">
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="github-icon" viewBox="0 0 19 19">
|
|
||||||
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="social-icon" viewBox="0 0 20 20">
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="x-icon" viewBox="0 0 19 19">
|
|
||||||
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
|
|
||||||
</symbol>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB |
Vendored
+3
-3
@@ -2,11 +2,11 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/empleado/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>glm-card-qr</title>
|
<title>glm-card-qr</title>
|
||||||
<script type="module" crossorigin src="/empleado/assets/index-CzNrgdBd.js"></script>
|
<script type="module" crossorigin src="/empleado/assets/index-VXZlFSJm.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/empleado/assets/index-D0nK2oaA.css">
|
<link rel="stylesheet" crossorigin href="/empleado/assets/index-YseJQpQ5.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 9.3 KiB |
@@ -1,24 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<symbol id="bluesky-icon" viewBox="0 0 16 17">
|
|
||||||
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
|
|
||||||
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="discord-icon" viewBox="0 0 20 19">
|
|
||||||
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="documentation-icon" viewBox="0 0 21 20">
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="github-icon" viewBox="0 0 19 19">
|
|
||||||
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="social-icon" viewBox="0 0 20 20">
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
|
|
||||||
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="x-icon" viewBox="0 0 19 19">
|
|
||||||
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
|
|
||||||
</symbol>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -5,9 +5,29 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
|
min-height: 10vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page.loading,
|
||||||
|
.page.not-found {
|
||||||
|
min-height: 10vh;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page.loading h2,
|
||||||
|
.page.not-found h1 {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page.not-found h1 {
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
.employee-card {
|
.employee-card {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -3,6 +3,25 @@ import { useSearchParams } from "react-router-dom";
|
|||||||
import { supabase } from "../services/supabase";
|
import { supabase } from "../services/supabase";
|
||||||
import "./EmployeeCard.css";
|
import "./EmployeeCard.css";
|
||||||
|
|
||||||
|
function toDriveDirectUrl(url) {
|
||||||
|
if (!url) return url;
|
||||||
|
|
||||||
|
// Detectamos si es una URL de Google Drive
|
||||||
|
if (url.includes("drive.google.com")) {
|
||||||
|
// Expresión regular para extraer el ID
|
||||||
|
const match = url.match(/(?:file\/d\/|id=)([a-zA-Z0-9_-]+)/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const fileId = match[1];
|
||||||
|
// Usamos el endpoint de thumbnail que no tiene problemas de CORS
|
||||||
|
return `https://drive.google.com/thumbnail?id=${fileId}&sz=w1000`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si es de BambooHR u otra URL, la devolvemos tal cual
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
export default function EmployeeCard() {
|
export default function EmployeeCard() {
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
@@ -13,9 +32,7 @@ export default function EmployeeCard() {
|
|||||||
const [notFound, setNotFound] = useState(false);
|
const [notFound, setNotFound] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
async function loadEmployee() {
|
async function loadEmployee() {
|
||||||
|
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.rpc("get_carnet_publico", { p_cedula: employeeNumber });
|
.rpc("get_carnet_publico", { p_cedula: employeeNumber });
|
||||||
|
|
||||||
@@ -24,17 +41,14 @@ export default function EmployeeCard() {
|
|||||||
} else {
|
} else {
|
||||||
setEmployee(data[0]);
|
setEmployee(data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadEmployee();
|
loadEmployee();
|
||||||
|
|
||||||
}, [employeeNumber]);
|
}, [employeeNumber]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page loading">
|
||||||
<h2>Cargando...</h2>
|
<h2>Cargando...</h2>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -42,39 +56,46 @@ export default function EmployeeCard() {
|
|||||||
|
|
||||||
if (notFound) {
|
if (notFound) {
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page not-found">
|
||||||
<h1 style={{ color: "red" }}>
|
<h1>Empleado no encontrado</h1>
|
||||||
Empleado no encontrado
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("1. URL original de Supabase:", employee.photo_url);
|
||||||
|
|
||||||
|
// Procesamos la URL final directamente aquí
|
||||||
|
const finalPhotoSrc = toDriveDirectUrl(employee.photo_url);
|
||||||
|
|
||||||
|
console.log("2. URL final a renderizar:", finalPhotoSrc);
|
||||||
|
|
||||||
const active = employee.status?.toLowerCase() === "active";
|
const active = employee.status?.toLowerCase() === "active";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
|
|
||||||
<div className="employee-card">
|
<div className="employee-card">
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="header"
|
className="header"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: active
|
backgroundColor: active ? "#22c55e" : "#ef4444"
|
||||||
? "#22c55e"
|
|
||||||
: "#ef4444"
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{active
|
{active ? "Empleado Activo" : "Empleado No Activo"}
|
||||||
? "Empleado Activo"
|
|
||||||
: "Empleado No Activo"}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{employee.photo_url ? (
|
{employee.photo_url ? (
|
||||||
<img
|
<img
|
||||||
src={employee.photo_url}
|
src={finalPhotoSrc} // <-- CORREGIDO: Usamos la variable ya procesada directamente
|
||||||
alt={employee.name}
|
alt={employee.name}
|
||||||
|
style={{
|
||||||
|
width: "150px",
|
||||||
|
height: "150px",
|
||||||
|
objectFit: "cover",
|
||||||
|
borderRadius: "50%",
|
||||||
|
display: "block",
|
||||||
|
margin: "0 auto"
|
||||||
|
}}
|
||||||
className="employee-photo"
|
className="employee-photo"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -83,43 +104,19 @@ export default function EmployeeCard() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="label">
|
<div className="label">Nombre</div>
|
||||||
Nombre
|
<div className="value">{employee.name}</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="value">
|
<div className="label">Puesto</div>
|
||||||
{employee.name}
|
<div className="value">{employee.job_title}</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="label">
|
<div className="label">País</div>
|
||||||
Puesto
|
<div className="value">{employee.country}</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="value">
|
<div className="label">Estado</div>
|
||||||
{employee.job_title}
|
<div className="value">{employee.status}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="label">
|
|
||||||
País
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="value">
|
|
||||||
{employee.country}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="label">
|
|
||||||
Estado
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="value">
|
|
||||||
{employee.status}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,928 @@
|
|||||||
|
{
|
||||||
|
"name": "GLM ID Card Generator",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"httpMethod": "POST",
|
||||||
|
"path": "carnet",
|
||||||
|
"authentication": "headerAuth",
|
||||||
|
"responseMode": "responseNode",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"position": [
|
||||||
|
-2128,
|
||||||
|
656
|
||||||
|
],
|
||||||
|
"name": "Webhook1",
|
||||||
|
"webhookId": "28db8328-4ea5-47ac-91cb-67dff9deb56d",
|
||||||
|
"type": "n8n-nodes-base.webhook",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"id": "b8f3afe3-2b7d-4759-bf71-4a2bae5924b4",
|
||||||
|
"credentials": {
|
||||||
|
"httpHeaderAuth": {
|
||||||
|
"id": "uafjxH8xBa9B1gOT",
|
||||||
|
"name": "GLM ID Generator"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "binaryToPropery",
|
||||||
|
"binaryPropertyName": "=edited",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.extractFromFile",
|
||||||
|
"typeVersion": 1.1,
|
||||||
|
"position": [
|
||||||
|
608,
|
||||||
|
368
|
||||||
|
],
|
||||||
|
"id": "ca2e4cef-f7cd-4607-bc8d-fbe7d4e6d320",
|
||||||
|
"name": "Extract from File"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "download",
|
||||||
|
"fileId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "={{ $json.fotoUrl.split('/d/')[1].split('/')[0] }}",
|
||||||
|
"mode": "id"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.googleDrive",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
-272,
|
||||||
|
176
|
||||||
|
],
|
||||||
|
"id": "0edb6036-e893-4adf-89a2-e93979e1c9dc",
|
||||||
|
"name": "Download file",
|
||||||
|
"credentials": {
|
||||||
|
"googleDriveOAuth2Api": {
|
||||||
|
"id": "gL2ZTwJb6xojauac",
|
||||||
|
"name": "Eidan - Google Drive account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "image",
|
||||||
|
"operation": "edit",
|
||||||
|
"modelId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "models/gemini-3-pro-image",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "models/gemini-3-pro-image (Nano Banana Pro)"
|
||||||
|
},
|
||||||
|
"prompt": "Professional employee ID card portrait.\nUse the first input image (binary: data) as the employee reference. Preserve the exact facial features, identity, hairstyle, skin tone, facial hair, facial expression, and natural proportions of the person. Do not alter the person's appearance.\nUse the second input image (binary: logo) as the official company logo. Dress the subject in a Columbia-style outdoor button-up work shirt. The shirt color must be exactly #2d3748. Embroider the provided company logo from the second image on the RIGHT chest (the subject's right side), preserving the original colors, proportions, and details of the logo.\nThe subject must be standing completely facing the camera with the head, neck, and shoulders perfectly square to the camera. Both shoulders must be level and symmetrical with no body rotation, tilt, or angled pose. Maintain direct eye contact with the camera.\nReplace the background with a clean, solid white seamless studio background. Use soft, even professional studio lighting with minimal shadows and natural skin tones.\nFrame the portrait as a wide corporate headshot that starts from the chest area and goes upward. The bottom edge of the frame must cut across the chest, clearly below the company logo, showing the full chest, both shoulders, neck, and head. Do not start the crop below the chest (no waist, no arms, no hands) — the visible body must begin at chest level at the very bottom edge of the image.\nThe face should occupy approximately 40–50% of the image height, smaller and further back than a tight close-up. Leave generous, clearly visible white/background space above the head — at least 20–25% of the total image height must be empty background between the top of the head and the top edge of the frame. Leave balanced empty margins on both sides as well.\nThe full embroidered company logo on the right chest must be completely visible, clearly readable, and not cropped or cut off by the bottom edge of the frame.\nThe collar, both shoulders, and the upper chest area must all be clearly visible within the frame. Never crop tightly into the face. Never zoom in close on the face; always keep the wider framing described above, with the bottom of the image at chest level and generous white space above the head.\nPhotorealistic, ultra-high resolution, sharp focus on the eyes and facial features, realistic fabric texture, professional corporate photography, studio quality, natural colors, sharp focus throughout the face and upper body.\nOutput every portrait using exactly the same wider framing, crop, camera distance, focal length, and canvas size. Do not automatically zoom in or out based on the subject. Maintain identical head size and shoulder width relative to the frame across all generated images.\nThe final image must have a fixed portrait aspect ratio of 3:4 and an exact resolution of 1200 × 1600 pixels. The subject's eyes should always be positioned at approximately the same height (around 28–32% from the top of the frame), with the head occupying approximately 40–50% of the image height, and a clearly visible band of empty background space above the head. Keep consistent margins above the head and on both sides for every image.\nUse a fixed virtual camera setup (50mm portrait lens equivalent, eye-level camera position, standing further back from the subject) and identical lighting, perspective, and composition for every generation. Never change the crop or framing based on hairstyle, body size, clothing, or facial features. Every generated portrait must match the same template so all employee photos appear uniform on ID cards, with the frame always starting at chest level and generous white space above the head.",
|
||||||
|
"images": {
|
||||||
|
"values": [
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"binaryPropertyName": "logo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.googleGemini",
|
||||||
|
"typeVersion": 1.2,
|
||||||
|
"position": [
|
||||||
|
432,
|
||||||
|
368
|
||||||
|
],
|
||||||
|
"id": "fd945ca4-2ec1-4d0b-878e-6dd4c6a2a19f",
|
||||||
|
"name": "Edit an image",
|
||||||
|
"credentials": {
|
||||||
|
"googlePalmApi": {
|
||||||
|
"id": "tFqBJras00HUi1hA",
|
||||||
|
"name": "Eidan - Google Gemini(PaLM) Api account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"url": "=https://dbit.digitalcompass.agency/storage/v1/object/public/public-assets/GLM_completo.png",
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"responseFormat": "file",
|
||||||
|
"outputPropertyName": "logo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.4,
|
||||||
|
"position": [
|
||||||
|
304,
|
||||||
|
208
|
||||||
|
],
|
||||||
|
"id": "67fae4f4-2158-4552-a712-7aa40b520d72",
|
||||||
|
"name": "Descargar logo GLM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"fieldToSplitOut": "body.empleados",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.splitOut",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
-800,
|
||||||
|
544
|
||||||
|
],
|
||||||
|
"id": "f0793e22-1567-4a88-8a9b-712283e5f255",
|
||||||
|
"name": "Split Out"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"respondWith": "allIncomingItems",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.respondToWebhook",
|
||||||
|
"typeVersion": 1.5,
|
||||||
|
"position": [
|
||||||
|
-224,
|
||||||
|
-64
|
||||||
|
],
|
||||||
|
"id": "5766587b-d999-4324-8c24-36a00a55b16e",
|
||||||
|
"name": "Respond to Webhook1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.splitInBatches",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
-512,
|
||||||
|
272
|
||||||
|
],
|
||||||
|
"id": "1275247d-4d5b-4f64-b05d-277e643a0e6f",
|
||||||
|
"name": "Loop Over Items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"mode": "combine",
|
||||||
|
"combineBy": "combineByPosition",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.merge",
|
||||||
|
"typeVersion": 3.2,
|
||||||
|
"position": [
|
||||||
|
800,
|
||||||
|
576
|
||||||
|
],
|
||||||
|
"id": "91b86280-864b-49b7-87fb-3060be8b35e3",
|
||||||
|
"name": "Merge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"conditions": {
|
||||||
|
"options": {
|
||||||
|
"caseSensitive": true,
|
||||||
|
"leftValue": "",
|
||||||
|
"typeValidation": "strict",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"id": "30a53e6f-395e-418a-ac50-98b881dbccd1",
|
||||||
|
"leftValue": "={{ $json.body.empleados }}",
|
||||||
|
"rightValue": "",
|
||||||
|
"operator": {
|
||||||
|
"type": "array",
|
||||||
|
"operation": "exists",
|
||||||
|
"singleValue": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"combinator": "and"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.if",
|
||||||
|
"typeVersion": 2.3,
|
||||||
|
"position": [
|
||||||
|
-992,
|
||||||
|
656
|
||||||
|
],
|
||||||
|
"id": "306f5ee6-0630-46c5-b7ff-65cada9ac5e4",
|
||||||
|
"name": "Es un binario?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "image",
|
||||||
|
"operation": "edit",
|
||||||
|
"modelId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "models/gemini-3-pro-image",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "models/gemini-3-pro-image (Nano Banana Pro)"
|
||||||
|
},
|
||||||
|
"prompt": "Professional employee ID card portrait.\nUse the first input image (binary: data) as the employee reference. Preserve the exact facial features, identity, hairstyle, skin tone, facial hair, facial expression, and natural proportions of the person. Do not alter the person's appearance.\nUse the second input image (binary: logo) as the official company logo. Dress the subject in a Columbia-style outdoor button-up work shirt. The shirt color must be exactly #2d3748. Embroider the provided company logo from the second image on the RIGHT chest (the subject's right side), preserving the original colors, proportions, and details of the logo.\nThe subject must be standing completely facing the camera with the head, neck, and shoulders perfectly square to the camera. Both shoulders must be level and symmetrical with no body rotation, tilt, or angled pose. Maintain direct eye contact with the camera.\nReplace the background with a clean, solid white seamless studio background. Use soft, even professional studio lighting with minimal shadows and natural skin tones.\nFrame the portrait as a wide corporate headshot that starts from the chest area and goes upward. The bottom edge of the frame must cut across the chest, clearly below the company logo, showing the full chest, both shoulders, neck, and head. Do not start the crop below the chest (no waist, no arms, no hands) — the visible body must begin at chest level at the very bottom edge of the image.\nThe face should occupy approximately 40–50% of the image height, smaller and further back than a tight close-up. Leave generous, clearly visible white/background space above the head — at least 20–25% of the total image height must be empty background between the top of the head and the top edge of the frame. Leave balanced empty margins on both sides as well.\nThe full embroidered company logo on the right chest must be completely visible, clearly readable, and not cropped or cut off by the bottom edge of the frame.\nThe collar, both shoulders, and the upper chest area must all be clearly visible within the frame. Never crop tightly into the face. Never zoom in close on the face; always keep the wider framing described above, with the bottom of the image at chest level and generous white space above the head.\nPhotorealistic, ultra-high resolution, sharp focus on the eyes and facial features, realistic fabric texture, professional corporate photography, studio quality, natural colors, sharp focus throughout the face and upper body.\nOutput every portrait using exactly the same wider framing, crop, camera distance, focal length, and canvas size. Do not automatically zoom in or out based on the subject. Maintain identical head size and shoulder width relative to the frame across all generated images.\nThe final image must have a fixed portrait aspect ratio of 3:4 and an exact resolution of 1200 × 1600 pixels. The subject's eyes should always be positioned at approximately the same height (around 28–32% from the top of the frame), with the head occupying approximately 40–50% of the image height, and a clearly visible band of empty background space above the head. Keep consistent margins above the head and on both sides for every image.\nUse a fixed virtual camera setup (50mm portrait lens equivalent, eye-level camera position, standing further back from the subject) and identical lighting, perspective, and composition for every generation. Never change the crop or framing based on hairstyle, body size, clothing, or facial features. Every generated portrait must match the same template so all employee photos appear uniform on ID cards, with the frame always starting at chest level and generous white space above the head.",
|
||||||
|
"images": {
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"binaryPropertyName": "edited"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binaryPropertyName": "logo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.googleGemini",
|
||||||
|
"typeVersion": 1.2,
|
||||||
|
"position": [
|
||||||
|
-416,
|
||||||
|
1104
|
||||||
|
],
|
||||||
|
"id": "7d5ddee1-de8e-487c-a6a4-661b9a093340",
|
||||||
|
"name": "Edit an image1",
|
||||||
|
"credentials": {
|
||||||
|
"googlePalmApi": {
|
||||||
|
"id": "tFqBJras00HUi1hA",
|
||||||
|
"name": "Eidan - Google Gemini(PaLM) Api account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"url": "=https://dbit.digitalcompass.agency/storage/v1/object/public/public-assets/GLM_completo.png",
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"responseFormat": "file",
|
||||||
|
"outputPropertyName": "logo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.4,
|
||||||
|
"position": [
|
||||||
|
-592,
|
||||||
|
976
|
||||||
|
],
|
||||||
|
"id": "5f498427-7d97-4b3a-bf12-182ddafaa61a",
|
||||||
|
"name": "Descargar logo GLM1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"respondWith": "binary",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.respondToWebhook",
|
||||||
|
"typeVersion": 1.5,
|
||||||
|
"position": [
|
||||||
|
-224,
|
||||||
|
1104
|
||||||
|
],
|
||||||
|
"id": "695fe1ac-29bd-44ec-b902-11d8088ee504",
|
||||||
|
"name": "Respond to Webhook"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "image",
|
||||||
|
"operation": "edit",
|
||||||
|
"modelId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "models/gemini-3.1-flash-image",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "models/gemini-3.1-flash-image (Nano Banana 2)"
|
||||||
|
},
|
||||||
|
"prompt": "Professional employee ID card portrait.\n\nUse the first input image (binary: data) as the employee reference. Preserve the exact facial features, identity, hairstyle, skin tone, facial hair, facial expression, and natural proportions of the person. Do not alter the person's appearance.\n\nUse the second input image (binary: logo) as the official company logo. Dress the subject in a Columbia-style outdoor button-up work shirt. The shirt color must be exactly #2d3748. Embroider the provided company logo from the second image on the RIGHT chest (the subject's right side), preserving the original colors, proportions, and details of the logo.\n\nThe subject must be standing completely facing the camera with the head, neck, and shoulders perfectly square to the camera. Both shoulders must be level and symmetrical with no body rotation, tilt, or angled pose. Maintain direct eye contact with the camera.\n\nReplace the background with a clean, solid white seamless studio background. Use soft, even professional studio lighting with minimal shadows and natural skin tones.\n\nFrame the portrait as a tight corporate headshot. Crop from just below the shoulders upward, with the face occupying approximately 65–75% of the image height. Show the complete head, neck, and both shoulders while minimizing the visible torso. Leave a small amount of space above the head and balanced margins on both sides. The composition should prioritize the face while still showing enough of the shirt collar and upper shoulders to look professional.\n\nOnly the upper portion of the shirt should be visible. The collar must be clearly visible. If possible, include only the very top of the embroidered company logo near the lower edge of the frame without reducing the prominence of the face. Never zoom out to show the chest.\n\nPhotorealistic, ultra-high resolution, sharp focus on the eyes and facial features, realistic fabric texture, professional corporate photography, studio quality, natural colors, shallow depth of field with the entire face in sharp focus.\n\nOutput every portrait using exactly the same framing, crop, camera distance, focal length, and canvas size. Do not automatically zoom in or out based on the subject. Maintain identical head size and shoulder width relative to the frame across all generated images.\n\nThe final image must have a fixed portrait aspect ratio of 3:4 and an exact resolution of 1200 × 1600 pixels. The subject's eyes should always be positioned at approximately the same height (around 42% from the top of the frame), with the head occupying approximately 65–70% of the image height. Keep consistent margins above the head and on both sides for every image.\n\nUse a fixed virtual camera setup (85mm portrait lens equivalent, eye-level camera position) and identical lighting, perspective, and composition for every generation. Never change the crop or framing based on hairstyle, body size, clothing, or facial features. Every generated portrait must match the same template so all employee photos appear uniform on ID cards.",
|
||||||
|
"images": {
|
||||||
|
"values": [
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"binaryPropertyName": "logo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.googleGemini",
|
||||||
|
"typeVersion": 1.2,
|
||||||
|
"position": [
|
||||||
|
544,
|
||||||
|
-64
|
||||||
|
],
|
||||||
|
"id": "aae51298-3a4b-4191-be62-b3234e34b40e",
|
||||||
|
"name": "Edit an image2",
|
||||||
|
"credentials": {
|
||||||
|
"googlePalmApi": {
|
||||||
|
"id": "tFqBJras00HUi1hA",
|
||||||
|
"name": "Eidan - Google Gemini(PaLM) Api account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "image",
|
||||||
|
"operation": "edit",
|
||||||
|
"modelId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "models/gemini-3-pro-image",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "models/gemini-3-pro-image (Nano Banana Pro)"
|
||||||
|
},
|
||||||
|
"prompt": "Professional employee ID card portrait.\nUse the first input image (binary: data) as the employee reference. Preserve the exact facial features, identity, hairstyle, skin tone, facial hair, facial expression, and natural proportions of the person. Do not alter the person's appearance.\nUse the second input image (binary: logo) as the official company logo. Dress the subject in a Columbia-style outdoor button-up work shirt. The shirt color must be exactly #2d3748. Embroider the provided company logo from the second image on the RIGHT chest (the subject's right side), preserving the original colors, proportions, and details of the logo.\nThe subject must be standing completely facing the camera with the head, neck, and shoulders perfectly square to the camera. Both shoulders must be level and symmetrical with no body rotation, tilt, or angled pose. Maintain direct eye contact with the camera.\nReplace the background with a clean, solid white seamless studio background. Use soft, even professional studio lighting with minimal shadows and natural skin tones.\nFrame the portrait as a wide corporate headshot that starts from the chest area and goes upward. The bottom edge of the frame must cut across the chest, clearly below the company logo, showing the full chest, both shoulders, neck, and head. Do not start the crop below the chest (no waist, no arms, no hands) — the visible body must begin at chest level at the very bottom edge of the image.\nThe face should occupy approximately 40–50% of the image height, smaller and further back than a tight close-up. Leave generous, clearly visible white/background space above the head — at least 20–25% of the total image height must be empty background between the top of the head and the top edge of the frame. Leave balanced empty margins on both sides as well.\nThe full embroidered company logo on the right chest must be completely visible, clearly readable, and not cropped or cut off by the bottom edge of the frame.\nThe collar, both shoulders, and the upper chest area must all be clearly visible within the frame. Never crop tightly into the face. Never zoom in close on the face; always keep the wider framing described above, with the bottom of the image at chest level and generous white space above the head.\nPhotorealistic, ultra-high resolution, sharp focus on the eyes and facial features, realistic fabric texture, professional corporate photography, studio quality, natural colors, sharp focus throughout the face and upper body.\nOutput every portrait using exactly the same wider framing, crop, camera distance, focal length, and canvas size. Do not automatically zoom in or out based on the subject. Maintain identical head size and shoulder width relative to the frame across all generated images.\nThe final image must have a fixed portrait aspect ratio of 3:4 and an exact resolution of 1200 × 1600 pixels. The subject's eyes should always be positioned at approximately the same height (around 28–32% from the top of the frame), with the head occupying approximately 40–50% of the image height, and a clearly visible band of empty background space above the head. Keep consistent margins above the head and on both sides for every image.\nUse a fixed virtual camera setup (50mm portrait lens equivalent, eye-level camera position, standing further back from the subject) and identical lighting, perspective, and composition for every generation. Never change the crop or framing based on hairstyle, body size, clothing, or facial features. Every generated portrait must match the same template so all employee photos appear uniform on ID cards, with the frame always starting at chest level and generous white space above the head.",
|
||||||
|
"images": {
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"binaryPropertyName": "edited"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binaryPropertyName": "logo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.googleGemini",
|
||||||
|
"typeVersion": 1.2,
|
||||||
|
"position": [
|
||||||
|
-368,
|
||||||
|
1328
|
||||||
|
],
|
||||||
|
"id": "32b46579-d7f9-43bc-b27b-b25504f67d26",
|
||||||
|
"name": "Edit an image3",
|
||||||
|
"credentials": {
|
||||||
|
"googlePalmApi": {
|
||||||
|
"id": "tFqBJras00HUi1hA",
|
||||||
|
"name": "Eidan - Google Gemini(PaLM) Api account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"name": "={{ $json.employeeId }}",
|
||||||
|
"driveId": {
|
||||||
|
"__rl": true,
|
||||||
|
"mode": "list",
|
||||||
|
"value": "My Drive"
|
||||||
|
},
|
||||||
|
"folderId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "1Gf4XInkmYErR1OhjplQg-kdH74qEBtEk",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "Fotos Temporal Carnet Empleados",
|
||||||
|
"cachedResultUrl": "https://drive.google.com/drive/folders/1Gf4XInkmYErR1OhjplQg-kdH74qEBtEk"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.googleDrive",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
-16,
|
||||||
|
64
|
||||||
|
],
|
||||||
|
"id": "404efdda-ae45-4b67-a584-bca58e08ec88",
|
||||||
|
"name": "Guardar foto",
|
||||||
|
"credentials": {
|
||||||
|
"googleDriveOAuth2Api": {
|
||||||
|
"id": "gL2ZTwJb6xojauac",
|
||||||
|
"name": "Eidan - Google Drive account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "share",
|
||||||
|
"fileId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "={{ $json.webViewLink }}",
|
||||||
|
"mode": "url"
|
||||||
|
},
|
||||||
|
"permissionsUi": {
|
||||||
|
"permissionsValues": {
|
||||||
|
"role": "reader",
|
||||||
|
"type": "anyone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.googleDrive",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
144,
|
||||||
|
64
|
||||||
|
],
|
||||||
|
"id": "0d598bda-4b27-4539-b989-222253918b93",
|
||||||
|
"name": "Guardar foto1",
|
||||||
|
"credentials": {
|
||||||
|
"googleDriveOAuth2Api": {
|
||||||
|
"id": "gL2ZTwJb6xojauac",
|
||||||
|
"name": "Eidan - Google Drive account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"name": "={{ $('Webhook1').item.json.body.employeeId }}",
|
||||||
|
"driveId": {
|
||||||
|
"__rl": true,
|
||||||
|
"mode": "list",
|
||||||
|
"value": "My Drive"
|
||||||
|
},
|
||||||
|
"folderId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "1Gf4XInkmYErR1OhjplQg-kdH74qEBtEk",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "Fotos Temporal Carnet Empleados",
|
||||||
|
"cachedResultUrl": "https://drive.google.com/drive/folders/1Gf4XInkmYErR1OhjplQg-kdH74qEBtEk"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.googleDrive",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
-1344,
|
||||||
|
176
|
||||||
|
],
|
||||||
|
"id": "698c9524-999a-4e7c-86f8-801e739a3789",
|
||||||
|
"name": "Guardar foto2",
|
||||||
|
"credentials": {
|
||||||
|
"googleDriveOAuth2Api": {
|
||||||
|
"id": "gL2ZTwJb6xojauac",
|
||||||
|
"name": "Eidan - Google Drive account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"content": "## Descarga masiva de foto de perfil para empleados\n\nEste flujo guarda temporalmente la foto del link de\nGoogle Drive en la tabla empleados_glm temporalmente \nhasta que tenga foto en BambooHR",
|
||||||
|
"height": 880,
|
||||||
|
"width": 1584
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.stickyNote",
|
||||||
|
"position": [
|
||||||
|
-640,
|
||||||
|
-176
|
||||||
|
],
|
||||||
|
"typeVersion": 1,
|
||||||
|
"id": "aa7003e6-969f-4250-8229-a4b820e3f70e",
|
||||||
|
"name": "Sticky Note"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"content": "## Descarga individual de foto de perfil para empleados\n\nAl subir una foto de empleado en el campo \"Subir foto del colaborador\" en vista previa en tiempo real\nla foto llega a este flujo y se edita con IA.",
|
||||||
|
"height": 480,
|
||||||
|
"width": 640,
|
||||||
|
"color": 6
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.stickyNote",
|
||||||
|
"position": [
|
||||||
|
-640,
|
||||||
|
768
|
||||||
|
],
|
||||||
|
"typeVersion": 1,
|
||||||
|
"id": "a3becf7e-93de-4356-afaa-f48e46525e40",
|
||||||
|
"name": "Sticky Note1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"content": "## Guardar temporalmente foto en Google Drive en supabase\n\nEste flujo se activa al clickear el boton de descargar en vista previa en tiempo real. \nLo que hace es guardar la foto con el employeeId como nombre de archivo.",
|
||||||
|
"height": 480,
|
||||||
|
"width": 736,
|
||||||
|
"color": 6
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.stickyNote",
|
||||||
|
"position": [
|
||||||
|
-1584,
|
||||||
|
-80
|
||||||
|
],
|
||||||
|
"typeVersion": 1,
|
||||||
|
"id": "28012bbc-2b4b-4561-984e-dcd43470929d",
|
||||||
|
"name": "Sticky Note2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"conditions": {
|
||||||
|
"options": {
|
||||||
|
"caseSensitive": true,
|
||||||
|
"leftValue": "",
|
||||||
|
"typeValidation": "strict",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"id": "30a53e6f-395e-418a-ac50-98b881dbccd1",
|
||||||
|
"leftValue": "={{ $json.body.data && $json.body.employeeId }}",
|
||||||
|
"rightValue": "",
|
||||||
|
"operator": {
|
||||||
|
"type": "string",
|
||||||
|
"operation": "exists",
|
||||||
|
"singleValue": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"combinator": "and"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.if",
|
||||||
|
"typeVersion": 2.3,
|
||||||
|
"position": [
|
||||||
|
-1904,
|
||||||
|
656
|
||||||
|
],
|
||||||
|
"id": "f43d07e0-ac3d-462e-837a-b8f8d0e1c224",
|
||||||
|
"name": "Es un binario y employeeId?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "toBinary",
|
||||||
|
"sourceProperty": "body.data",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.convertToFile",
|
||||||
|
"typeVersion": 1.1,
|
||||||
|
"position": [
|
||||||
|
-1520,
|
||||||
|
176
|
||||||
|
],
|
||||||
|
"id": "5d00eb25-ab9f-4851-83bb-a6363a36ad90",
|
||||||
|
"name": "Convert to File"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "share",
|
||||||
|
"fileId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "={{ $json.webViewLink }}",
|
||||||
|
"mode": "url"
|
||||||
|
},
|
||||||
|
"permissionsUi": {
|
||||||
|
"permissionsValues": {
|
||||||
|
"role": "reader",
|
||||||
|
"type": "anyone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.googleDrive",
|
||||||
|
"typeVersion": 3,
|
||||||
|
"position": [
|
||||||
|
-1184,
|
||||||
|
176
|
||||||
|
],
|
||||||
|
"id": "02e9a57b-436f-4625-851c-cc6789a92bd7",
|
||||||
|
"name": "Hacer url publica",
|
||||||
|
"credentials": {
|
||||||
|
"googleDriveOAuth2Api": {
|
||||||
|
"id": "gL2ZTwJb6xojauac",
|
||||||
|
"name": "Eidan - Google Drive account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "update",
|
||||||
|
"tableId": "empleados_glm",
|
||||||
|
"filters": {
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"keyName": "cedula",
|
||||||
|
"condition": "eq",
|
||||||
|
"keyValue": "={{ $('Loop Over Items').item.json.employeeId }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fieldsUi": {
|
||||||
|
"fieldValues": [
|
||||||
|
{
|
||||||
|
"fieldId": "photo_url",
|
||||||
|
"fieldValue": "={{ $('Guardar foto').item.json.webViewLink }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldId": "photo_uploaded",
|
||||||
|
"fieldValue": "FALSE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.supabase",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
304,
|
||||||
|
64
|
||||||
|
],
|
||||||
|
"id": "c5b12702-fc99-4501-884f-0fdb3ace2999",
|
||||||
|
"name": "Actualizar foto del empleado",
|
||||||
|
"credentials": {
|
||||||
|
"supabaseApi": {
|
||||||
|
"id": "2PlsR6rpK7rQTIEn",
|
||||||
|
"name": "Sofia test - Supabase account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "update",
|
||||||
|
"tableId": "empleados_glm",
|
||||||
|
"filters": {
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"keyName": "cedula",
|
||||||
|
"condition": "eq",
|
||||||
|
"keyValue": "={{ $('Webhook1').item.json.body.employeeId }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fieldsUi": {
|
||||||
|
"fieldValues": [
|
||||||
|
{
|
||||||
|
"fieldId": "photo_url",
|
||||||
|
"fieldValue": "={{ $('Guardar foto2').item.json.webViewLink }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldId": "photo_uploaded",
|
||||||
|
"fieldValue": "FALSE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.supabase",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
-1024,
|
||||||
|
176
|
||||||
|
],
|
||||||
|
"id": "2a4698ea-98dd-49e5-b220-8e2ed451565b",
|
||||||
|
"name": "Actualizar foto del empleado1",
|
||||||
|
"credentials": {
|
||||||
|
"supabaseApi": {
|
||||||
|
"id": "2PlsR6rpK7rQTIEn",
|
||||||
|
"name": "Sofia test - Supabase account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pinData": {},
|
||||||
|
"connections": {
|
||||||
|
"Webhook1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Es un binario y employeeId?",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Download file": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit an image",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Guardar foto",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Descargar logo GLM",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Descargar logo GLM": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit an image",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Split Out": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Loop Over Items",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Edit an image": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Extract from File",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Respond to Webhook1": {
|
||||||
|
"main": [
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Loop Over Items": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Respond to Webhook1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Download file",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Merge",
|
||||||
|
"type": "main",
|
||||||
|
"index": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Merge": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Loop Over Items",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Extract from File": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Merge",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Es un binario?": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Split Out",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit an image1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Descargar logo GLM1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Descargar logo GLM1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit an image1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Edit an image1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Respond to Webhook",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Guardar foto": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Guardar foto1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Guardar foto1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Actualizar foto del empleado",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Guardar foto2": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Hacer url publica",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Respond to Webhook": {
|
||||||
|
"main": [
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Es un binario y employeeId?": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Convert to File",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Es un binario?",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Convert to File": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Guardar foto2",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Hacer url publica": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Actualizar foto del empleado1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Actualizar foto del empleado": {
|
||||||
|
"main": [
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": true,
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1",
|
||||||
|
"binaryMode": "separate",
|
||||||
|
"timeSavedMode": "fixed",
|
||||||
|
"callerPolicy": "workflowsFromSameOwner",
|
||||||
|
"availableInMCP": false
|
||||||
|
},
|
||||||
|
"versionId": "e67d854e-7e97-4afc-ae89-21a636dc9bcd",
|
||||||
|
"meta": {
|
||||||
|
"templateCredsSetupCompleted": true,
|
||||||
|
"instanceId": "b4b77b17af092830e794eef639ce2f6d7daccf7eddc075060b03b3b6545aac70"
|
||||||
|
},
|
||||||
|
"id": "D7X6KqXqTCXz9SY0",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user