Changelog
Cosa c'è di nuovo.
Ogni miglioramento alla piattaforma, come si spedisce.
· kamo-internal
Scrivere una descrizione di supporto programmato come testo ricco
La descrizione su... area di testo a tre righe. È la /kb / nuova superficie di scrittura ora, meno immagini e la libreria multimediale — quelli caricati in KB media, che è la casa giusta per un articolo e quello sbagliato per un campo di impostazioni. La colonna contiene due forme da qui in poi: un documento Lexical su qualcosa salvato da quando, e nudo prosa su ogni riga più vecchio di quello, dal nulla riscrive loro. app/lib/richTextField.ts è il ponte. Rileva un documento mediante parsing piuttosto che da una breccia principale — prosa come '{beta} clienti solo' è legale, e sniffing lo invierebbe attraverso parseEditorState, che lancia, apre il editor vuoto e perde il testo dell'autore sul salvataggio successivo. La prosa della Legacy è avvolto in un documento in modo che si apre come testo modificabile invece. Un editor svuotato ancora serializza ad un paragrafo vuoto, quindi cosa viene memorizzato è deciso dal testo normale che l'editor consegna le mani indietro, non dal JSON — un chiarito descrizione si legge come assente ovunque a valle. Ogni lettore è alimentato dalle parole piuttosto che dal documento: la procedura guidata di prenotazione carta picker mantiene il suo teaser a due linee, e il passo di conferma guadagna il reso descrizione, che è l'unico posto che la formattazione di un autore ha scritto è in realtà Leggi. RichTextView lo rende attraverso il lessicalToHtml, e mostra un valore ereditario come testo sfuggito — qualsiasi pasta una volta portata in un testo normale campo è esattamente quello che altrimenti correre. Kb ArticleEditor guadagna segnaposto e consenteMedia; la tipologia di anteprima della nota in globals.css è ora condivisa con una superficie di lettura .kamo-richtext, che differisce solo in quanto i suoi collegamenti funzionano. Richiede il MediaService che conosce la descrizionePlain — distribuito e verificato prima di atterrare, dal suo ObjectMapper rifiuta proprietà sconosciute.
· kamo-login
Aggiungi il raccoglitore spazio di lavoro
Un segno in cui i nomi di nessuna organizzazione ora torna con una lista invece di una sessione. Questa è la metà del cliente: /api/login passa che payload attraverso (prima del controllo no-OTK, che altrimenti riferirebbe un perfettamente buono sign-in come un fallimento), /api/session/select relays la scelta e impianti sessione esattamente come /api/login fa, e un terzo passo nella scheda chiede quale spazio di lavoro. Costruito intorno a ciò che i membri realmente fanno, che è aprire lo stesso spazio di lavoro come ultima volta: quella ricordata è prescelta e nominata sul pulsante, così questo si legge come una conferma piuttosto che un sondaggio, mentre ogni alternativa rimane un tasto lontano. Freccia chiavi muoversi, Invio si apre e la ricerca appare oltre otto spazi di lavoro. L'alias sotto ogni nome non è decorazione. Organizzazioni qui autenticamente nomi di condivisione -- ci sono quattro chiamati "Acme Corp" -- quindi è l'unica cosa che dice due righe separate. Un fiore: una singola rotaia che passa tra le righe attraverso il layout condiviso, quindi la selezione della tastiera è leggibile senza un anello di messa a fuoco su ogni elemento. Onorato contro le preferenze-ridotta-mozione, e il passo si monta solo dopo il password, quindi l'opacità serializzata:0 che rende gli stati iniziali di Framer blocco prima vernice non si applica mai qui. Ancora irraggiungibile nella produzione: SecurityService porta il raccoglitore dietro E' spento. Questo atterra l'UI prima quindi la bandiera ha qualcosa da accendere.
· MediaService
Portare la descrizione del tipo in entrambe le sue forme
La descrizione è un documento Lexical ora, quindi il servizio memorizza il testo normale specchio il cliente invia accanto a esso e mani lettori qualsiasi forma che possono In realta' usa. WebinarTypeDTO ottiene la descrizionePlain per una superficie che vuole le parole piuttosto del documento. Il DTO di prenotazione pubblica e il DTO di programma-webinar testo semplice — né una pagina anonima né un promemoria hanno una Lexical runtime, e la stampa di stato editor grezzo a un lettore è peggio di nulla. Lo specchio è scritto incondizionatamente accanto al documento: una richiesta nessuno specchio sta portando prosa, così schiarindo mette la fila di nuovo nell'eredità i lettori di forma già cadono a, dove uno specchio stante accanto a un fresco descrizione sarebbe parole che non corrispondono più. Richiede la colonna webinar type.description plain, applicata da KamoInitializer e verificato presente in Yugabyte prima che questo atterrare.
· InitializerService
Colonne di descrizione del testo ricco su webinar type
Specchi il cambiamento dell'entità condivisa-lib. Due cose che il tavolo ha bisogno prima MediaService li mappa. La colonna di descrizione deve essere unbounded: detiene uno stato di editor Lexical ora, e un soffitto varchar non sarebbe troncate, respingerebbe l'intero salvataggio con un errore di valore-too-long all'interno di un aggiornamento @Transactional che poi torna indietro e non lascia nulla per spiegarlo. Check-then-alter piuttosto che un nudo ALTER, perché l'entità ha dichiarato TEXT dal momento che la tabella è stata creata — così su ogni database questa piattaforma gestisce i cortocircuiti della sonda e nessun DDL viene rilasciato in tutto, che conta su YugabyteDB dove un ALTER COLUMN incondizionato... TIPO logga un guasto su ogni startup. descrizione plain è nuova: lo specchio in chiaro, nullable senza default, perché null è il valore onesto per ogni riga che precede l'editor ed è che cosa dice a un lettore di cadere alla descrizione. Verificato contro il cluster live: la descrizione era già testo, ed entrambi le colonne sono presenti dopo la corsa.
· kamo-shared-library
Conservare la descrizione del tipo come testo ricco
La descrizione su... L'editore Lexical afferma ora piuttosto che una linea di prosa, quindi la colonna deve essere un TEXT non legato come un lungo varchar — un nudo @Lob su una mappa di stringa a un PostgreSQL grande oggetto (oid) su Hibernate 6, che questa colonna non è. DESCRIZIONE PLAIN è lo specchio a testo semplice che l'editor scrive accanto al documento, per lo stesso motivo TrainingSlide mantiene il corpoTesto accanto a bodyJson: solo un runtime Lexical può leggere un documento Lexical, così ogni consumatore che desidera le parole altrimenti dovranno spedire un parser per l'interno di un editore formato. RichTextValues legge sia la forma, perché le righe scritte prima del editor atterrato ancora tenere prosa nudo e nulla li riscrive. PublicWebinarTypeDTO continua a servire testo semplice: una pagina di prenotazione anonima non ha Il runtime lessicale e un campo pubblico che cambia silenziosamente dalla prosa a JSON stampa stato editor grezzo a un visitatore. CreaWebinarTypeRichiesta guadagni ignorareUnknown — MediaService costruisce il proprio ObjectMapper di un nuovo ObjectMapper(), quindi FAIL ON UNKNOWN PROPERTIES è a Jackson's default of true e ogni campo futuro qui è una trappola di distribuzione.
· SecurityService
Lasciate un membro entrare senza un host che nomina il loro org
Aggiunge la seconda metà della divisione: un segnale in cui non nomina nessuna organizzazione autentica l'utente, quindi chiede quale spazio di lavoro. POST /api/security/session/select trasforma una scelta in una sessione, e SignInCompletionService tiene ogni cancello tra una password corretta e una sessione utilizzabile in modo da login e selezione non possono allontanarsi. Raggiungibile in due casi. Un ospite che non nomina un'organizzazione sfida sempre... prima di ora che era un segno-in che non poteva avere successo affatto, quindi niente è portato via. L'host della piattaforma è il caso in cui il cambiamento esiste per: login.kamocrm.com si risolve a KamoCRM Inc., quindi senza questo va avanti ogni accesso a questo org e un membro di un org senza domini ancora non può entrare. Il secondo caso si nasconde dietro. FALSE predefinito. Attivarlo fa un membro di più org ricevere un elenco workspace invece di una sessione, che un client che non può rendere uno legge come un login fallito -- 17 di 53 utenti hanno più di un membro. Va avanti con il rilascio che insegna kamo-login il picker. Fino a allora questo rilascio non cambia nulla per chiunque si sottoscrive oggi, e un dominio personalizzato mantiene il percorso originale in entrambi i casi. Le regole di divulgazione sono preservate deliberatamente. Una password corretta che può entrare nulla è rifiutato nelle stesse parole di uno sbagliato, o la forma diventa oracolo per le credenziali valide. La lista degli spazi di lavoro non è mai autorità: la selezione rimprovera l'appartenenza, quindi un modificato, stallo o inventato la lista ottiene un rifiuto. The selectToken non è una sessione -- uso singolo, cinque minuti, un utente id e nient'altro. E' il momento giusto. correttamente contrassegnato il nuovo in quanto pre-sessione; si basa sul ragionamento, poiché il cui scopo è quello di mentare una sessione non ha nessuno da risolvere. Org ids attraversano ogni nuovo filo come stringhe di cifra. 1200096283020229788 è un vero id qui e non ha una doppia rappresentazione esatta. Passo 923 test.
· InitializerService
Ricordate l'ultimo spazio di lavoro a cui un membro ha firmato
user.last org id supporta il raccoglitore dello spazio di lavoro. Un'organizzazione non è più chiamato dal nome host, quindi un membro che appartiene a diverse scelte una dopo la firma; questa colonna smette di essere una nuova decisione ogni Buongiorno. Una dichiarazione, a differenza delle quattro di UserIsFakeMigration. Quella colonna finisce NON NULL con un DEFAULT e Yugabyte rifiuta ADD COLUMN... NON NULL in un tavolo popolato. Questo è deliberatamente nullable senza default e senza chiave straniera: NULL è il valore significativo per "non ha ancora scelto", che è ogni account che predating il raccoglitore, e una chiave straniera lascerebbe un cancellato org blocco un segnale-in. Un id stante è innocuo -- il picker solo lo utilizza per preimpostare una riga è già elencato. Già applicato al database live, dal momento che questo servizio non ha CI e spingerlo non spedisce nulla; questo è ciò che dà un ambiente fresco colonna.
· kamo-internal
Un file può essere abbandonato ovunque su una finestra di chat, non solo sulla striscia di input
L'obiettivo di goccia era la sola superficie del compositore — alcune dozzine di pixel in fondo a una finestra che è altrimenti tutti i messaggi. Uno screenshot lasciato andare oltre la conversazione non ha fatto nulla, e peggio: il default del browser per una caduta di file non reclamata è a NAVIGATE la scheda al file, che prende ogni finestra di strumento aperto e ogni bozzetto invio con esso. `useComposerIngest` guadagna `bindDropTarget`, che lega i gesti di trascinamento ad un elemento compositore non possiede, e `ComposerSurface` risolve quell'elemento dal DOM — il guscio propri `data-tool-window`, o `data-chatbox-root` per una chat che disegna il proprio frame. Nativo ascoltatori nella fase CAPTURE, così nulla all'interno della finestra può prendere il gesto prima o smettere breve prima che la finestra l'abbia vista; solo trascina i file di trasporto sono rivendicati, quindi la chat AI l'albero della cartella mantiene il suo drag-and-drop intatto. Un trascinamento di file viene richiesto anche durante l'attacco è bloccato — rifiutando il file non deve costare al membro la pagina. Un ingest per compositore ancora, quindi la finestra e la superficie non possono mai mettere in scena la stessa goccia Due volte. I membri chat, biglietti di supporto, conversazioni sociali, chat AI e SMS tutti ottenere questo da l'unica superficie che condividono; un compositore senza finestra intorno a esso mantiene il vecchio comportamento.
· kamo-internal
Gettare il blocco di saluto e mettere la testata su una riga
La testata della lancetta portava un kicker, una voce "buon pomeriggio" e una status line di app/title/trial/date accanto al logo, e il membro controlli galleggiati sopra di esso assolutamente — così l'intestazione ha riservato un 150px gutter e ~130px di altezza per dire il tempo del giorno. Il logo e i comandi ora condividere una riga flex, che è l'altezza del logo da solo, e la griglia inizia molto più in alto.
· kamo-internal
Spostare Binders e Carica a destra della striscia
La striscia ora separa ciò che un responsabile del documento è da dove ti porta. Sinistra: Originals, Modificato, Comune — tre punti di vista degli stessi documenti. Bene. le quattro scorciatoie icone, poi Binders e Uploads come destinazioni, mantenendo le loro etichette e la loro vernice. Là fuori non sono più bambini di <Tabs>, così hanno impostato attivoTab e contrassegnare il proprio stato selezionato — non c'è nessun indicatore fuori il gruppo a farlo. Una scheda dipinta mostra la selezione con una sottolineatura bianca: su marrone e blu che è l'unica cue che legge a colpo d'occhio senza disturbare il riempimento, e si riserva il 3px se selezionato o meno così l'etichetta fa non spostare quando è cliccato. dipintoTab porta anche la sua tipografia e dimensionamento ora. All'interno <Tabs> quelli proveniva dalla `& .MuiTab-root` del genitore; una scheda standalone non eredita nessuno di esso e avrebbe reso al maiuscolo di MUI.
· kamo-marketing
Impostare la titolo in virgolette
Quotazioni intorno alla linea banner, come richiesto — ma reso da CSS (`open-quote`/`close-quote` contro `quote: auto`) piuttosto che digitato nel stringa, per due motivi. La pipeline ha già tradotto `previewBanner.headline` in 19 locali da e67f59b atterrato. `translate.ts` rivede una chiave solo quando manca o ancora uguale all'inglese, quindi l'aggiunta di citazioni al valore inglese lascerebbe tutti i 19 traduzioni esattamente come sono — citata l'inglese, non citata tutto il resto — e nessuna esecuzione a corto di `--forza ` mai noterebbe. Questa è la trappola che rinomina e67f59b è stato scritto per evitare, e farlo di nuovo per la punteggiatura significherebbe un terzo nome chiave e una seconda ritraslazione completa di una linea che non ha cambiato parola. E il glifo non e' condiviso. Set tedesco „...“, francese « ... », giapponese 「...」. Uno coppia digitata in en.json è una convenzione che gli altri 21 locali portano erroneamente o cadere; `quotes: auto` risolve contro il `lang` su <html>, che [locale]/layout.tsx già imposta per locale, quindi ognuno ottiene il proprio. Inglese si risolve al riccio “...” che la copia del display vuole piuttosto che la macchina da scrivere coppia. `quotes: auto` è il valore iniziale ed è scritto comunque — `quotes` è ereditato, quindi una regola antenato aggiunto in seguito potrebbe altrimenti cambiare ciò che questo rende senza toccare questo blocco. Nient'altro in globals.css lo imposta oggi. Nessun cambiamento di dizionario in questo, quindi nessuna spinta cross-repo che ordina di sbagliare.
· kamo-internal
Espressione — colore, spirito Animali e logo come una decisione
Due comandi ad angolo diventano uno. Quella scissione è stata un incidente dell'ordine caratteristiche spedite piuttosto che una distinzione chiunque detiene: un colore, un modello e il marchio dell'organizzazione sono tre LAYERS di una domanda — che cosa fa questo riquadro sembra — e si combinano. Scegliere loro da due popup significava che non poteva mai vedere la combinazione che stavate facendo durante la realizzazione, così il foglio si apre su un'anteprima live che impila tutti e tre esattamente come il pannello li impila. THIRTY-FOUR SPIRIT ANIMALS, come SVG <pattern> sfida piuttosto che gradienti CSS. I gradienti fanno strisce e punti e molto poco altro, e la metà di questa lista è rosette, patch poligonali, bilance sovrapposte e copriocchi di un pavone. SVG disegna forme reali, rimane croccante a qualsiasi dimensione del pannello, prende l'inchiostro del membro direttamente, ed è markup piuttosto che un bene — nessuna richiesta per il CSP di avere un parere su e no byte da trasmettere. Le forme sono dati dichiarativi girati in elementi, così nulla raggiunge il DOM come una corda interpolata, e ogni l'inchiostro è espulso sulla strada per lo stesso motivo per cui il frame designer i colori sono. Colore e modello sono memorizzati separatamente e combinare, perché sono scelte separate: cambiare idea sul colore non deve perdere animale. L'inchiostro predefinito del modello è il colore del bordo della carta — il suo più profondo compagno — così "Sage + Leopard" significa leopardo in salvia piuttosto che leopardo in Qualche abbraccio non correlato, che è quello che un membro che sceglie quei due chiaramente significato. Un inchiostro esplicito dalla rampa di org o la loro tavolozza lo sovrascrive. Il disegno dipinge UNDER il contenuto del pannello e il suo vetro, a differenza del marchio org che doveva muoversi davanti per sopravvivere al blur. Una texture appartiene sotto stessa superficie ghiacciata il colore è sotto; davanti stampava zebra striscia attraverso il testo di qualcuno. Riguarda ovunque i vecchi controlli hanno fatto — widget, schede app, appunti pinned, la banda perno-widget — poiché tutti e quattro hanno già condiviso il pannello cromato. PaneColorButton e PaneBrandControl vengono eliminati piuttosto che lasciati accanto al loro sostituto: due modi per impostare una cosa è come si allontanano.
· kamo-internal
Contare sulla scheda Binders e atterrare su Docs selezionati
La scheda legge "Binders (n)" in modo che il conteggio del legante Docs selezionato è visibile dalla striscia — compreso (0), che è il caso da vedere, dal dice che il legante è vuoto prima che il membro vada a cercarlo. Entrando nella scheda ora si apre Documenti selezionati. Il membro arriva qui dalla scelta documenti, in modo che il legante è quello che sono venuti per; facendoli trovare nel la lista era un passo senza decisione. L'apertura di un altro legante durante una visita non è annullata dalla prossima sincronizzazione — la "già atterrato" bandiera è un ref reset da smontaggio, in modo da re-lands per visita piuttosto che combattere la metà del membro. Una nuova chiave i18n piuttosto che un reticolo di schede. leganti: la finestra di dialogo pacchetto legale usa quello come un'etichetta normale e non ha alcun conto da mettere in esso.
· kamo-internal
La cornice è il pannello, non qualcosa dentro uno
Ogni altro widget è contenuto nella carta di vetro smerigliata del launchpad, con una intestazione, un titolo e un controllo angolo. Una cornice non è: reso che come è un telaio seduto all'interno di un secondo, cornice invisibile, e lo stampaggio il membro progettato diventa un dettaglio all'interno del rettangolo di qualcun altro. Così il registro di sistema guadagna `ownsSurface`, e dichiarandolo porta via esattamente il tre cose che combattono un tal widget piuttosto che servirlo — il vetro superficie, lo sfondo COLOUR swatch (una cornice già ha un colore opaco e un modellare il membro scelto) e lo sfondo LOGO (una filigrana stampata attraverso la fotografia di qualcuno). Entrambi i luoghi che decorano la decorazione della vernice onorano esso: la griglia ordinabile e la banda a catena. Ciò che l'intestazione ha portato è ancora lì come controlli che sbiadiscono sopra stampaggio — il nome del telaio su una piastra leggibile in basso a sinistra, la strada nella sua editor e il controllo di rimozione in alto a destra. Oscuro e traslucido piuttosto che il solito cromo leggero del launchpad, perché questi siedono su una fotografia e un pallido pulsante svanisce il momento in cui un cielo luminoso atterra in quell'angolo. Si fermano eventi del puntatore da raggiungere il pannello sottostante, o raggiungere per l'editor Comincerebbe a trascinarsi. Una bandiera sul registro piuttosto che un assegno per questo id del widget, quindi il secondo widget che dipinge la propria superficie non ha bisogno di modifiche qui.
· kamo-internal
Mostra su quali strati di un documento modificato sono stati elaborati
Un documento ha un record modificato, quindi la scheda Modificata ha una riga per documento. I nomi delle colonne gli strati hanno toccato piuttosto che di due tipi riga era: Il documento una volta che i suoi byte differiscono dall'originale, campi di forma una volta i campi sono stati posti su di esso, e "non ancora modificato" per un record che è stato derivato dall'apertura di un editor e poi nulla è stato fatto. Quell'ultimo stato è reale e vale la pena dire: aprire un editor deriva il record, così sostenendo uno strato là avrebbe detto al membro hanno modificato qualcosa che solo Guardato.
· kamo-marketing
Scambiare il distintivo NOW LIVE per la titolo che si nascondeva
Il banner superiore ha condotto con una pillola di sei caratteri — confinato, maiuscolo, pulsing — e mettere il messaggio reale dopo di esso. La pillola ora porta il messaggio stesso: "La tua attività senza Kamo è un errore". Nessuno del tesserino cromato sopravvive. Una scatola 1px intorno a una frase completa legge come un pulsante, `text-transform: maiuscolo` griderebbe una riga scritta in frase caso, e 1.2px tracking è una misura del distintivo piuttosto che una lettura. The `:: dopo ` lavare bianco e il suo `badge-pulse` keyframe andare con loro, insieme il morto `.preview-banner-live` entrata nella lista di movimento ridotto — il l'animazione era sullo pseudo-element, quindi pinning l'elemento non ha mai fatto nulla. Quello che rimane è audace e bianco. #fff over #cc1111, la più leggera fermata del gradiente dietro di esso, misure 5.25:1; il resto del banner siede a 0,92 alfa, così il peso e che dura l'8% di bianco separano la titolo dal la linea di changelog accanto a esso. Il punto di rottura avvolge 640px -> 768px. Quel numero è stato scelto quando questa slot ha tenuto sei caratteri; la singola linea orarap ora misura ~625px con copia del changelog dopo di esso, così a 640px il banner passerebbe l'ultimo ~15px di la sua gamma di linea singola trabocca la propria scatola fissa 38px. 768 anche le linee avvolgere con il punto di rottura di movimento ridotto qui sotto, così il banner smette di shimmering e inizia a avvolgere ad una larghezza invece di due 128px separati. La chiave di copia è RENAMED, non rivalutata (lato dizionario, stesso set di modifiche). `translate.ts` coda una chiave solo quando manca o quando il suo valore ancora uguale alla fonte inglese — non ha alcuna nozione di una stringa inglese che è cambiata. Modificare `nowLive` in posizione avrebbe lasciato tutte le 21 località tradurre "Ora LIVE!" fino a quando qualcuno pensava di eseguire `--forza`. Una nuova chiave manca ovunque, così la prossima sincronizzazione lo raccoglie, e `writeLocaleFile` itera le chiavi, che prunes il vecchio da ogni locale. Fino a quel momento, il fallback inglese merge in i18n/request.ts rende la frase inglese piuttosto che una chiave grezza.
· InitializerService
Unire i due record modificati in uno con due strati
Se un documento ha entrambi i tipi, la riga CLASSIC sopravvive — è quella che può contenere byte modificate — il disegno è rinominato su di esso, e il FORM FILLABLE riga viene cancellata. Perdere entrambi i lati sarebbe perdere il lavoro dei membri: i byte sono modifiche realizzate in LibreOffice, il design è campo di posizionamento fatto a mano. L'indice unico diventa una riga per originale piuttosto che una per (originale, tipo), ed è costruito solo dopo la fusione non lascia nessun documento che tiene due. Modifica kind è volutamente lasciato nella tabella. Gettarlo si romperebbe DocsService pod ancora in esecuzione l'immagine precedente midrollout, che nomina il colonna in ogni SELECT Img; può andare una volta che la flotta ha girato. Il corridore precedente non crea più il vecchio indice unico per genere, quindi i due le migrazioni non spendono ogni corsa combattendo su di esso. Applicato a prod avanti a questa spinta: 8 righe modificate, 4 disegni portanti, 2 con divergenti byte, nessuno raddoppiato, niente perso.
· kamo-internal
Picture Frame — foto e video di un membro, in una cornice che costruiscono
Il primo widget INSTANCED. Un membro appende il maggior numero di cornici come piace, ogni con il proprio contenuto, il proprio stampaggio e il proprio posto nella griglia, tutto da una voce del Registro di sistema. Il MITRE. Un telaio è un profilo di stampaggio unico ripetuto su quattro lati e tagliato a 45° dove si incontrano, che è il modo in cui si realizza una vera cornice e la ragione modello non ha "fine superiore" o "fine sinistro" — non c'è nulla da tenere in passo perché c'è solo una cosa. Un membro progetta la sezione trasversale, i quattro i lati cadono fuori di esso, e ogni angolo è una linea 45° BY CONSTRUCTION piuttosto che con uno stile chiunque può sbagliare. Ogni lato è un trapezoide ritagliato fuori una scatola full-size e dipinto con un gradiente che scorre dal bordo esterno verso l'interno; le estremità inclinate sono il mitre, e quattro di loro piastrelle il confine con nessuna sovrapposizione e nessuna cucitura. I colori «frontali» sarebbero stati liberi ed erano strumento sbagliato: non possono portare un profilo multi-banda o una texture, e un membro che ha modificato un lato avrebbe altri tre da risolvere. La foto. Rapporto di controllo sempre tenuto, telaio sempre riempito, overflow cropped. Letterboxing all'interno di uno stampo sembra un difetto nella cornice piuttosto che un proprietà della foto. Le istanze viaggiano come `widget: frame-immagine# riquadro negozio e la preferenza show/hide, quindi una cornice mantiene le sue dimensioni, colore, logo e posizione e nascondendo uno lascia i suoi fratelli da soli. L'id vocabolario trasferito in widgetIds — puro e coperto, perché queste stringhe sono persiste nella disposizione di ogni membro e la loro forma è Portare il carico. Un'istanza di default a SHOWN: il membro l'ha fatto, e fare è la decisione di averla. L'editore al posto suo. mette il telaio a dimensioni appese a sinistra e tutto ciò che cambia su a destra. L'anteprima è il componente SAME il renderpad, non un facsimile — uno stampaggio che guarda raffinato a 90px è una lastra a 400, e due i renderrs andrebbero alla deriva con l'anteprima di essere quello che ha alla deriva. I risparmi sono debounced e ottimista: progettare un telaio è un centinaio di piccoli cambiamenti in un minuto, quindi un pulsante di salvataggio significa perdere il lotto a un clic sbagliato. Ogni colore in un disegno memorizzato viene ricontrollato prima che raggiunga un gradiente. Questi blobs sono dati autorizzati dai membri che vengono interpolati in un stile attributo, e il controllo è ciò che mantiene una cornice salvata da essere un modo scrivere CSS arbitrario. Media riordina con frecce piuttosto che trascinando: questa griglia si trova all'interno di una pagina raggiungibile da un launchpad il membro già trascina i riquadri intorno, e un secondo differently-behaved drag superficie è come la gente sposta la cosa sbagliata. Le frecce funzionano anche su un telefono e con una tastiera. I carichi vanno uno alla volta — sparando venti richieste multipart concurrent a una pod è come un membro con una cartella di vacanza prende il servizio giù per tutti Altrimenti.
· SecurityService
Telaio e media endpoint, e seminare i nuovi diritti
Solo se stesso, e imposto nella QUERY. Ogni lettura e scrittura risolve il membro della sessione e ogni chiamata del repository prende quello id, compreso la ricerca single-frame — un frame id è un UUID che viaggia al browser e indietro, così un findById avrebbe consegnato il muro di qualcun altro a chiunque indovinasse Uno. Non c'è volutamente un punto finale "gestire le cornici di un altro membro": un il controllo dell'amministratore su questa funzione è il diritto, non il contenuto. I media passano attraverso ImageService piuttosto che essere memorizzati qui, che acquista dedup (la stessa foto in tre cornici è un file memorizzato), og contabilità di archiviazione, e la riproduzione attraverso il proxy di imaging esistente — che già parla HTTP Range, quindi un video cerca già. Le ceneri sono calcolato nel controller perché la pipeline convalida il chiamante contro il proprio e il chiamante qui è il server; questo è ciò che ogni altro uploader lato server nella piattaforma. ORDER di una presentazione vive nel blob delle impostazioni della cornice, non come colonna su ogni immagine: una riga di immagini è condivisa da ogni associazione che ne fa riferimento bytes, quindi una sorta di colonna su di esso apparterebbe a qualsiasi frame ha scritto l'ultimo. Cancellare una cornice trattiene i suoi media. Lasciare le righe dietro sarebbe mantenere fatturare l'organizzazione per un muro nessuno può aprire, che è l'orfano classe questa piattaforma è stata morsa prima. Ceilings: 12 frames a member, 120 elementi a frame, 100 MB a file. L'ultimo è bene sotto gli altri limiti di caricamento della piattaforma di proposito — questa è parete decorazione che autoplays dietro un launchpad, e un video da 2 GB sarebbe preso da ogni scheda che il membro apre. Il seme dei diritti di MANAGE OWN BACKGROUND IMAGES, che già dice questo membro può decorare il proprio schermo con i propri uploads — il seme più sicuro del lotto, dato che niente in una cornice è dati di qualcun altro. DATI NON seme, a differenza di ogni altro widget: gli altri si aprono su qualcosa che il membro ha già e sono utili al momento in cui appaiono, mentre una cornice vuota che nessuno ha chiesto è ingombrante. I gestori nominano la loro sessione helper correnteMember così il non autorizzato ratchet endpoint può vedere la guardia — la sua scansione legge un corpo metodo e fa non seguire le chiamate.
· InitializerService
Crea la tabella picture frames
Una riga per Picture Frame widget un membro ha organizzato sul loro launchpad. Una tabella piuttosto che una preferenza blob perché le foto e i video in un frame sono file di imaging che trasportano il suo id in assoc object id, e un'associazione ha bisogno di qualcosa di durevole per puntare. Una cornice che vive solo all'interno di un membro Le preferenze di JSON sarebbero una chiave straniera per nulla: nulla potrebbe far rispettare che il frame esiste ancora, e la cancellazione delle preferenze di un membro sarebbe silenziosamente orfani ogni byte che avevano caricato. le impostazioni sono TEXT che tiene JSON di proposito. È l'aspetto della cornice — leggere tutto per disegnare un riquadro, scritto intero su salvare, mai messo in — così come colonne ogni nuovo bevel o grano il designer crescerebbe sarebbe un altro DDL cambiare atterraggio qui prima del servizio che lo mappa, per un valore nessuna query sarà sempre filtrare. @Order(0) per la convenzione di schema: una volta che l'entità condivisa-lib esiste, qualsiasi corridore che carica una PictureFrame attraverso JPA emette queste colonne nella sua SELECT, quindi una migrazione tardiva non sarebbe mai stata raggiunta — un precedente corridore morirebbe su "relation picture frames non esiste" e prendere la corsa Prima giù. NOTA PER DEPLOY: SecurityService esegue ibernate ddl-auto: nessuna, quindi questa tabella non appare da solo. Questo servizio deve essere RUN prima della cornice dell'immagine funzione funziona.
· kamo-shared-library
Lo schema, i diritti e il dominio di archiviazione dietro widget frame
Un frame immagine è un membro di proprie foto e video sul proprio launchpad, e un membro può appendere diversi. Questo è tutto il necessario per tenere la piattaforma Uno. PictureFrame è una riga piuttosto che una chiave nel blob preferenza del membro perché i media sono file di imaging associate BY frame id, e un'associazione ha bisogno di qualcosa di durevole per puntare. Iscritto piuttosto che utilizzatore: i byte sono memorizzati sotto un'organizzazione e contati contro di esso, quindi una cornice che ha seguito una persona tra org avrebbe messo uno stoccaggio di org su un altro Il conto di Org. Il suo aspetto è una colonna JSON — letto intero per disegnare un pannello, scritto tutto su salvare, mai queried in — così un designer che cresce un bevel Il mese prossimo non ha bisogno di un cambiamento DDL prima di esso. ImageAssocType.PICTURE FRAME per il FRAME, non il membro: diversi cornici sono diversi slideshow, e scoping al membro farebbe ogni di loro mostrano tutto. Compra dedup di contenuto-individuato gratuitamente, quindi un membro che mette la stessa foto in tre cornici è fatturato per uno. StorageDomain.PICTURE FRAMES ottiene la propria linea piuttosto che essere piegato in un secchio generale. Questo è l'unico dominio che un'organizzazione personale riempie un pochi megabyte alla volta con nessuno che lo amministra, e un org guardando la sua fattura deve vedere che separatamente dai documenti la sua attività funziona. Il test di copertura avrebbe fallito la costruzione altrimenti, che è il punto di esso. I diritti seguono la forma ogni altro widget utilizza — PICTURE FRAME WIDGET più i quattro bambini politici — appeso fuori MANAGE OWN BACKGROUND IMAGES, la destra che già governa i media personali che un membro mette sul proprio schermo. Non una radice: un widget la cui sovvenzione è irraggiungibile dal gruppo che possiede la sua i dati sono un diritto che nessuno trova. Ids 229-233; 228 è stato preso. Tassonomia 219/156/32/31 224/161/32/31.
· kamo-internal
Mettere i quattro scorciatoie membri su una riga
sono una classe di controllo, quindi ora condividono una riga: il launchpad's l'angolo in alto a destra legge come una singola striscia piuttosto che uno stack a due linee. styling; utilizza la pillola condivisaLinkSx come i suoi vicini, e collassa la sua etichetta a xs come fanno, così quattro scorciatoie ancora adattarsi un telefono. La fila avvolge piuttosto che traboccare quando un membro tiene ognuno di loro.
· kamo-internal
Posizione e colore per il logo di un pannello, e lasciare sempre che un membro apra l'editor
L'Editore era irraggiungibile per chiunque non fosse morto. `brandOf` rispose null fino a quando non esisteva un marchio e il controllo è stato cancellato sulla risposta, quindi un membro il cui non aveva funzionato — o non aveva persistito — non aveva alcun pulsante affatto e nessun modo di dare riquadro un logo. Un pannello indeciso è uno non marcato, non mancante: `brandOf` now sempre le risposte, e l'editor è sempre lì. La banda appiattita aveva lo stesso sintomo per un motivo diverso. Rende fuori SortableCard, che è ciò che rivela il cromo di un pannello su hover, così i suoi controlli si sedevano a opacità 0 permanentemente. Porta ora la regola stessa. POSIZIONE. Nove ancore nel popup, disegnate come una griglia le cui celle tengono ciascuno un punto nel loro proprio angolo, quindi il raccoglitore legge come il pannello che sta per. La rotazione doveva muoversi il logo stesso: ruotando la scatola di dimensionamento ha oscillato un segno bordato intorno al pannello centro e fuori dall'angolo che il membro aveva appena messo. COLORE. Il marchio può essere dipinto una solida silhouette, attraverso l'esistente di ThemeLogo overlayColor — una maschera CSS, quindi raggiunge un colore arbitrario piuttosto che spingere i colori dell'opera. Due fonti: la rampa di marca dell'organizzazione E' morto perche' un org che ha stabilito solo un primario. ha la sua luce e più leggera di default allo stesso valore; e la tavolozza del membro, usando il compagno profondo di ogni colore piuttosto che la sua carta pastello, poiché una silhouette pallida su un pannello pallido è un segno che nessuno può vedere. SIZE JOINS THE ROLL, tra 0,55 e 1.1 del pannello. Ogni segno a esattamente 0,85 era dire che una pagina era stata generata piuttosto che composta.
· kamo-internal
Dipingere le note master nei colori dell'organizzazione
"Il nostro Master Note" è il PRIMARY e il "My Master Note" dell'organizzazione SECONDARIO, ciascuno come un pastello — una tinta del 18% su bianco. La coppia legge come un set ad un colpo d'occhio, e nessuno può essere scambiato per uno dei dodici colori post-it un il membro sceglie per le proprie note. Derivato da --colore-primario / --colore-secondario piuttosto che un esago, quindi un white-label org ottiene il suo marchio. Il bordo è pavimentato contro ardesia e la carta deliberatamente non è: un org può impostare una primaria quasi bianca, e una tinta del 18% è solo un foglio più pallido, ma un bordo mescolato da solo sarebbe una regola invisibile, perno e caretto. Stesso ragionamento come i token della barra di scorrimento della pagina. Una conseguenza, ed è il punto: una nota principale non ha più tavolozza. Il colore è quello che dice la cui nota è, che non è la scelta di un membro — così il swatch è andato dal riquadro, la carta, il appiccicoso e l'editor, e KBService smette di vederne uno. '${color.edge}33` ha dovuto andare con esso. A seconda delle cifre esagonali a un colore-mix() espressione dà una dichiarazione che il browser scende silenziosamente, lasciando i confini con nessun colore; conStickyAlpha() prende entrambe le forme e ogni superficie delle note va ora. utilizzareMasterNotes anche sindacati con la cache del sovrapposto galleggiante, il modo selezionareInserimento Panes fa — altrimenti una nota master modificata nel suo appiccicoso ha mostrato la sua mount-time text on the launchpad fino a un reload.
· kamo-internal
Mettere le due note master su ogni launchpad
"My Master Note" e "Our Master Note" sono riquadri nella stessa griglia selezionabile come tutto il resto — trascinato, ridimensionato e ordinato come qualsiasi altro riquadro — e né può essere rimosso. L'organizzazione porta un anello conico-gradiente girante dipinto da --colore-primario, l'unico bordo in movimento sulla pagina, quindi l'unico pannello che ha fatto non viene dal membro legge come tale dall'altra parte della stanza. Reciso ad una statica anello sotto preferi-ridotto-mozione. Entrambi sono pinned, così arrivano anche nell'elenco pinned; selezionarePinnedPanes gocce li là, o ciascuno sarebbe dipinto due volte e il duplicato sarebbe la copia senza il distintivo e il bordo. Preso da /api/notes/master, che NON è gated sull'app Notes: il pinned i riquadri di note sono l'app Notes che versa sulla home page, e questi sono mobili della home page stessa. Ogni controllo che il server avrebbe rifiutato viene rimosso piuttosto che disabilitato: no unpin, no delete and no rinominare su entrambe le note master, e nessun colore, nessuna barra degli strumenti e nessuna superficie di digitazione dell'organizzazione è per un membro senza il diritto. A membro di sola lettura ottiene un lettore — lo stesso rendering del pannello utilizza — invece di un redattore i cui risparmi sarebbero respinti dopo aver fatto il lavoro. noteApi.saveNote percorsi per portata, quindi il appiccicoso, l'editor, la parete e il L'arresto del raccoglitore di colore del lavagna deve sapere che la nota dell'organizzazione ha Nessun membro e quindi non può essere raggiunto dal punto di vista per-id.
· KBService
Servire, fornire e proteggere le due note master
GET /api/notes/master risponde sia alle disposizioni mancanti. PUT /api/notes/master/org scrive "Our Master Note", indirizzata dall'organizzazione piuttosto che per nota id, quindi non c'è nulla da indovinare e nessun altro nota per raggiungere. Modificarlo richiede MANAGE ORG MASTER NOTE o la proprietà del organizzazione — il piano proprietario è la garanzia antiblocco, dal momento che il diritto è deliberatamente non seminato su ruoli esistenti. GET /master deliberatamente non prende note giuste. VIEW NOTES porta le note *app*; questi sono dispositivi della home launchpad, e "ogni membro ha sempre uno" ha significare ogni membro. Gli elenchi ordinari tengono il loro VIEW NOTES cancello e ora anche restituire la nota dell'organizzazione, quindi è leggibile e ricercabile sul muro. Le regole sono applicate qui piuttosto che nel cliente: una nota master non può essere cancellato (409 — un fatto circa la nota, non su chi chiede), non può essere non piegato, e non può essere rinominato. Titolo e pin sono ignorati piuttosto che rifiutati, perché l'editor invia ogni campo su ogni salvataggio e rifiutando la richiesta fallire una modifica al BODY su un titolo che il membro non ha mai toccato. Le chiavi dei contenuti seguono lo scopo: keyForOrg(orgId) per la nota dell'organizzazione, quindi ogni il membro dell'organizzazione può leggerlo. Deriving da chiunque l'abbia scritto fare una nota condivisa leggibile da una persona. Il provisioning è il proprio fagiolo e la propria transazione, e fa ogni lettura prima il suo primo scritto: dal momento che il trasferimento a Yugabyte un SELECT dopo una scrittura in uno transazione può tornare 40001 e annullare. Un metodo privato su NotesService sarebbe stato inerte come @ Transactional ed eseguire nella transazione del chiamante.
· InitializerService
Aggiungere le colonne del master-scope alle note
MASTER SCOPE ('MEMBER' / 'ORG' / NULL) e ORGANIZATION ID, più i due indici l'entità dichiara e un indice unico parziale per portata in modo da una nota master live per membro e per organizzazione è applicato dal database piuttosto che solo da la creazione di note in NotesService. Nessun backfill: ogni nota esistente è una nota ordinaria e NULL legge esattamente Quello. Le note master sono fornite pigramente sulla prima lettura che li vuole, che copre i membri e le organizzazioni creati dopo questo percorso senza una seconda migrazione. @Order(0), come ogni colonna-add runner: il momento in cui la libreria condivisa mappa queste colonne, qualsiasi corridore che carica una nota tramite JPA li emette nel suo SELECT, così una migrazione ordinato tardi non è mai raggiunto. Applicato a Yugabyte 2026-08-22: tutte le sette dichiarazioni applicate, sia colonne che tutti e quattro gli indici verificati presenti.
· kamo-shared-library
Modelli le note master e la destra che custodisce l'org
Una nota principale è quella che un membro — o un'organizzazione — ha sempre. "My Master Note" è fornito per appartenenza; "Our Master Note" è uno per l'organizzazione e appare su ogni launchpad di ogni membro. Entrambi sono ordinari `nota` righe che trasportano un MASTER SCOPE, non una nuova tabella, quindi la Editor Lexical, autosave, versioni, colori, appiccicoso galleggiante e RAG pubblicare tutti continuano a lavorare con nulla per mantenere in passo. Una riga ORG porta un NULL MEMBER ID di proposito: ogni ricercatore a giroscopio match `n.member.id = :memberId`, quindi la nota dell'organizzazione non può mai essere restituito dall'elenco privato di un membro, l'aggiornamento o l'eliminazione. Leggi che dovrebbero vedere passare attraverso il nuovo `...VisibleToMember` finders, che si allargano a esso esplicitamente; le scritture mantengono la coppia membro-scoped e quindi non possono raggiungerla affatto. MANAGE ORG MASTER NOTE (228) è una radice standalone con un servizio null seguendo MANAGE ORG BRANDING: il ruolo, il lavoro-titolo e gli editor di reparto solo rendere la sezione di un servizio quando l'org ha abilitato l'app e il master org nota è su ogni launchpad se o meno Note è acceso. Non genitori a VIEW NOTES per lo stesso motivo — KBService serve la nota senza un diritto di note.
· kamo-internal
Marcare un terzo dei riquadri di un membro con il logo org, e lasciare loro sintonizzare
Un terzo dei riquadri di un membro indossa lo stesso segno di org debole /leads e /calendar portare, a scala del pannello. Quali vetri, e come, è rotolato una volta e tenuto. Quello che la pallina e' morto. Il marchio di un pannello di marca dipende dalla forma del pannello è entrando, perché un wordmark e un'icona si adattano a rettangoli diversi. Un pannello quadrato è il ha dichiarato gettoni tra i due. Un'ampia si appoggia alla parola a tre su quattro — una wordmark è largo, e un'icona quadrata in una striscia a quattro colonne è un punto in un campo. Uno alto prende sempre la parolaccia e lo gira novanta gradi in senso orario, che si adatta a un pannello alto meglio di entrambi i marchi che giacciono. E ogni pannello di marca ottiene alcuni gradi di inclinazione qualsiasi altra cosa è stata rotolata: un segno posto perfettamente quadrato su un pannello rettangolare legge come un errore di layout, e alcuni gradi spento vero legge come un timbro, che è quello che è. The inclinazione va in entrambi i modi, perché una pagina di segni tutti appoggiati a sinistra legge come un bug di rendering. PER PANE, NON ONCE EVER — la differenza dalla semina del colore, e la ragione di un pannello che non è marcato ha quello registrato piuttosto che lasciato vuoto. L'assenza significa "questo pannello è nuovo, roll it", che è ciò che permette un widget acceso il prossimo mese, una nota pinned il prossimo settimana o un'app appena concessa dare lo stesso passaggio sulla sua prima apparizione mentre nulla già sulla pagina si muove. È anche il backfill: un launchpad organizzato prima di qualsiasi di questo esisteva non ha decisioni, così ogni suo riquadro è nuovo da quella definizione e è rotolato sul carico successivo. Nessuna migrazione, e nessun membro la funzione non riesce a raggiungere. L'ORG's OPT-OUT arriva prima. Un'organizzazione il cui bgWatermark è NONE loghi di sfondo off; una nuova superficie non è un'esenzione da una preferenza che già espresso, in modo che quei riquadri non facciano alcun segno qualsiasi cosa sia stata rotolata. L'Editore. Un controllo accanto al colore si apre un popover per il marchio stesso: pieno, semplice o nessuna, più rotazione, dimensione, tonalità e contrasto. Tutto in esso è vivo — il il valore va dritto nella preferenza che il pannello rende da, quindi un membro trascinando hue slider guarda il pannello dietro il cambio popover mentre trascinano. Conservati contro i loro record membro come ogni altra preferenza pannello. Il filtro è hue-rotate e contrasto piuttosto che la scala grigia della filigrana di pagina, perché la scala grigia spoglia la tonalità e sarebbe hanno lasciato il membro un cursore che non ha mosso nulla. Reset-to-defaults sulla pagina dei widget deliberatamente non chiari marche: ri-rolling a logo avrebbe consegnato a qualcuno un diverso launchpad ogni volta che lo premevano, che non è un reset.
· kamo-internal
Modifica in Modalità Classica e ridisegna quando salva
L'editor compilabile può ora riunirsi a LibreOffice. Il server deriva la versione classica sulla strada se il documento non ha uno, che è la il punto di offerta da qui — un membro che ha sempre aggiunto la forma campi non hanno una copia classica da aprire ancora. Quando l'altra scheda salva, l'editor ricarica. Le pagine dei suoi campi siedono su hanno appena cambiato sotto di esso, e altrimenti continuare a disegnare quelli sono stati posti sopra. Lo dice piuttosto che ridisegnare silenziosamente: differenza tra "il documento aggiornato" e "i miei campi saltati per niente ragione", e dopo un riflusso possono veramente bisogno di muoversi. L'editor che DID il salvataggio non è volutamente ricaricato — già detiene i byte che ha scritto, e ricaricarlo scarterebbe qualcosa digitato da allora. Ids sono confrontati come stringhe da fine a fine. Due diversi id membri int64 confrontano EQUAL come numeri, il che significa che un collega salva ricarica il tuo editore; il test afferma che l'uguaglianza direttamente in modo che la ragione non è solo un commento.

Il tuo universo ti sta aspettando.
Aggiungi i prodotti quando sei pronto: nessuna migrazione, nessun nuovo login, nessuna richiesta di pagamento.
Gratis per sempre — nessuna carta di credito richiesta