Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.


HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        *.release-notes-container {
            margin: 0font-family: Arial, sans-serif;
            paddingmax-width: 01200px;
            box-sizingmargin: 0 border-boxauto;
        }    padding: 20px;
        }
        body.header {
            font-familybackground: 'Segoe UI', Arial, sans-seriflinear-gradient(135deg, #667eea 0%, #764ba2 100%);
            backgroundcolor: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)white;
            min-heightpadding: 100vh20px;
            paddingborder-radius: 20px8px;
        }
        margin-bottom: 20px;
        .release-notes-wrapper {}
        .header    max-width: 1400px;h1 {
            margin: 0 auto;
            backgroundfont-size: white24px;
        }
    border-radius: 12px;    .metadata {
            boxbackground-shadowcolor: 0 10px 40px rgba(0, 0, 0, 0.15)#f4f5f7;
            overflowpadding: hidden15px;
        }
    border-radius: 5px;
     
       margin: .header20px {0;
            backgrounddisplay: linear-gradient(135deg, #667eea 0%, #764ba2 100%)flex;
            colorjustify-content: whitespace-between;
            paddingflex-wrap: 30px 40pxwrap;
        }
      border-radius: 0;  .metadata-item {
            margin-bottom: 5px 0;
        }
    position: relative;
   .metadata-item strong {
       overflow: hidden;
       color: }#667eea;
        }
        .header::beforewidget-container {
            contentmargin: ''20px 0;
            positionborder: 1px absolutesolid #ddd;
            topborder-radius: -50%5px;
            rightoverflow: -10%hidden;
        }
    width: 500px;    .loading {
            heighttext-align: 500pxcenter;
            background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%)padding: 40px;
            border-radiuscolor: 50%#666;
        }
        
        .header-content.error {
            positionbackground-color: relative#fee;
            z-indexcolor: 1#c33;
            displaypadding: flex15px;
            alignborder-itemsradius: center5px;
            gapmargin: 20px 0;
        }
        .links {
        .totvs-logo {
   margin: 20px 0;
       display: flex;}
        .links    align-items: center;a {
            gapdisplay: 12pxinline-block;
            flex-shrink:margin: 5px 10px 5px 0;
        }
    padding: 8px 15px;
   
         .totvsbackground-iconcolor: {#0052CC;
            widthcolor: 50pxwhite;
            heighttext-decoration: 50pxnone;
            backgroundborder-radius: white4px;
            borderfont-radiusweight: 8pxbold;
            display: flex;}
            align-items: center;.links a:hover {
            justifybackground-contentcolor: center#0065FF;
        }
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
</style>
</head>
<body>
    <div class="release-notes-container">
          }<div class="header">
        
    <h1 id="page-title">Release Notes</h1>
  .totvs-icon svg {
    </div>
        width:
 32px;
       <div class="metadata">
    height: 32px;
        }<div class="metadata-item">
        
        .totvs-text {<strong>Versão:</strong> <span id="version">Carregando...</span>
            font-size: 24px;
</div>
             font-weight: 700;<div class="metadata-item">
            letter-spacing: 2px;
   <strong>Última atualização:</strong> <span id="last-update">-</span>
  }
        
  </div>
      .header h1 {</div>
        
    margin: 0;
   <div class="links" id="links-container">
       font-size: 32px;
    <!-- Links serão inseridos aqui -->
   font-weight: 600;
    </div>
        flex:
 1;
        }<div class="widget-container">
        
    <div id="loading" class="loading">
  .metadata {
            background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); 🔄 Carregando documento...
            padding: 20px 40px;</div>
            border-bottom: 1px solid #dee2e6;<div id="error" class="error" style="display: none;"></div>
            display: flex;<div id="widget-placeholder"></div>
        </div>
    align-items: center;</div>

    <script>
        gap: 30px;(function() {
            flex-wrap: wrap;
        }// Função para extrair versão do título da página
        
    function getVersionFromPage() {
  .metadata-item {
              // display: flex;
       Tenta várias formas de obter o título da página
     align-items: center;
          let version gap:= 10pxnull;
        }
        
        .metadata-item strong {
       // Método 1: Título da color: #495057;página (Confluence)
            font-weight: 600;
   const pageTitle = document.querySelector('h1#title-text,  }
.page-title, h1');
        
        .metadata-item spanif (pageTitle) {
            color: #0A2333;
       version     background: white= pageTitle.textContent.trim();
            padding: 6px 14px;
  }
          border-radius: 6px;
       
     font-weight: 600;
          // Método box-shadow2: 0Meta 2pxtags
 4px rgba(0, 0, 0, 0.05);
        }
   if (!version) {
   
        #widget-container {
        const metaTitle   padding: 0;
= document.querySelector('meta[property="og:title"], meta[name="title"]');
               min-height: 700px;
    if (metaTitle) {
      background: #ffffff;
        }
        
 version = metaTitle.getAttribute('content');
      .message-box {
            padding: 40px;}
            text-align: center;
   }
         background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%);
  
          margin: 30px;
     // Método 3: URL (fallback)
   border-radius: 10px;
            border-left: 5px solid #ffc107;if (!version) {
            box-shadow: 0 4px 12px rgba(255, 193, 7, 0.2);
  const urlParams = new URLSearchParams(window.location.search);
   }
           
      const titleParam .message-box.error {= urlParams.get('title');
            background: linear-gradient(135deg, #fee 0%, #fcc 100%);
    if (titleParam) {
      border-left-color: #dc3545;
            box-shadow: 0 4px 12px rgba(220, 53, 69, 0.2 version = decodeURIComponent(titleParam);
        }
        
    }
    .message-box h2 {
          }
  color: #856404;
            margin-bottom: 15px;
            font-size: 24px;
   // Limpar versão (remover prefixos }comuns)
        
        .message-box.error h2if (version) {
            color: #721c24;
       version }
        = version
        .message-box p {
            color: #856404;
   .replace(/^Release Notes\s*[-:]?\s*/i, '')
          font-size: 16px;
            line-height: 1.6;.replace(/^Release\s*Notes\s*/i, '')
        }
        
        .message-box.error p {
trim();
               color: #721c24;}
        }
        
        .message-icon {
        return version;
      font-size: 48px;      }
            margin-bottom: 15px;
            display: block;
        }
// Função para construir URL do Google Doc
          
  function getGoogleDocUrl(version) {
    iframe {
           // borderPadrão: none;
   versão.txt ou apenas versão
         width: 100%;
      const docName = version.endsWith('.txt') ? version height: 800px version + '.txt';
            display: block;
          }
        
        .loading {
        // ID do folder do Google Drive (do seu config)
    text-align: center;
           const padding:folderId 60px 20px= '141aJRhZeYZca4QCBnou6-00WzRLkBYbs';
            color: #6c757d;
   
         font-size: 18px;
      // URL }
base do Google      Drive
        .loading::before {
         const baseUrl = content: '''https://drive.google.com/drive/folders/' + folderId;
            display: block;    
            width: 50px;
   // Retornar URL de busca (será usado para encontrar height: 50px;
o documento)
              margin: 0 autoreturn 20px;{
            border: 4px solid #e9ecef;
     searchUrl: baseUrl,
      border-top-color: #667eea;
              border-radiusdocName: 50%;docName,
            animation: spin 1s linear infinite;
        }version: version
        
        @keyframes spin {};
            from { transform: rotate(0deg); }
            
 to { transform: rotate(360deg); }
       // }
Função para criar Widget Connector
    
        @mediafunction (max-width: 768pxcreateWidgetConnector(docUrl) {
            body  {
  // URL completa do Google Doc
         padding: 10px;
      const fullUrl = docUrl;
   }
             
            .header {
   // Criar iframe como fallback (caso Widget Connector não funcione)
    padding: 20px;
           const }
iframe = document.createElement('iframe');
          
      iframe.src =     .header-content {fullUrl.replace('/edit', '/preview');
                flex-direction: columniframe.width = '100%';
                align-items: flex-startiframe.height = '800';
            }
    iframe.style.border = 'none';
      
            .header h1 {
iframe.style.borderRadius = '5px';
                 font-size: 24pxiframe.allow = 'fullscreen';
            }
    
        
        // Tentar usar Widget .metadata {Connector do Confluence
                padding: 15px 20px;const widgetCode = `
                flex-direction: column;
       <ac:structured-macro ac:name="widget" ac:schema-version="1">
       align-items: flex-start;
                 <ac:parameter ac:name="url">${fullUrl}</ac:parameter>
        }
    </style>
</head>
<body>
    <div class="release-notes-wrapper">
        <div class<ac:parameter ac:name="header">width">100%</ac:parameter>
            <div class="header-content">
                <div class="totvs-logo"><ac:parameter ac:name="height">800</ac:parameter>
                    <div class="totvs-icon"></ac:structured-macro>
                `;
        <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
   
                // Se estiver em modo de edição, retornar código <polygon points="50,10 90,30 90,70 50,90 10,70 10,30" 
do macro
                // Se estiver em visualização, usar iframe
                return {
    fill="#667eea" 
                widgetCode: widgetCode,
                    stroke="#764ba2" iframe: iframe,
                    directUrl: fullUrl
                stroke-width="2"/>};
            }
            
    <path d="M 30 50 L 50 30 L 70// 50 L 50 70 Z" Função principal
            function init() {
                const   version fill="white"  getVersionFromPage();
                
                if  opacity="0.9"/>(!version) {
                    document.getElementById('error').style.display = 'block';
  </svg>
                  document.getElementById('error').textContent = </div>
                    <div class="totvs-text">TOTVS</div>
                </div>    '❌ 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.2)';
                <h1 id="page-title">Dicionário de Dados</h1>
    document.getElementById('loading').style.display = 'none';
         </div>
        </div>
   return;
         
       }
 <div class="metadata">
              <div class="metadata-item">
                <strong>Versão:</strong> // Atualizar interface
                <span id="version-display">Carregando...</span>document.getElementById('version').textContent = version;
            </div>
    document.getElementById('page-title').textContent = `Release Notes - ${version}`;
   <div class="metadata-item">
            document.getElementById('last-update').textContent = new  <strong>Última atualização:</strong> 
Date().toLocaleString('pt-BR');
                
   <span id="last-update">-</span>
            </div>// Construir URLs
        </div>
        const docInfo = getGoogleDocUrl(version);
         <div id="widget-container">
       
         <div class="loading">Carregando documento...</div>
        </div>
    </div>

    <script>
        (function() {
// URL do Google Doc (assumindo que o nome do arquivo é a versão)
                // MapeamentoVocê deprecisará versõesmapear paraversão Document-> IDsdocument doID Googleou Docsusar ebusca
 arquivos .txt
            // Gerado automaticamenteconst agoogleDocUrl partir= da pasta: 141aJRhZeYZca4QCBnou6-00WzRLkBYbs`https://docs.google.com/document/d/[DOCUMENT_ID]/edit?usp=sharing`;
            // Data: 2025-12-16
   
         // Total: 62 versões (2 Google Docs +// 60Criar arquivoslinks
 .txt - todos funcionando!)
            const versionToDocIdlinksContainer = {document.getElementById('links-container');
                // Google Docs (2)linksContainer.innerHTML = `
                '12.1.2503.14': '13QaSU_lP1_haWnOYl7UjPvsKfi3AaPdKwciYHrceEt4',
   <a href="${googleDocUrl}" target="_blank">📄 Abrir no         '12.1.2511.2': '1gLo16QDT99iGdaoKyFHBW1n5jF-gt-awBjnSQrBZa3c',Google Docs</a>
                
                // Arquivos .txt (60) - funcionando diretamente no Widget Connector
                '12.1.2503': '1BRsJyHOHQNOEpAfIm5ndOn6z_0gffbaF',
                '12.1.2503.15': '12ejZuDikegyaH2n16n2Hpas1Z3VEjc5e',
                '12.1.2503.16': '15BkT50wXw7kJccfw4iRB-LVGQyTzQVf1',
                '12.1.2503.17': '1L4FUKbDjnAs29rK0ymfMgRVJPPVtzYdW',
                '12.1.2503.18': '1LNSFua5jsEw9m2D4X7lBVsbk6qXsG3cm',
                '12.1.2507': '1pT42y90cnf2UY2gK5k035jEFVkIs7s-n',
                '12.1.2507.1': '1lo7KiRJGWYJFfH-Xqv-dvNcRoIy6ecj3',
                '12.1.2507.2': '1xe9L8cCurcXIw5tzxe4H9KNzFgpIObA1',
                '12.1.2507.3': '1P9jEM2cgtUkyfdK5bsKlSvFCk_SqpMqU',
                '12.1.2507.4': '12Qk7mEnEe2iIsE-nFUUGOmbt_t8rwjn-',
                '12.1.2507.5': '1ljgI7Re2mT3yv7TgnZLOZv_n0vzzJTxF',
                '12.1.2507.6': '1lwblHVXZUKF8qgdajVB2Va41fxpJkZ9X',
                '12.1.2507.7': '1LWO9GFD8iO6HQEJn_wBybP1EdZ2AZSsD',
                '12.1.2507.8': '1bhB3Pig68EAvmXGoUptLYnJPEnGW4fVr',
                '12.1.2507.9': '1shjpLbeGfQmrV6DMtm4EuIvqdhHTuEIy',
                '12.1.2507.10': '1wU40XkkEMRqw4Ieanf5QrkBz8SwqISzj',
                '12.1.2507.11': '1goM3M1WCXvtdx46fY7ZmeeDtwpnvbld5',
                '12.1.2507.12': '15r-G5LdQpPn9gcktkpYVPQS1exs6Io8t',
                '12.1.2507.13': '1xVHx0mjDewGUVwIGR8GWqTMqX1R_Cj21',
                '12.1.2507.14': '1uFblMZhJaYPFrGKtFCC9bAa-2xxtXmi_',
                '12.1.2507.15': '1vNN6ONnbq1ApNJy6uzGW_hZ27HvhW7Dd',
                '12.1.2507.16': '1g27jhn6ZEliSZhAJ7Co9FUFLtNBfqVHH',
                '12.1.2507.17': '1LkwBvxVy_oykf3gEAwlf2eRn0NMiMnL1',
                '12.1.2507.18': '1he66XmpG6YhgKlxtMv3xik6KccuMKLeS',
                '12.1.2511': '1gPiO2P_mF0wpLX-2g5oFBqi4QS630wKM',
                '12.1.2511.1': '1yv4EZZKrfPgI-RWggMfBANtx6dL8owhA',
                '12.1.2511.3': '14Zd-Npn6VGioc1wsokDL4vfPRVzhb-AY',
                '12.1.2511.4': '1VjoqjmjqCokx4Kv5QDTDa9wZsF1QwICY',
                '12.1.2511.5': '1evpMFJmgDUFX__dC6W83LZqKQXjmy88s',
                '12.1.2511.6': '1_e3AgOsc9Oqy-JoZhus-zyU-961karvw',
                '12.1.2511.7': '19TKZ4fYof03H0pdzldQnV7_ZYjxowkNr',
                '12.1.2511.8': '12ivR5sJUwVwcRJr0Q_aHBT_y4JwlnTd4',
                '12.1.2511.9': '1Exio4F5z2lo6HnEnLpkDquuu8HUiD3C-',
                '12.1.2511.10': '1NRs4aZct5OVmSiXDPgMmUw9iFURlC6Od',
                '12.1.2511.11': '1AAOtpmIahaHaYYUtUFL3OJGJ07dTKLU_',
                '12.1.2511.12': '1c19qwsUQdWb_H58qcamAQ6Fz9Bwg78Bs',
                '12.1.2511.13': '1CS-VXZJLzPSBjov0r4JVAcTPE5daaE4M',
                '12.1.2511.14': '1dei-4_gijuPsGzSQKZpIh9DMCYJ2pw8j',
                '12.1.2511.15': '1qDv9Zm_0CJiKl6iJBzxVxwFCoHNZBky4',
                '12.1.2511.16': '1H51vcp3ierWZE0XB1QEtzUnm0J-0uEVp',
                '12.1.2511.17': '1OwFzjD6j4_OlDi9x7f5xqqoBo_eKY1rd',
                '12.1.2511.18': '1iaMmEP6yDzHR4oTM_SjM2obkaUz1zrBA',
                '12.1.2603.1': '19iieXcJNDoIM8lp09Zd-faD22AWepfTC',
                '12.1.2603.2': '1DFR1cWRUVm3PsPQsVbuJySIjxMIy085L',
                '12.1.2603.3': '1PLCl8hhtuvnW8Q9WDug9NH9F_qO-CUoq',
                '12.1.2603.4': '1qFmELYGulpQizNrXFBCpHdcLOSC5LrsZ',
                '12.1.2603.5': '1Q8ZSMOooNeSgmfdEucEsRO6P8z370enZ',
                '12.1.2603.6': '1P5-nq151raX-NhYufnTRrZMZyeAKsSp2',
                '12.1.2603.7': '1VfNdP7lRvi37ZKSOzX1KyEp6dK_t0I-N',
                '12.1.2603.8': '1pxJPuMKfOWXrkwS7zzmm_3i_GerA44Zi',
                '12.1.2603.9': '1evoXM_3WvL4SGVkwB8EYgwXuD6E4Asmw',
                '12.1.2603.10': '18tytubaH1oywQoWyAycMM-qMq_347CHb',
                '12.1.2603.11': '1ORyeFI8qYQynt20Ud66XLKewYQoVdLA6',
                '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>
<a href="https://drive.google.com/drive/folders/141aJRhZeYZca4QCBnou6-00WzRLkBYbs" target="_blank">📁 Pasta Release Notes</a>
                    <a href="https://tdn.totvs.com/pages/viewpage.action?pageId=649987902" target="_blank">📚 Release Notes Principal</a>
       <p style="color: #6c757d; font-size: 14px;">
     `;
                
       💡 <strong>Instruções:</strong> Copie o código acima e cole no editor// doCriar Confluencewidget
 usando o macro "Widget Connector".
           const widget = createWidgetConnector(googleDocUrl);
          </p>
      const placeholder = document.getElementById('widget-placeholder');
           </div>
     
           `;
     // Tentar inserir Widget Connector (se em }modo elsede {edição)
                // ModoCaso decontrário, visualização: usar iframe
                const iframe = document.createElement('iframe'placeholder.appendChild(widget.iframe);
                iframe.src = previewUrl;
                iframe.widthdocument.getElementById('loading').style.display = '100%none';
            }
      iframe.height = '800';
    
            iframe.allow = 'fullscreen';
   // Executar quando a página carregar
            if iframe(document.titlereadyState === `Dicionário de Dados ${version}`;'loading') {
                document.addEventListener('DOMContentLoaded', init);
            }    container.innerHTML = '';else {
                container.appendChildinit(iframe);
            }
        })();
    </script>
</body>
</html>