Histórico da Página
| HTML |
|---|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.release-notes-container* {
font-familymargin: Arial, sans-serif0;
max-widthpadding: 1200px0;
marginbox-sizing: 0 autoborder-box;
padding: 20px;}
}
.headerbody {
background: linearfont-family: 'Segoe UI', Arial, sans-serif;
background: linear-gradient(135deg, #667eea#f5f7fa 0%, #764ba2#c3cfe2 100%);
colormin-height: white100vh;
padding: 20px;
}
border-radius: 8px;
margin-bottom: 20px;.release-notes-wrapper {
}
.header h1 {max-width: 1400px;
margin: 0 auto;
font-sizebackground: 24pxwhite;
}
border-radius: 12px;
.metadata {
box-shadow: 0 10px 40px rgba(0, background-color: #f4f5f70, 0, 0.15);
paddingoverflow: 15pxhidden;
}
border-radius: 5px;
.header {
margin: 20px 0;
background: linear-gradient(135deg, #667eea 0%, display: flex#764ba2 100%);
justify-contentcolor: space-betweenwhite;
flex-wrappadding: wrap30px 40px;
}
.metadata-item {border-radius: 0;
margin-bottom: 5px 0;
}
position: relative;
.metadata-item strong {
overflow: hidden;
color: #667eea;}
}
.widget-containerheader::before {
margincontent: 20px 0'';
borderposition: 1px solid #dddabsolute;
border-radiustop: 5px-50%;
overflowright: hidden-10%;
}
.loading {width: 500px;
text-alignheight: center500px;
padding: 40pxbackground: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
colorborder-radius: #66650%;
}
.error {
.header background-color: #fee;h1 {
colormargin: #c330;
paddingfont-size: 15px32px;
borderfont-radiusweight: 5px600;
margin: 20px 0;}
}
.linksmetadata {
marginbackground: 20px 0;
linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
}
padding: .links a {20px 40px;
display: inline-blockborder-bottom: 1px solid #dee2e6;
margindisplay: 5px 10px 5px 0flex;
paddingalign-items: 8px 15pxcenter;
background-colorgap: #0052CC30px;
colorflex-wrap: white;wrap;
}
text-decoration: none.metadata-item {
display: flex;
borderalign-radiusitems: 4pxcenter;
font-weightgap: bold10px;
}
.links a:hover .metadata-item strong {
background-color: #0065FF#495057;
}
</style>
</head>
<body>font-weight: 600;
}
<div class="release-notes-container">
.metadata-item <div class="header">span {
<h1 id="page-title">Release Notes</h1>color: #0A2333;
</div>
background: white;
<div class="metadata">
padding: 6px 14px;
<div class="metadata-item"> border-radius: 6px;
font-weight: 600;
<strong>Versão:</strong> <span id="version">Carregando...</span>
box-shadow: 0 2px 4px rgba(0, 0, </div>0, 0.05);
}
<div class="metadata-item">
#widget-container {
<strong>Última atualização:</strong> <span id="last-update">-</span>
padding: 0;
</div>
min-height: 700px;
</div>
background: #ffffff;
<div class="links" id="links-container">}
<!-- Links serão inseridos aqui -->.message-box {
</div>
padding: 40px;
<div class="widget-container">
text-align: center;
background: linear-gradient(135deg, #fff3cd <div id="loading" class="loading">0%, #ffe69c 100%);
margin: 30px;
🔄 Carregando documento...border-radius: 10px;
</div>
border-left: 5px solid #ffc107;
<div id="error" class="error" style="display: none;"></div>
<div id="widget-placeholder"></div> box-shadow: 0 4px 12px rgba(255, 193, 7, 0.2);
</div>}
</div>
<script>
(function().message-box.error {
// Função para extrair versão do título da página
background: linear-gradient(135deg, #fee 0%, #fcc 100%);
border-left-color: #dc3545;
function getVersionFromPage() {
box-shadow: 0 4px 12px rgba(220, 53, 69, // Tenta várias formas de obter o título da página0.2);
}
let version = null;.message-box h2 {
color: #856404;
margin-bottom: 15px;
// Método 1: Título da página (Confluence)
font-size: 24px;
}
const pageTitle = document.querySelector('h1#title-text, .page-title, h1');
.message-box.error h2 {
if (pageTitle) {
color: #721c24;
}
version = pageTitle.textContent.trim();
.message-box p {
}
color: #856404;
font-size: 16px;
// Método 2: Meta tagsline-height: 1.6;
}
if (!version) {
.message-box.error p {
const metaTitle = document.querySelector('meta[property="og:title"], meta[name="title"]') color: #721c24;
}
if (metaTitle) .message-icon {
font-size: 48px;
version = metaTitle.getAttribute('content')margin-bottom: 15px;
display: block;
}
}iframe {
border: none;
width: 100%;
// Método 3: URL (fallback)
height: 800px;
if (!version) {display: block;
}
const urlParams = new URLSearchParams(window.location.search);.loading {
text-align: center;
const titleParam = urlParams.get('title');
padding: 60px 20px;
color: #6c757d;
if (titleParam) {
font-size: 18px;
}
version
= decodeURIComponent(titleParam);
.loading::before {
content: }'';
}display: block;
width: 50px;
height: 50px;
// Limpar versão (remover prefixos comuns)
margin: 0 auto 20px;
border: if4px (version) {solid #e9ecef;
border-top-color: #667eea;
version = version border-radius: 50%;
animation: spin 1s linear infinite;
.replace(/^Release Notes\s*[-:]?\s*/i, '')}
@keyframes spin {
from .replace(/^Release\s*Notes\s*/i, ''){ transform: rotate(0deg); }
to { transform: rotate(360deg); }
.trim();}
}
@media (max-width: 768px) {
body {
returnpadding: version10px;
}
// Função para construir URL do Google Doc
.header {
padding: 20px;
function getGoogleDocUrl(version) {
}
// Padrão: versão.txt ou apenas versão
.header h1 {
const docName = version.endsWith('.txt') ? version : version + '.txt';
font-size: 24px;
}
// ID do folder do Google Drive (do seu.metadata config){
constpadding: folderId = '141aJRhZeYZca4QCBnou6-00WzRLkBYbs'15px 20px;
flex-direction: column;
// URL base do Google Drive
align-items: flex-start;
}
}
const baseUrl = 'https://drive.google.com/drive/folders/' + folderId;</style>
</head>
<body>
<div class="release-notes-wrapper">
<div class="header">
<h1 id="page-title">Dicionário de // Retornar URL de busca (será usado para encontrar o documento)Dados</h1>
</div>
return {<div class="metadata">
searchUrl: baseUrl,<div class="metadata-item">
docName: docName,<strong>Versão:</strong>
version: version<span id="version-display">Carregando...</span>
</div>
};
}<div class="metadata-item">
<strong>Última atualização:</strong>
// Função para criar Widget Connector
<span id="last-update">-</span>
function createWidgetConnector(docUrl) {
</div>
</div>
// URL completa do Google Doc
<div id="widget-container">
const fullUrl<div class= docUrl;"loading">Carregando documento...</div>
</div>
</div>
<script>
(function() {
// CriarMapeamento de iframeversões comopara fallbackDocument (casoIDs Widgetdo ConnectorGoogle nãoDocs funcione)
e arquivos .txt
// Gerado constautomaticamente iframea = document.createElement('iframe');partir da pasta: 141aJRhZeYZca4QCBnou6-00WzRLkBYbs
// Data: 2025-12-16
iframe.src = fullUrl.replace('/edit', '/preview');
// Total: 62 versões (2 Google Docs + 60 arquivos iframe.widthtxt - = '100%';todos funcionando!)
const versionToDocId = {
iframe.height = '800';
// Google iframe.style.border = 'none';Docs (2)
iframe.style.borderRadius = '5px';'12.1.2503.14': '13QaSU_lP1_haWnOYl7UjPvsKfi3AaPdKwciYHrceEt4',
iframe.allow = 'fullscreen';'12.1.2511.2': '1gLo16QDT99iGdaoKyFHBW1n5jF-gt-awBjnSQrBZa3c',
// TentarArquivos usar Widget Connector do Confluence
.txt (60) - funcionando diretamente no Widget Connector
const widgetCode = `
'12.1.2503': '1BRsJyHOHQNOEpAfIm5ndOn6z_0gffbaF',
'12.1.2503.15': '12ejZuDikegyaH2n16n2Hpas1Z3VEjc5e',
<ac:structured-macro ac:name="widget" ac:schema-version="1">
'12.1.2503.16': '15BkT50wXw7kJccfw4iRB-LVGQyTzQVf1',
<ac:parameter ac:name="url">${fullUrl}</ac:parameter>
'12.1.2503.17': '1L4FUKbDjnAs29rK0ymfMgRVJPPVtzYdW',
'12.1.2503.18': '1LNSFua5jsEw9m2D4X7lBVsbk6qXsG3cm',
<ac:parameter ac:name="width">100%</ac:parameter>
'12.1.2507': '1pT42y90cnf2UY2gK5k035jEFVkIs7s-n',
<ac:parameter ac:name="height">800</ac:parameter>'12.1.2507.1': '1lo7KiRJGWYJFfH-Xqv-dvNcRoIy6ecj3',
'12.1.2507.2': '1xe9L8cCurcXIw5tzxe4H9KNzFgpIObA1',
</ac:structured-macro>
'12.1.2507.3': '1P9jEM2cgtUkyfdK5bsKlSvFCk_SqpMqU',
`;
'12.1.2507.4': '12Qk7mEnEe2iIsE-nFUUGOmbt_t8rwjn-',
// Se estiver em modo de edição, retornar código do macro'12.1.2507.5': '1ljgI7Re2mT3yv7TgnZLOZv_n0vzzJTxF',
// Se estiver em visualização, usar iframe'12.1.2507.6': '1lwblHVXZUKF8qgdajVB2Va41fxpJkZ9X',
return {'12.1.2507.7': '1LWO9GFD8iO6HQEJn_wBybP1EdZ2AZSsD',
widgetCode: widgetCode'12.1.2507.8': '1bhB3Pig68EAvmXGoUptLYnJPEnGW4fVr',
iframe: iframe'12.1.2507.9': '1shjpLbeGfQmrV6DMtm4EuIvqdhHTuEIy',
directUrl: fullUrl'12.1.2507.10': '1wU40XkkEMRqw4Ieanf5QrkBz8SwqISzj',
};'12.1.2507.11': '1goM3M1WCXvtdx46fY7ZmeeDtwpnvbld5',
}
'12.1.2507.12': '15r-G5LdQpPn9gcktkpYVPQS1exs6Io8t',
// Função principal
'12.1.2507.13': '1xVHx0mjDewGUVwIGR8GWqTMqX1R_Cj21',
function init() { '12.1.2507.14': '1uFblMZhJaYPFrGKtFCC9bAa-2xxtXmi_',
const version = getVersionFromPage();
'12.1.2507.15': '1vNN6ONnbq1ApNJy6uzGW_hZ27HvhW7Dd',
'12.1.2507.16': '1g27jhn6ZEliSZhAJ7Co9FUFLtNBfqVHH',
if (!version) {'12.1.2507.17': '1LkwBvxVy_oykf3gEAwlf2eRn0NMiMnL1',
document.getElementById('error').style.display = 'block';'12.1.2507.18': '1he66XmpG6YhgKlxtMv3xik6KccuMKLeS',
'12.1.2511': '1gPiO2P_mF0wpLX-2g5oFBqi4QS630wKM',
document.getElementById('error').textContent =
'12.1.2511.1': '1yv4EZZKrfPgI-RWggMfBANtx6dL8owhA',
'❌ Não foi possível identificar a versão da página. Certifique-se de que o título da página contém a versão (ex: '12.1.2511.3': '14Zd-Npn6VGioc1wsokDL4vfPRVzhb-AY',
'12.1.2511.2)';4': '1VjoqjmjqCokx4Kv5QDTDa9wZsF1QwICY',
document.getElementById('loading').style.display = 'none';'12.1.2511.5': '1evpMFJmgDUFX__dC6W83LZqKQXjmy88s',
return;
'12.1.2511.6': '1_e3AgOsc9Oqy-JoZhus-zyU-961karvw',
}'12.1.2511.7': '19TKZ4fYof03H0pdzldQnV7_ZYjxowkNr',
'12.1.2511.8': '12ivR5sJUwVwcRJr0Q_aHBT_y4JwlnTd4',
// Atualizar interface'12.1.2511.9': '1Exio4F5z2lo6HnEnLpkDquuu8HUiD3C-',
document.getElementById('version').textContent = version;'12.1.2511.10': '1NRs4aZct5OVmSiXDPgMmUw9iFURlC6Od',
document.getElementById('page-title').textContent = `Release Notes - ${version}`;
'12.1.2511.11': '1AAOtpmIahaHaYYUtUFL3OJGJ07dTKLU_',
'12.1.2511.12': '1c19qwsUQdWb_H58qcamAQ6Fz9Bwg78Bs',
document.getElementById('last-update').textContent = new Date().toLocaleString('pt-BR');
'12.1.2511.13': '1CS-VXZJLzPSBjov0r4JVAcTPE5daaE4M',
'12.1.2511.14': '1dei-4_gijuPsGzSQKZpIh9DMCYJ2pw8j',
// Construir URLs'12.1.2511.15': '1qDv9Zm_0CJiKl6iJBzxVxwFCoHNZBky4',
const docInfo = getGoogleDocUrl(version);
'12.1.2511.16': '1H51vcp3ierWZE0XB1QEtzUnm0J-0uEVp',
'12.1.2511.17': '1OwFzjD6j4_OlDi9x7f5xqqoBo_eKY1rd',
// URL do Google Doc (assumindo que o nome do arquivo é a versão)
'12.1.2511.18': '1iaMmEP6yDzHR4oTM_SjM2obkaUz1zrBA',
'12.1.2603.1': '19iieXcJNDoIM8lp09Zd-faD22AWepfTC',
// Você precisará mapear versão -> document ID ou usar busca '12.1.2603.2': '1DFR1cWRUVm3PsPQsVbuJySIjxMIy085L',
const googleDocUrl = `https://docs.google.com/document/d/[DOCUMENT_ID]/edit?usp=sharing`;'12.1.2603.3': '1PLCl8hhtuvnW8Q9WDug9NH9F_qO-CUoq',
'12.1.2603.4': '1qFmELYGulpQizNrXFBCpHdcLOSC5LrsZ',
// Criar links'12.1.2603.5': '1Q8ZSMOooNeSgmfdEucEsRO6P8z370enZ',
const linksContainer = document.getElementById('links-container');'12.1.2603.6': '1P5-nq151raX-NhYufnTRrZMZyeAKsSp2',
linksContainer.innerHTML = `'12.1.2603.7': '1VfNdP7lRvi37ZKSOzX1KyEp6dK_t0I-N',
'12.1.2603.8': '1pxJPuMKfOWXrkwS7zzmm_3i_GerA44Zi',
<a href="${googleDocUrl}" target="_blank">📄 Abrir no Google Docs</a>
'12.1.2603.9': '1evoXM_3WvL4SGVkwB8EYgwXuD6E4Asmw',
<a href="https://drive.google.com/drive/folders/141aJRhZeYZca4QCBnou6-00WzRLkBYbs" target="_blank">📁 Pasta Release Notes</a>
'12.1.2603.10': '18tytubaH1oywQoWyAycMM-qMq_347CHb',
'12.1.2603.11': '1ORyeFI8qYQynt20Ud66XLKewYQoVdLA6',
<a href="https://tdn.totvs.com/pages/viewpage.action?pageId=649987902" target="_blank">📚 Release Notes Principal</a>
'12.1.2603.12': '1gDfH7fyZSUGl90ikqO3yXsZGm_EXC4PW',
'12.1.2607.1': '1ruRPs4fBJrKpLoECMGh0X5Ca4Bc_hfPb',
'12.1.2607.2': '1njYTB38Ts6_dAZKvkqdvdQcPx99HTRml',
'12.1.2607.3': '1uQR-2_JLet0Cyo7K6XaClDaXqxBu7udV',
'12.1.2607.4': '1G41yiKUzoWgIrbQATlhYntb73FSH9U76',
'12.1.2607.5': '1_BfY0poM0AeAFy39vK-XZmBhEafIzzBf',
'12.1.2607.6': '1cm7WuMWrQYjGDdeMdmdAqIFX5ugROaHY',
};
// Função para extrair versão do título "Dicionário de Dados 12.1.2503.14"
function getPageVersion() {
const versionPattern = /(\d+\.\d+\.\d+(?:\.\d+)?)/;
// Método 1: Título da página (Confluence)
const selectors = [
'h1#title-text',
'.page-title',
'h1',
'[data-page-title]'
];
for (const selector of selectors) {
const element = document.querySelector(selector);
if (element) {
const text = element.textContent.trim();
const match = text.match(versionPattern);
if (match) {
return match[1];
}
}
}
// Método 2: Meta tags
const metaTitle = document.querySelector('meta[property="og:title"], meta[name="title"]');
if (metaTitle) {
const titleText = metaTitle.getAttribute('content') || '';
const match = titleText.match(versionPattern);
if (match) {
return match[1];
}
}
// Método 3: document.title
const titleMatch = document.title.match(versionPattern);
if (titleMatch) {
return titleMatch[1];
}
// Método 4: URL (fallback)
const urlParams = new URLSearchParams(window.location.search);
const titleParam = urlParams.get('title');
if (titleParam) {
const match = decodeURIComponent(titleParam).match(versionPattern);
if (match) {
return match[1];
}
}
return null;
}
// Obter versão
const version = getPageVersion();
const container = document.getElementById('widget-container');
if (!version) {
container.innerHTML = `
<div class="message-box error">
<span class="message-icon">❌</span>
<h2>Versão não identificada</h2>
<p>Certifique-se de que o título da página contém a versão no formato:<br>
<strong>"Dicionário de Dados 12.1.2503.14"</strong></p>
</div>
`;
return;
}
// Atualizar display
document.getElementById('version-display').textContent = version;
document.getElementById('page-title').textContent = `Dicionário de Dados ${version}`;
document.getElementById('last-update').textContent = new Date().toLocaleString('pt-BR');
// Obter Document ID
const docId = versionToDocId[version];
if (!docId) {
container.innerHTML = `
<div class="message-box">
<span class="message-icon">📋</span>
<h2>Release Notes ainda não foi expedido para essa versão</h2>
<p>O Release Notes para a versão <strong>${version}</strong> ainda não foi expedido.<br>
Aguarde a expedição ou verifique se a versão está correta.</p>
</div>
`;
return;
}
// Construir URL do Google Doc
const googleDocUrl = `https://docs.google.com/document/d/${docId}/edit?usp=sharing`;
const previewUrl = `https://docs.google.com/document/d/${docId}/preview`;
// Verificar se está em modo de edição (Confluence)
if (window.location.href.includes('editpage.action') || window.location.href.includes('edit')) {
// Modo de edição: mostrar código do macro Widget Connector
const widgetCode = `<ac:structured-macro ac:name="widget" ac:schema-version="1">
<ac:parameter ac:name="url">${googleDocUrl}</ac:parameter>
<ac:parameter ac:name="width">100%</ac:parameter>
<ac:parameter ac:name="height">800</ac:parameter>
</ac:structured-macro>`;
container.innerHTML = `
<div style="padding: 30px 40px;">
<div style="background: #f4f5f7; padding: 20px; border-radius: 8px; margin-bottom: 15px;">
<h3 style="margin-bottom: 15px; color: #495057;">📋 Código do Widget Connector:</h3>
<pre style="background: white; padding: 15px; border-radius: 5px; overflow-x: auto; font-size: 13px; border: 1px solid #dee2e6;">${widgetCode}</pre>
</div>
<p style="color: #6c757d; font-size: `14px;">
💡 <strong>Instruções:</strong> Copie o código acima e cole //no Criareditor widget
do Confluence usando o macro "Widget Connector".
const widget = createWidgetConnector(googleDocUrl);
</p>
const placeholder = document.getElementById('widget-placeholder');
</div>
`;
// Tentar inserir Widget Connector (se em modo} deelse edição){
// Modo Casode contrário,visualização: usar iframe
const iframe = placeholderdocument.appendChildcreateElement(widget.'iframe');
iframe.src = previewUrl;
document.getElementById('loading').style.displayiframe.width = 'none100%';
}
iframe.height = '800';
iframe.allow // Executar quando a página carregar
= 'fullscreen';
iframe.title if (document.readyState === 'loading') {
= `Dicionário de Dados ${version}`;
document.addEventListener('DOMContentLoaded', init);
}container.innerHTML else= {'';
initcontainer.appendChild(iframe);
}
})();
</script>
</body>
</html> |
Visão Geral
Import HTML Content
Conteúdo das Ferramentas
Tarefas