merge: Google Kalender som menupunkt, med Verdandes egen kalender lagt over
Release / Build and publish image (push) Failing after 9m58s
Release / Build and publish image (push) Failing after 9m58s
Læs bredt, skriv snævert — decision 5 i planen, og kun den første halvdel: kalenderen læses, og der skrives ingenting tilbage. **OAuth-blokeringen er reel og blev ikke gået udenom.** En klient registreret som *Internal* tager kun konti i sit eget workspace — også til kalendere, ikke kun Gmail. Andreas' private konto bliver afvist med `org_internal`, og det er klienten, der virker efter hensigten, ikke en fejl. Fladen siger det nu med ord, man kan handle på, frem for at vise Googles egen skærm, der ikke gør. Vejen udenom, som ikke er bygget: kalenderens egen hemmelige ICS-adresse. Ingen OAuth, virker for enhver konto, og `internal/ics` findes allerede. Det er det næste stykke, og det eneste, der låser den private konto op. `internal/google` er flyttet ud af `internal/gmail`, fordi de to er det samme flow, der er uenige om én streng. Egen callback-adresse frem for at dele Gmails: én callback, der finder ud af hvilken token-butik den skal skrive i, går galt ved at overskrive en Gmail-forbindelse, der virkede. Egne tabeller frem for `mailboxes`. `trigger_kind`, `seen` og `last_uid` svarer alle på "hvad gør en besked til en opgave", og ingenting her bliver til en opgave; én konto har mange kalendere, og `mailboxes` har ikke plads til en en-til-mange. Afgørende i praksis: `mailboxes.kind` har en CHECK, og SQLite kan ikke ændre en — en tredje værdi koster den tabelombygning, som migration 0021 skulle igennem. Begivenheder erstattes pr. kalender pr. vindue frem for at flettes med et sync-token: et vindue, der slettes og skrives forfra, kan ikke komme ud af trit, og et sync-token er endnu en ting, der skal være rigtig for altid, for at gitteret ikke stille viser noget forkert. `CalendarView` er udvidet, ikke kopieret. En begivenhed er et fyldt bånd, hvor en opgave er et kort med en farvet kant, så de to læses forskelligt før et ord er læst — og den kan ikke trækkes og er aldrig en knap: der er ikke noget at gøre færdigt ved en andens møde. To værn på det, der kommer fra Google: farven skal matche et hex-mønster, før den må stå i en style, og linket bliver kun til et href, hvis det begynder med https. Konflikten i jobs.go var to nye jobs skrevet på samme linje. Begge skal med. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,7 @@ export const da = {
|
||||
'nav.upcoming': 'Kommende',
|
||||
'nav.delegated': 'Venter på andre',
|
||||
'nav.inbox': 'Indbakke',
|
||||
'nav.calendar': 'Kalender',
|
||||
'nav.settings': 'Indstillinger',
|
||||
'nav.signOut': 'Log ud',
|
||||
'nav.main': 'Hovedmenu',
|
||||
@@ -593,7 +594,7 @@ export const da = {
|
||||
'Klienten er sat i miljøet (VERDANDE_GMAIL_CLIENT_ID), så den kan ikke ændres her. Det er med vilje: en værdi i runens manifest er en beslutning, der bliver anvendt igen ved hver genstart, og en formular, der kunne overskrive den, ville gøre manifestet til en løgn.',
|
||||
'int.oauthClient': 'OAuth-klient hos Google',
|
||||
'int.registerHint':
|
||||
'Registrér en klient i Google Cloud Console → APIs & Services → Credentials → OAuth client ID → Web application, slå Gmail API til, og indsæt de to værdier her. Din egen konto skal stå som testbruger, så længe appen ikke er verificeret hos Google.',
|
||||
'Registrér en klient i Google Cloud Console → APIs & Services → Credentials → OAuth client ID → Web application, og indsæt de to værdier her. Den samme klient bruges til både Gmail og Google Kalender: slå det API til, du skal bruge, og tilføj begge redirect-URI\'er — den nedenfor og kalenderens, som står i panelet Google Kalender. Din egen konto skal stå som testbruger, så længe appen ikke er verificeret hos Google.',
|
||||
'int.redirectURI': 'Godkendt redirect-URI',
|
||||
'int.clientID': 'Klient-id',
|
||||
'int.clientSecret': 'Klienthemmelighed',
|
||||
@@ -633,6 +634,32 @@ export const da = {
|
||||
'int.server': 'Server',
|
||||
'int.caldavAuth':
|
||||
'Brugernavn er din e-mail. Adgangskoden er en API-token — ikke din rigtige adgangskode.',
|
||||
'int.calendar': 'Google Kalender',
|
||||
'int.calendarHint':
|
||||
'Læses, aldrig skrives. Begivenhederne vises i Kalender ved siden af dine egne opgaver med forfaldsdato — de kan ikke flyttes eller lukkes herfra, for de hører til i Google.',
|
||||
'int.connectCalendar': 'Forbind Google Kalender',
|
||||
'int.calendarConnectedAs': 'Forbundet som',
|
||||
'int.calendarSameClient':
|
||||
'Bruger den samme OAuth-klient som Gmail ovenfor. Google Calendar API skal være slået til, og denne adresse skal stå som godkendt redirect-URI.',
|
||||
'int.whichCalendars': 'Hvilke kalendere vises',
|
||||
'int.noCalendars': 'Kontoen har ingen kalendere at vise.',
|
||||
'int.calendarLastSync': 'Sidst hentet {when}.',
|
||||
'int.calendarNeverSynced': 'Ikke hentet endnu.',
|
||||
'int.calendarFetchedOne': '{n} begivenhed hentet.',
|
||||
'int.calendarFetchedMany': '{n} begivenheder hentet.',
|
||||
'int.calendarNothingNew': 'Ingen begivenheder i vinduet.',
|
||||
'int.calendarConnected': 'Google Kalender er forbundet.',
|
||||
'int.calendarState':
|
||||
'Svaret fra Google passede ikke til det forsøg, der blev startet her. Prøv igen.',
|
||||
'int.calendarExpired': 'Forsøget udløb undervejs. Prøv igen.',
|
||||
'int.calendarInvalid': 'Svaret fra Google kunne ikke læses. Prøv igen.',
|
||||
'int.calendarFailed': 'Google afviste ombytningen af koden.',
|
||||
'int.calendarNoRefresh':
|
||||
'Google sendte ingen refresh-token. Fjern verdande under din Google-konto og forbind igen.',
|
||||
'int.calendarDenied': 'Adgangen blev afvist hos Google.',
|
||||
'int.calendarOrgInternal':
|
||||
'Google-appen er registreret som Internal og tager kun imod konti i organisationen. En privat konto kan ikke godkende den, uanset hvad der står på skærmen.',
|
||||
'int.calendarOther': 'Google svarede: {what}',
|
||||
'int.gmailFetchedOne': '{n} opgave hentet.',
|
||||
'int.gmailFetchedMany': '{n} opgaver hentet.',
|
||||
'int.gmailNothingNew': 'Ingen nye beskeder.',
|
||||
@@ -647,6 +674,18 @@ export const da = {
|
||||
'int.gmailDenied': 'Adgangen blev afvist hos Google.',
|
||||
'int.gmailOther': 'Gmail svarede: {what}',
|
||||
|
||||
// --- kalenderen, med Googles begivenheder lagt over ---------------------------------
|
||||
'cal.title': 'Kalender',
|
||||
'cal.notConnected':
|
||||
'Ingen kalender er forbundet endnu. Det gøres under Indstillinger → Integrationer.',
|
||||
'cal.settings': 'Indstillinger',
|
||||
'cal.noneChosen': 'Ingen af kontoens kalendere er valgt endnu.',
|
||||
'cal.allDay': 'Hele dagen',
|
||||
'cal.openInGoogle': 'Åbn i Google Kalender',
|
||||
'cal.beyondWindow':
|
||||
'Begivenheder gemmes fra {from} til {to}. Uden for det viser gitteret kun dine egne opgaver.',
|
||||
'cal.eventCannotMove': '{name} — en begivenhed i {calendar}. Den kan ikke flyttes herfra.',
|
||||
|
||||
// --- a project ----------------------------------------------------------------------
|
||||
'project.name': 'Projektets navn',
|
||||
'project.clickToRename': 'Klik for at omdøbe',
|
||||
@@ -789,6 +828,10 @@ export const da = {
|
||||
'Denne instans kan ikke genstarte sig selv: {missing} er ikke sat. En container kan ikke udskifte sit eget image — panelet gør arbejdet, og det her er kun måden at bede om det.',
|
||||
|
||||
'error.gmailSaid': 'Gmail svarede: {what}',
|
||||
'error.calendarRefused': 'Google afviste kaldet. Prøv at forbinde kalenderen igen.',
|
||||
'error.calendarSaid': 'Google svarede: {what}',
|
||||
'int.disconnectCalendarQuestion':
|
||||
'Afbryd forbindelsen til Google Kalender? Tokens bliver glemt, og den hentede kopi af begivenhederne bliver slettet. Dine egne opgaver rører den ikke.',
|
||||
|
||||
'error.mailboxRefused': 'Postkassen kunne ikke læses.',
|
||||
'error.mailboxSaid': 'Postkassen svarede: {what}',
|
||||
|
||||
@@ -76,6 +76,7 @@ export const en = {
|
||||
'nav.upcoming': 'Upcoming',
|
||||
'nav.delegated': 'Waiting on others',
|
||||
'nav.inbox': 'Inbox',
|
||||
'nav.calendar': 'Calendar',
|
||||
'nav.settings': 'Settings',
|
||||
'nav.signOut': 'Sign out',
|
||||
'nav.main': 'Main menu',
|
||||
@@ -589,7 +590,7 @@ export const en = {
|
||||
'The client is set in the environment (VERDANDE_GMAIL_CLIENT_ID), so it cannot be changed here. That is deliberate: a value in the Rune’s manifest is a decision reapplied on every restart, and a form that could overwrite it would make the manifest a lie.',
|
||||
'int.oauthClient': 'OAuth client at Google',
|
||||
'int.registerHint':
|
||||
'Register a client in Google Cloud Console → APIs & Services → Credentials → OAuth client ID → Web application, enable the Gmail API, and paste the two values here. Your own account has to be listed as a test user for as long as the app is unverified with Google.',
|
||||
'Register a client in Google Cloud Console → APIs & Services → Credentials → OAuth client ID → Web application and paste the two values here. The same client serves both Gmail and Google Calendar: enable whichever API you need, and add both redirect URIs — the one below and the calendar\'s, which is shown in the Google Calendar panel. Your own account has to be listed as a test user for as long as the app is unverified with Google.',
|
||||
'int.redirectURI': 'Authorised redirect URI',
|
||||
'int.clientID': 'Client ID',
|
||||
'int.clientSecret': 'Client secret',
|
||||
@@ -629,6 +630,31 @@ export const en = {
|
||||
'int.server': 'Server',
|
||||
'int.caldavAuth':
|
||||
'The username is your email. The password is an API token — not your real password.',
|
||||
'int.calendar': 'Google Calendar',
|
||||
'int.calendarHint':
|
||||
'Read, never written. The events appear in Calendar beside your own tasks with due dates — they cannot be moved or completed from here, because they belong to Google.',
|
||||
'int.connectCalendar': 'Connect Google Calendar',
|
||||
'int.calendarConnectedAs': 'Connected as',
|
||||
'int.calendarSameClient':
|
||||
'Uses the same OAuth client as Gmail above. The Google Calendar API has to be enabled, and this address has to be listed as an authorised redirect URI.',
|
||||
'int.whichCalendars': 'Which calendars are shown',
|
||||
'int.noCalendars': 'The account has no calendars to show.',
|
||||
'int.calendarLastSync': 'Last fetched {when}.',
|
||||
'int.calendarNeverSynced': 'Not fetched yet.',
|
||||
'int.calendarFetchedOne': '{n} event fetched.',
|
||||
'int.calendarFetchedMany': '{n} events fetched.',
|
||||
'int.calendarNothingNew': 'No events in the window.',
|
||||
'int.calendarConnected': 'Google Calendar is connected.',
|
||||
'int.calendarState': 'Google’s reply did not match the attempt that started here. Try again.',
|
||||
'int.calendarExpired': 'The attempt expired on the way. Try again.',
|
||||
'int.calendarInvalid': 'Google’s reply could not be read. Try again.',
|
||||
'int.calendarFailed': 'Google refused to exchange the code.',
|
||||
'int.calendarNoRefresh':
|
||||
'Google sent no refresh token. Remove verdande from your Google account and connect again.',
|
||||
'int.calendarDenied': 'Access was refused at Google.',
|
||||
'int.calendarOrgInternal':
|
||||
'The Google app is registered as Internal and only accepts accounts inside the organisation. A private account cannot consent to it, whatever the screen says.',
|
||||
'int.calendarOther': 'Google replied: {what}',
|
||||
'int.gmailFetchedOne': '{n} task fetched.',
|
||||
'int.gmailFetchedMany': '{n} tasks fetched.',
|
||||
'int.gmailNothingNew': 'No new messages.',
|
||||
@@ -642,6 +668,17 @@ export const en = {
|
||||
'int.gmailDenied': 'Access was refused at Google.',
|
||||
'int.gmailOther': 'Gmail replied: {what}',
|
||||
|
||||
// --- the calendar, with Google’s events laid over ------------------------------------
|
||||
'cal.title': 'Calendar',
|
||||
'cal.notConnected': 'No calendar is connected yet. That is done under Settings → Integrations.',
|
||||
'cal.settings': 'Settings',
|
||||
'cal.noneChosen': 'None of the account’s calendars are chosen yet.',
|
||||
'cal.allDay': 'All day',
|
||||
'cal.openInGoogle': 'Open in Google Calendar',
|
||||
'cal.beyondWindow':
|
||||
'Events are kept from {from} to {to}. Outside that the grid shows only your own tasks.',
|
||||
'cal.eventCannotMove': '{name} — an event in {calendar}. It cannot be moved from here.',
|
||||
|
||||
// --- a project ----------------------------------------------------------------------
|
||||
'project.name': 'The project’s name',
|
||||
'project.clickToRename': 'Click to rename',
|
||||
@@ -784,6 +821,10 @@ export const en = {
|
||||
'This instance cannot restart itself: {missing} are not set. A container cannot replace its own image — the panel does the work, and this is only the way to ask.',
|
||||
|
||||
'error.gmailSaid': 'Gmail said: {what}',
|
||||
'error.calendarRefused': 'Google refused the call. Try connecting the calendar again.',
|
||||
'error.calendarSaid': 'Google replied: {what}',
|
||||
'int.disconnectCalendarQuestion':
|
||||
'Disconnect Google Calendar? The tokens are forgotten and the fetched copy of the events is deleted. Your own tasks are untouched.',
|
||||
|
||||
'error.mailboxRefused': 'The mailbox could not be read.',
|
||||
'error.mailboxSaid': 'The mailbox answered: {what}',
|
||||
|
||||
Reference in New Issue
Block a user