Changeset c1b757d in Klonkt


Ignore:
Timestamp:
06/21/2026 07:01:45 PM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
1ee5f65
Parents:
e25438a
Message:

feat(admin): Google setup revised — beginner-friendly explanation

The explanation was buried in a collapsed <details> with fragmented text. Now:
always-visible numbered steps (1-5) in plain language, with the redirect URI
inline at step 4 + a Copy button, a short "must match exactly" warning,
and a "no APIs needed" tip. NL/EN/DE (full sentences instead of fragments).

Co-Authored-By: Claude <noreply@…>

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/services/i18n.js

    re25438a rc1b757d  
    305305    'aseo.save': 'SEO opslaan',
    306306    'agoog.title': 'Google-login',
     307    'agoog.intro': 'Hiermee kunnen bezoekers met hun <strong>Google-account</strong> inloggen om te reageren. Je stelt dit één keer in met je eigen (gratis) Google-account — zo\'n 5 minuten, geen creditcard of betaalde dienst nodig.',
     308    'agoog.g1': 'Open de Google Cloud Console en log in. Maak bovenaan een <strong>nieuw project</strong> (Project selecteren → Nieuw project), geef het een naam en klik op <strong>Maken</strong>.',
     309    'agoog.g2': 'Ga in het menu links naar <strong>APIs en services → OAuth-toestemmingsscherm</strong>. Kies <strong>Extern</strong>, vul de app-naam + je e-mail in en sla op. Vraagt het systeem om testgebruikers? Voeg dan jezelf toe.',
     310    'agoog.g3': 'Ga naar <strong>APIs en services → Inloggegevens → Inloggegevens maken → OAuth-client-ID</strong> en kies als type <strong>Webapplicatie</strong>.',
     311    'agoog.g4': 'Plak bij <strong>Geautoriseerde omleidings-URI\'s</strong> exact dit adres en klik op <strong>Maken</strong>:',
     312    'agoog.g5': 'Google toont nu een <strong>Client-ID</strong> en <strong>Client-secret</strong>. Kopieer die naar de velden hieronder en klik op <strong>Opslaan</strong>. Klaar!',
     313    'agoog.copy': 'Kopieer',
     314    'agoog.copied': 'Gekopieerd ✓',
     315    'agoog.warn_short': 'Let op: moet <strong>exact</strong> kloppen — met <code>https://</code>, het juiste domein, en <strong>geen</strong> schuine streep aan het eind. Anders krijg je "Error 400: redirect_uri_mismatch".',
     316    'agoog.need_baseurl': 'Stel eerst <code>PUBLIC_BASE_URL</code> in (de publieke URL van je site) — daar wordt dit adres van afgeleid.',
     317    'agoog.no_api_note': '<strong>Tip:</strong> je hoeft géén API\'s aan te zetten (geen "People API" o.i.d.). Alleen het toestemmingsscherm + de OAuth-client zijn nodig.',
    307318    'agoog.back': 'Instellingen',
    308319    'agoog.card_title': 'Google-login (bezoekers)',
     
    12741285    'aseo.save': 'Save SEO',
    12751286    'agoog.title': 'Google login',
     1287    'agoog.intro': 'This lets visitors sign in with their <strong>Google account</strong> to comment. You set it up once with your own (free) Google account — about 5 minutes, no credit card or paid service needed.',
     1288    'agoog.g1': 'Open the Google Cloud Console and sign in. At the top, create a <strong>new project</strong> (Select project → New project), give it a name and click <strong>Create</strong>.',
     1289    'agoog.g2': 'In the left menu go to <strong>APIs &amp; Services → OAuth consent screen</strong>. Choose <strong>External</strong>, fill in the app name + your email and save. If it asks for test users, add yourself.',
     1290    'agoog.g3': 'Go to <strong>APIs &amp; Services → Credentials → Create credentials → OAuth client ID</strong> and choose type <strong>Web application</strong>.',
     1291    'agoog.g4': 'Under <strong>Authorized redirect URIs</strong> paste exactly this address and click <strong>Create</strong>:',
     1292    'agoog.g5': 'Google now shows a <strong>Client ID</strong> and <strong>Client secret</strong>. Copy them into the fields below and click <strong>Save</strong>. Done!',
     1293    'agoog.copy': 'Copy',
     1294    'agoog.copied': 'Copied ✓',
     1295    'agoog.warn_short': 'Note: it must match <strong>exactly</strong> — with <code>https://</code>, the correct domain, and <strong>no</strong> trailing slash. Otherwise you get "Error 400: redirect_uri_mismatch".',
     1296    'agoog.need_baseurl': 'First set <code>PUBLIC_BASE_URL</code> (the public URL of your site) — this address is derived from it.',
     1297    'agoog.no_api_note': '<strong>Tip:</strong> you do not need to enable any APIs (no "People API" etc.). Only the consent screen + the OAuth client are needed.',
    12761298    'agoog.back': 'Settings',
    12771299    'agoog.card_title': 'Google login (visitors)',
     
    22422264    'aseo.save': 'SEO speichern',
    22432265    'agoog.title': 'Google-Anmeldung',
     2266    'agoog.intro': 'Damit können sich Besucher mit ihrem <strong>Google-Konto</strong> anmelden, um zu kommentieren. Du richtest das einmalig mit deinem eigenen (kostenlosen) Google-Konto ein — etwa 5 Minuten, keine Kreditkarte oder kostenpflichtiger Dienst nötig.',
     2267    'agoog.g1': 'Öffne die Google Cloud Console und melde dich an. Erstelle oben ein <strong>neues Projekt</strong> (Projekt auswählen → Neues Projekt), gib ihm einen Namen und klicke auf <strong>Erstellen</strong>.',
     2268    'agoog.g2': 'Gehe im linken Menü zu <strong>APIs und Dienste → OAuth-Zustimmungsbildschirm</strong>. Wähle <strong>Extern</strong>, trage den App-Namen + deine E-Mail ein und speichere. Falls nach Testnutzern gefragt wird, füge dich selbst hinzu.',
     2269    'agoog.g3': 'Gehe zu <strong>APIs und Dienste → Anmeldedaten → Anmeldedaten erstellen → OAuth-Client-ID</strong> und wähle den Typ <strong>Webanwendung</strong>.',
     2270    'agoog.g4': 'Füge unter <strong>Autorisierte Weiterleitungs-URIs</strong> genau diese Adresse ein und klicke auf <strong>Erstellen</strong>:',
     2271    'agoog.g5': 'Google zeigt nun eine <strong>Client-ID</strong> und ein <strong>Client-Secret</strong>. Kopiere sie in die Felder unten und klicke auf <strong>Speichern</strong>. Fertig!',
     2272    'agoog.copy': 'Kopieren',
     2273    'agoog.copied': 'Kopiert ✓',
     2274    'agoog.warn_short': 'Achtung: muss <strong>exakt</strong> stimmen — mit <code>https://</code>, der richtigen Domain und <strong>ohne</strong> Schrägstrich am Ende. Andernfalls bekommst du „Error 400: redirect_uri_mismatch“.',
     2275    'agoog.need_baseurl': 'Lege zuerst <code>PUBLIC_BASE_URL</code> fest (die öffentliche URL deiner Seite) — daraus wird diese Adresse abgeleitet.',
     2276    'agoog.no_api_note': '<strong>Tipp:</strong> du musst keine APIs aktivieren (keine „People API“ usw.). Nur der Zustimmungsbildschirm + der OAuth-Client sind nötig.',
    22442277    'agoog.back': 'Einstellungen',
    22452278    'agoog.card_title': 'Google-Anmeldung (Besucher)',
  • src/views/pages/admin-google.ejs

    re25438a rc1b757d  
    88  <section class="set-card">
    99    <h2><%= t('agoog.card_title') %></h2>
    10     <p class="set-help"><%= t('agoog.card_help_pre') %> <strong><%= t('agoog.card_help_own') %></strong>
    11       <%= t('agoog.card_help_mid') %>
    12       <a href="https://console.cloud.google.com/apis/credentials" target="_blank" rel="noopener">console.cloud.google.com</a>
    13       <%= t('agoog.card_help_post') %>
     10    <p class="set-help"><%- t('agoog.intro') %>
    1411      <% if (google && google.configured) { %><strong><%= t('agoog.status_set') %></strong><% } else { %><%= t('agoog.status_unset') %><% } %></p>
    1512
    16     <details class="set-google-guide">
    17       <summary><%= t('agoog.guide_summary') %></summary>
    18       <ol class="set-google-steps">
    19         <li><%= t('agoog.step1_pre') %> <a href="https://console.cloud.google.com/" target="_blank" rel="noopener">Google Cloud Console</a> <%= t('agoog.step1_post') %></li>
    20         <li><strong>APIs &amp; Services → OAuth consent screen</strong>: <%= t('agoog.step2_usertype') %> <strong>External</strong>. <%= t('agoog.step2_scopes_pre') %> <code>email</code>, <code>profile</code> <%= t('agoog.step2_scopes_and') %> <code>openid</code> <%= t('agoog.step2_scopes_post') %> <%= t('agoog.step2_testmode') %></li>
    21         <li><strong>APIs &amp; Services → Credentials → Create credentials → OAuth client ID</strong>, <%= t('agoog.step3_type') %> <strong>Web application</strong>.</li>
    22         <li><%= t('agoog.step4_pre') %> <strong>Authorized redirect URIs</strong><%= t('agoog.step4_post') %></li>
    23         <li><%= t('agoog.step5_pre') %> <strong>Client ID</strong> + <strong>Client Secret</strong> <%= t('agoog.step5_post') %></li>
    24       </ol>
    25       <p class="set-help" style="margin:.5rem 0 0"><strong><%= t('agoog.note_label') %></strong> <%= t('agoog.note_pre') %> <strong><%= t('agoog.note_noapi') %></strong> <%= t('agoog.note_mid') %> <em><%= t('agoog.note_not') %></em> <%= t('agoog.note_post') %></p>
    26     </details>
    27 
    28     <% if (google && google.redirectUri) { %>
    29       <div class="set-redirect">
    30         <div class="set-redirect-label"><%= t('agoog.redirect_label') %></div>
    31         <code class="set-redirect-url" style="user-select:all"><%= google.redirectUri %></code>
    32         <ol class="set-redirect-steps">
    33           <li><%= t('agoog.rstep1_pre') %> <a href="https://console.cloud.google.com/apis/credentials" target="_blank" rel="noopener">Google Cloud Console → APIs &amp; Services → Credentials</a>.</li>
    34           <li><%= t('agoog.rstep2') %></li>
    35           <li><%= t('agoog.rstep3_pre') %> <strong>Authorized redirect URIs</strong> → <%= t('agoog.rstep3_mid') %> <strong>+ ADD URI</strong> <%= t('agoog.rstep3_post') %></li>
    36           <li><%= t('agoog.rstep4_pre') %> <strong>Save</strong> <%= t('agoog.rstep4_post') %></li>
    37         </ol>
    38         <p class="set-redirect-warn"><%= t('agoog.warn_pre') %> <strong><%= t('agoog.warn_exact') %></strong> <%= t('agoog.warn_mid1') %> <code>https://</code> (<%= t('agoog.warn_nohttp') %> <code>http</code>)<%= t('agoog.warn_mid2') %> <strong><%= t('agoog.warn_noslash') %></strong> <%= t('agoog.warn_mid3') %> <em><%= t('agoog.warn_error') %></em>.</p>
    39       </div>
    40     <% } else { %>
    41       <p class="set-help" style="color:var(--accent)"><%= t('agoog.set_baseurl_pre') %> <code>PUBLIC_BASE_URL</code> <%= t('agoog.set_baseurl_post') %></p>
    42     <% } %>
     13    <ol class="gg-steps">
     14      <li>
     15        <span class="gg-num">1</span>
     16        <div class="gg-body"><%- t('agoog.g1') %> <a href="https://console.cloud.google.com/" target="_blank" rel="noopener">Google Cloud Console ↗</a></div>
     17      </li>
     18      <li>
     19        <span class="gg-num">2</span>
     20        <div class="gg-body"><%- t('agoog.g2') %></div>
     21      </li>
     22      <li>
     23        <span class="gg-num">3</span>
     24        <div class="gg-body"><%- t('agoog.g3') %></div>
     25      </li>
     26      <li>
     27        <span class="gg-num">4</span>
     28        <div class="gg-body">
     29          <%- t('agoog.g4') %>
     30          <% if (google && google.redirectUri) { %>
     31            <div class="gg-redirect">
     32              <code class="gg-url"><%= google.redirectUri %></code>
     33              <button type="button" class="btn gg-copy" data-copy="<%= google.redirectUri %>"><%= t('agoog.copy') %></button>
     34            </div>
     35            <p class="gg-warn"><%- t('agoog.warn_short') %></p>
     36          <% } else { %>
     37            <p class="gg-warn" style="color:var(--accent)"><%- t('agoog.need_baseurl') %></p>
     38          <% } %>
     39        </div>
     40      </li>
     41      <li>
     42        <span class="gg-num">5</span>
     43        <div class="gg-body"><%- t('agoog.g5') %></div>
     44      </li>
     45    </ol>
     46    <p class="gg-tip"><%- t('agoog.no_api_note') %></p>
    4347
    4448    <form method="post" action="/admin/settings/google" class="set-form">
     
    99103.set-redirect-warn { margin: 0.85rem 0 0; font-size: 0.85rem; color: var(--ink-muted); }
    100104.set-redirect-warn code { background: var(--paper-2); padding: 0.05rem 0.35rem; border-radius: 4px; }
     105/* Genummerde, altijd-zichtbare stap-voor-stap-uitleg (beginnervriendelijk) */
     106.gg-steps { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column; gap: 0.85rem; }
     107.gg-steps > li { display: flex; gap: 0.7rem; align-items: flex-start; }
     108.gg-num { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: #fff; font-weight: 700; font-size: 0.85rem; display: inline-flex; align-items: center; justify-content: center; }
     109.gg-body { font-size: 0.92rem; line-height: 1.5; color: var(--ink); padding-top: 2px; min-width: 0; }
     110.gg-body code { background: var(--paper-2); padding: 0.05rem 0.35rem; border-radius: 4px; font-size: 0.88em; }
     111.gg-redirect { display: flex; gap: 0.5rem; align-items: stretch; margin: 0.5rem 0 0.3rem; flex-wrap: wrap; }
     112.gg-url { flex: 1 1 220px; min-width: 0; padding: 0.5rem 0.7rem; background: var(--paper-2); border: 1px dashed var(--accent); border-radius: 6px; font-size: 0.85rem; word-break: break-all; align-self: center; }
     113.gg-copy { flex: 0 0 auto; }
     114.gg-warn { font-size: 0.82rem; color: var(--ink-muted); margin: 0.3rem 0 0; }
     115.gg-tip { font-size: 0.85rem; color: var(--ink-muted); background: var(--paper); border: 1px solid var(--rule); border-radius: 8px; padding: 0.6rem 0.8rem; margin: 0 0 1.25rem; }
    101116</style>
     117<script>
     118  (function () {
     119    if (window.__ggCopyWired) return;
     120    window.__ggCopyWired = true;
     121    document.addEventListener('click', function (e) {
     122      var b = e.target.closest && e.target.closest('.gg-copy');
     123      if (!b) return;
     124      e.preventDefault();
     125      var txt = b.getAttribute('data-copy') || '';
     126      var done = function () { var o = b.getAttribute('data-label') || b.textContent; b.setAttribute('data-label', o); b.textContent = '<%= t('agoog.copied') %>'; setTimeout(function () { b.textContent = o; }, 1500); };
     127      if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(txt).then(done, function () {}); }
     128      else { try { var ta = document.createElement('textarea'); ta.value = txt; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove(); done(); } catch (_) {} }
     129    });
     130  })();
     131</script>
Note: See TracChangeset for help on using the changeset viewer.