Salta al contenuto
KAMOUniverse

Changelog

Cosa c'è di nuovo.

Ogni miglioramento alla piattaforma, come si spedisce.

  1. · kamo-internal

    Aggiungere la scheda Politiche, e smettere di offrire chat il backend rifiuta

    Quattro punti di vista su un progetto di regolamento, perché ci sono quattro domande diverse e nessun singolo layout risponde a tutti. Le regole sono ciò che ogni regola fa, Matrix è che l'organizzazione sembra, Simulatore è quello che succede a due denominato persone, l'attività è ciò che la politica sta facendo a tutti gli altri. Una regola è una frase, non una forma. Un amministratore che assembla il significato da sei riduzioni etichettate malediranno la propria politica; una lettura "Le vendite possono non chattare con tutti in un dipartimento diverso" non lo farà. Ogni modificabile frase è un chip, e le funzioni di frase vivono in app/lib in modo che possano essere unit-tested -- il vocabolario attraversa quel confine come dati piuttosto che come un traduttore, dal momento che vitest li corre nell'ambiente nodo. Le due estremità di una regola di una sola via sono indicate separatamente di proposito. "Le vendite possono iniziare chat con Ingegneria, che può rispondere solo mentre quella finestra rimane aperta" descrive ciò che il motore fa; ogni singola frase simmetrica descriverebbe regola che non esiste. L'ordine è quello che i primi-match-wins costa, quindi la scheda lo paga: l'impatto del progetto viene controllato continuamente contro ciò che è realmente vivo, ombreggiato e le regole duplicate sono denominate sotto la regola che influiscono, e gli spettacoli di pubblicazione quante coppie blocca prima del pulsante. Nuove regole e ogni modello arriva in modalità audit, dove registrano ciò che avrebbero bloccato e bloccato Niente. Il gallo è annotato, non filtrato. Un membro bloccato mantiene il nome, la foto e la presenza, e il loro pulsante di chat si spiega invece di sparire. Inoltre crea /api/members/directory, che il raccoglitore di componenti aggiuntivi di ChatBox ha da quando è stato scritto - il percorso non è mai esistito, quindi la richiesta 404'd e la finestra di dialogo ha reso un elenco vuoto con nulla che segnala un problema.

  2. · InitializerService

    Creare lo schema dei criteri di chat

    Sei tabelle: il regolamento versioned, le sue regole e le loro clausole, la risposta concede dietro "ripiegare solo mentre la loro finestra è aperta", e il sentiero la politica rifiutata. Ogni dichiarazione è scritta per essere completa e idemponte, perché questo corridore viene applicato a mano come spesso viene eseguito. Spingere questo repo non dispiega nulla... non c'è CI e nessun carico di lavoro -- mentre MediaService e SecurityService entrambi run ddl-auto:none, quindi niente crea questi tavoli alla loro startup. Se il DDL non è atterrato prima, quei servizi si dispiegano in modo pulito e poi gettano su ogni politica legge. Il DDL per questo cambiamento è stato applicato a Yugabyte prima di entrambe le spinte di servizio, e verificato facendo funzionare le proprie due query istantanee del motore contro di esso piuttosto che controllando il catalogo. Il test di accompagnamento confronta le entità a queste dichiarazioni di riflessione. All'interno del inizializzatore Hibernate crea le tabelle delle entità prima qualsiasi corridore esegue, quindi una colonna mancante qui è invisibile da questo lato e fatale sull'altro.

  3. · SecurityService

    Annunciare il roster membro con il suo verdetto politica di chat

    SecurityService serve il roster la chat UI è costruito da, quindi deve rispondere con gli stessi verdetti MediaService fa rispettare -- uno condiviso evaluator, o il prodotto offre conversazioni il backend poi rifiuta e legge come una chat rotta piuttosto che come una politica. Il gallo è annotato, mai filtrato. Un membro dei blocchi politici mantiene i loro nome, foto e presenza e perde solo la convenienza di chat, che poi trasporta la spiegazione dell'organizzazione. nasconderli sarebbe stato meno lavoro e avrebbe fatto mentire su chi lavora qui. Verdicts per l'intero roster si risolvono in un unico passaggio da una snapshot cache. Chiedere per membro avrebbe messo una valutazione -- e su una cache fredda, una query - all'interno di un anello che già funziona una volta per collega. Una politica che non riesce lascia ogni riga non annunciata piuttosto che mancare il roster: il percorso di invio è ancora l'autorità, quindi il costo è una convenienza confusa, non una forza politica.

  4. · MediaService

    Forzare la politica di chat org, e chiudere due fori su

    Si basa sulla politica nei tre posti in cui una conversazione può iniziare o continuare: creazione di sessione, componente aggiunge, e il percorso di invio. Una stanza non è poliziotto coppia coppia -- il cancello di invito è il cancello di messaggio diretto, in modo da poter portare qualcuno in una stanza esattamente quando si poteva inviare loro, e una stanza che si restringe torna a due membri bloccati viene riletto come messaggio diretto. Due fori preesistenti erano direttamente sotto questo lavoro e sono fissati con esso. Il punto finale non ha mai controllato che il mittente appartenesse alla sessione, quindi qualsiasi membro autenticato potrebbe inviare in qualsiasi guida di sessione che potrebbero indovinare -- un il cancello di politica sarebbe stato decorativo senza di esso. E gli indicatori di digitazione erano pubblicato su un nudo /topic/chat/typing che ogni client connesso nel organizzazione abbonata a; scoping loro per sessione ferma la perdita e ferma una coppia separata da segnalazione a vicenda. Reply concede "rispettare solo mentre la finestra è aperta": i report del browser quello che può vedere e il server decide, con una grazia che supera un mancato battere e non un portatile chiuso. La loro trasmissione è per membro e sorvegliato, dal momento che una sovvenzione forgiata avrebbe sbloccato un compositore la politica chiusa. La scrittura di amministratore è il proprio fagiolo e la sua transazione. Su YugabyteDB una lettura dopo una scrittura in una transazione solleva 40001 e interrompe tutto intorno a esso, e un auto-invocato @Transactional non è un confine affatto -- quindi il salvataggio legge prima, scrive, e legge di nuovo solo una volta che ha commesso.

  5. · kamo-shared-library

    Aggiungi il org chat policy engine

    Decide se un membro può aprire una conversazione con un altro, e se possono inviare in uno che esiste. Le regole sono un elenco ordinato sopra ordinato coppie e la prima partita decide, così ogni verdetto nomina esattamente una regola -- che è ciò che permette le impostazioni UI si spiega invece di chiedere amministratore per fidarsi. La regola di orientamento è la parte portante del carico. Una regola scritta SUBJECT -> TARGET viene valutato da entrambe le estremità: in avanti l'attore è il lato da cui è scritto, invertire il lato è scritto circa. Senza questo, "Le vendite possono messaggio Ingegneria one-way" andrebbe bene quando un venditore agisce e falla qualsiasi cosa si sieda sotto quando un ingegnere non fa niente nell'unico la direzione che esiste per limitare. L'assenza non è mai un accordo. Una clausola di dipartimento, titolo o manager non può corrispondere un semplice membro, e inapplicabilità cortocircuiti davanti alla negazione, quindi "non in Vendite" non spazza in ogni abbonato che non ha alcun dipartimento affatto. L'evaluatore non contiene repository e non apre alcuna sessione: due query costruiscono un per-org snapshot, e ogni verdetto dopo che è impostato aritmetico. Risolvere un manager chain attraverso JPA sarebbe stata una query per link per membro a profondità senza limiti, su un percorso che viene eseguito ogni volta che una cache diventa fredda.

  6. · kamo-internal

    Riordinare le schede e dipingere Binders e Uploads

    La striscia legge Originals | Modificato | Common | Binders | Uploads, che mette le tre viste dei documenti insieme e le due destinazioni dopo di loro. Binders e Upload ora portano quella lettura visivamente: marrone e blu sfondi con etichette e icone bianche. La `&&&&&` in dipintoTab è portante di carico. Il genitore Tabs stili i suoi figli attraverso `& .MuiTab-root`, un selettore discendente che supera un semplice per-tab sx, quindi un singolo `&` perde la cascata e l'etichetta rimane grigio sul nuovo sottofondo.

  7. · kamo-internal

    Dire quando un documento selezionato non potrebbe essere aggiunto

    Il legante Docs selezionato salta un documento che non può contenere legalmente piuttosto che fallire l'intera sincronizzazione, che è giusto — ma ha fatto così silenziosamente, quindi un legante tenere meno documenti del membro controllato leggere come la caratteristica rotto, e l'unico posto che esisteva era il registro DocsService.

  8. · kamo-internal

    Piegare la scheda Modifica in Binders

    La striscia è ora Originals | Binders | Modificato | Common | Caricamenti. Modificare è andato: tutto ciò che ha fatto — organizzare i documenti controllati, in anteprima loro, fondersi loro in un PDF o un ZIP — l'organizzatore già ha fatto meglio, e ha fatto per una lista che puoi tenere. Ciò che li collega è un pinned "Seletto Docs" voce nella parte superiore del legante lista. Detiene tutto ciò che è controllato nella griglia e viene riscritto su ogni cambiamento di selezione, quindi un membro controlla i documenti in Originals, apre Binders, e li trova lì in ordine. Non può essere rinominato, cancellato o condiviso; pulsante che lo salva, "Salva come Binder", è lo stesso duplicato dell'editor già avuto, rilabelled — su qualsiasi altro legante legge "Duplicare questo Binder", e entrambi fanno un nuovo legante del membro che tiene tutto il aprire uno tiene. Scarica ora offre ZIP accanto al PDF fuso, che è l'ultima cosa che la scheda Modifica potrebbe fare che un legante non poteva. Gocce modificate PubblicatoCon Modifiche per Differenza, due documenti affiancati lato, e la barra degli strumenti morto "Prepare & Download" pulsante ora apre il legante la sua etichetta descriveva sempre.

  9. · DocsService

    Servire e sincronizzare il raccoglitore Docs selezionato

    POST /api/docs/binders/scratch fetches the caller's Selected Docs binder for una raccolta, che la crea al primo utilizzo, e sostituisce i suoi documenti con il selezione griglia nello stesso giro — l'organizzatore chiama questo su ogni cambiamento di selezione, e due chiamate per casella di controllo è la differenza tra una legante che continua con la griglia e uno che visibilmente la infastidisce. La sincronizzazione contiene ogni documento ancora selezionato nella posizione del membro sistemato in e aggiunge i nuovi; separatori e pagine generate sono mai toccata, perché sono le aggiunte proprie del membro piuttosto che un riflesso della griglia. Un documento che non può legalmente aderire al raccoglitore è saltato piuttosto che mancare l'intera sincronizzazione — una selezione di griglia non è curata, così una brutta fila non deve fermare gli altri venti dall'arrivo. L'ordinazione regole sono una funzione pura in modo che possano essere testati senza un database. Rinominare, eliminare, condividere e la promozione dei modelli sono rifiutati per esso, e le regole per quello che può diventare un prodotto DOC ora vivere in un aiuto così aggiungendo a mano e sincronizzare non può allontanarsi da quello che accettano.

  10. · InitializerService

    Aggiungere leganti.is scratch

    Quattro dichiarazioni piuttosto che una ALTER: i leganti sono popolati, e Yugabyte respinge l'intero ADD COLUMN... Non la dichiarazione NULL piuttosto che la clausola, quindi la colonna arriva nullable, è riempita, guadagna il suo DEFAULT, e solo allora è serrato. @Order(0) per convenzione colonna-add — l'entità condivisa-lib ora le mappe sono scratch, quindi qualsiasi corridore che carica un Binder prima che questo muore una colonna che non esiste ancora.

  11. · kamo-shared-library

    Segnare il legante autogestito del membro

    binders.is scratch bandiere l'unico legante per (proprietario, collezione) il cui i documenti sono la selezione della griglia DocManager piuttosto che una lista curata. È un legante ordinario in ogni altro senso, quindi la query dell'elenco deve escluderlo a mano: l'organizzatore lo spilla sopra la lista, e lasciarlo in lo metterebbe c'è due volte e — peggio — offrire in ogni "add to binder" picker. La ricerca restituisce un elenco piuttosto che un opzionale perché due schede che aprono la organizzatore insieme può mancare e entrambi inserire; il chiamante prende il più vecchio.

  12. · kamo-internal

    Assemblare il record principale invece di tenerlo dietro un girante

    Lo stato di caricamento della scheda Dettagli era una scheda di quattordici righe di impulso grigio MUI — una forma il pannello non prende mai, su un orologio per-element, sostituito all'ingrosso da un il layout non sembra nulla. E ha aspettato su `loading.insights`: un record che era già arrivato seduto dietro segnaposto fino a quando una comunicazione non correlata Il conto e' tornato. Il pannello mostra ora il suo layout mentre aspetta — quattro piastrelle di stat, il callbacks strip, due righe di tre carte, alle larghezze reali — sotto una banda di luce di marca che attraversa la pagina su una diagonale, e le carte reali dai loro fantasmi su quello stesso ordine, così il record si risolve lungo il sentiero luce viaggiata. Solo il record porta il riquadro; i conti e l'elenco delle attività risolvere all'interno delle proprie piastrelle, e i riquadri del mercato estendere l'ingresso ordine quando la sua configurazione atterra. La testata si unisce alla stessa sequenza: un fantasma a forma di nome invece della parola "Loading", e una ferrovia a tre segmenti sul suo bordo inferiore — record, attività, configurazione — dove un segmento riempie il bianco nel momento in cui il suo fetch atterra. Realtà arrivi, non un timer. E 'assolutamente posizionato in modo che la scheda sottolinea soggiorni arrossire con il contenuto che etichetta. Uno scheletro che non risolve mai è il peggior stato finale che un disegno di carico ha, quindi un record fallito ora cede il passo a quello che è successo e un Retry che ri-corre i apertura fetches, sui dettagli e Mortgage schede entrambi. La coreografia `kmail-*` in globals.css diventa la casa `kload-*` famiglia — stesse regole, stesso contratto di movimento ridotto, più `kload-settle` per il handoff e i segmenti della ferrovia. /messages, /notes e /network si muovono invariati. Niente nuove chiavi i18n.

  13. · SecurityService

    Chiedi a EmailService di ricaricare un'e-mail passata

    Implementa la libreria condivisa LeadEmailBackfillTrigger, così ticchettio "Associate Passato E-Mails w/ Lead" su un salva piombo raggiunge l'unico servizio che può leggere cassette postali. Due pericoli sono stati affrontati qui piuttosto che in LeadService. Aspetta il commit: le partite di back-fill contro il punto di contatto che il salvataggio sta ancora scrivendo, e ha sparato in linea che avrebbe eseguito contro una fila nessun altro collegamento può ancora vedere, trovare niente, e riferisci il successo. E non fa mai aspettare il membro: anche accettare il lavoro è un salto ad un altro servizio che può essere giù, quindi va su un filo di sfondo con brevi timeout. Il risultato peggiore a disposizione membro è una guida che viene salvata normalmente.

  14. · EmailService

    Scansiona le caselle di posta dell'org per un'e-mail passata di piombo su richiesta

    Serve la casella di spunta "Associate Past E-Mails w/ Lead". Data una pista e indirizzo appena registrato su di esso, leggere INBOX e Inviato di ogni casella di posta in quella l'organizzazione di piombo indietro di un anno e allegare qualsiasi cosa che trasporta l'indirizzo. Ogni guardia il percorso automatico si applica ancora, perché entrambi i percorsi ora condividere una classifica(): un org i cui indirizzi non possono essere classificati è rifiutato un filo puramente interno è rifiutato, e un indirizzo aziendale non è mai una corrispondenza candidato — così ticchettio su un piombo la cui e-mail è noreply@ ancora non associa niente piuttosto che consegnare che portano l'intera posta dell'azienda ruscello. In cima a questi, l'indirizzo del piombo deve essere effettivamente sul messaggio. Esegue il thread di richiesta e single-threaded: un'intera organizzazione mailboxs richiedono molto più tempo per leggere di un salvataggio di piombo può bloccare, e la posta server consente solo una manciata di connessioni per utente per l'intero pod, quindi Concurrency qui sarebbe affamare la spazzata dal vivo piuttosto che andare più veloce. The endpoint risponde 202 "queued", mai "fondato qualcosa" — il membro guarda il E-mail scheda compilare. La selezione della cartella si sposta su MailboxFolderScope in modo da spazzare e il riempimento posteriore non può derivare da dove vive la posta; una linea temporale il cui contenuto dipendeva da cui percorso trovato un messaggio prima sarebbe peggio di entrambi.

  15. · kamo-shared-library

    Lasciare una mail di reclamo di piombo che predate il suo indirizzo e-mail

    La corrispondenza è punto in tempo per design — un punto di contatto solo rivendica il traffico all'interno della sua finestra, quindi la modifica di un lead non può riscrivere retroattivamente la storia. The costo è che una pista inserita dopo la conversazione iniziata non può mai mostrare che conversazione, e il membro non ha modo di dire "questo indirizzo era già loro». linkHistoric è così. Si allarga esattamente una cosa, la finestra, e niente altro: l'indirizzo deve ancora essere un punto di contatto di quel piombo esatto, in questo esatto, in una finestra. Non può inventare una partita, attraversare un inquilino, o raggiungere un piombo che non ha mai tenuto l'indirizzo — i test pin ciascuno di quelli, perché tutti tre falliscono silenziosamente, come la posta attaccata al piombo sbagliato legge come un piombo che Ci ha davvero scritto. LeadService acquisisce la cucitura che porta l'intento del membro (opzionale LeadEmailBackfillTrigger, assente nei servizi senza accesso alla posta) e entrambi richiesta DTOs ottenere la bandiera. La bandiera non è volutamente perseverata: descrive un risparmio, e ogni chiamante esistente — importazioni, endpoint di assunzione, patch MeridianLink, auto-save del spazzatore di blocco — non invia nulla e così acquisisce nessuna scansione casella di posta che non ha mai chiesto.

  16. · kamo-internal

    Offerta per associare e-mail passata quando viene impostato l'indirizzo di un lead

    La posta è abbinata a un lead rigorosamente point-in-time: un indirizzo rivendica solo traffico dal momento in cui è registrato, in modo che la modifica di un lead oggi non può riscrivere la cui posta la settimana scorsa era. Questo è giusto per il percorso automatico e errato per il caso un membro colpisce in realtà — entrando in una pista che hanno già stato e-mail, quindi trovare la scheda Email vuota e il thread apparentemente perso. Così entrambi i posti un indirizzo proprio di piombo può essere impostato — il pannello di contatto su /leads/view/{id} e la nuova forma di foglie — ora mostrano un passato non sottratto E-Mails w/ Lead" scatola accanto a esso. Ticking chiede al server di andare a cercare; lasciarlo da solo non cambia nulla. La casella appare solo una volta che un indirizzo è stato digitato, e non ricorda mai di essere legato: descrive un salvare, non il piombo, così non è perseverato e il costruttore di whitelist lo omette interamente quando falso piuttosto che inviare un falso l'auto-save del spazzatore di serratura si riproponerebbe come un scelta.

  17. · kamo-internal

    Un agente picker per l'assegnazione, le prenotazioni e il filtro

    Il controllo dell'agente assegnato sul pannello di assegnazione del piombo era un componente locale nel LeadViewClient. Altri due posti volevano esattamente esso, così si muove a E porta con sé la finestra di dialogo. Il riquadro di assegnazione è invariato nell'aspetto e nel comportamento — non possiede più il codice. Opportunità di riserva — un membro che detiene EDIT OPPORTUNITIES, il diritto che cancelli gestire le opportunità su /leads/opportunities/reserved, ora ottiene un agente di vendita il nome del campo per chi è la prenotazione. Si apre su se stessi, così il deposito loro la propria richiesta non costa niente di più. A differenza dell'agente assegnato al piombo non può essere svuotato: una prenotazione è l'affermazione di qualcuno, e uno non è uno stato record può contenere. Questo è l'intero `clearable={false}` — nessun pulsante chiaro su il campo, e non rimuovere nel raccoglitore. Il filtro /leads Agent è stato un Select alimentato da un fetch dell'intero personale directory, che è da dove sono arrivate le sue opzioni e perché potrebbe solo offrire una pagina di un org che può correre a cinque figure di persone. Si muove sulla stessa picker, che cerca una pagina alla volta, in modo che il filtro può ora raggiungere ogni nome — e la fetch intera directory, la sua cache del modulo e il suo filtro ACTIVE sono andati con esso, la stessa pulizia il riquadro di assegnazione già fatto. Le risposte utili di quel filtro includono tre che non sono persone, quindi MemberPickerDialog cresce `quickOptions`: righe incise sopra i risultati, qui Prima io, poi Tutti i Piombo, poi Unassigned Piombo per un membro permesso di vedere Quelli. Io stesso conduce perché è la risposta voluta più spesso e quella a ricerca directory rende più difficile da raggiungere — altrimenti si digita il proprio nome e scelga te stesso dai nomi. I seni si spostano in testa a GridQuery accanto a loro. la mappatura che le legge. Erano letterali di corda in entrambi i posti, e un deriva tra i due non mancherebbe di compilare: la query tratterebbe non riconosciuto sentinel come membro id, filtrare su un membro nessuno è, e mostrare un griglia vuota — che legge come "non hai piste" piuttosto che come un bug. La sessione porta un id membro e un'email ma nessun nome di visualizzazione, in modo da vedere il modulo di riserva con "tu" lo risolve una volta attraverso la ricerca directory. La partita è sul membro id, mai sull'email che ha prodotto la pagina: una casella di posta condivisa restituisce diverse persone, e prendendo il primo avrebbe presentato un'opportunità per un collega che non l'ha mai chiesto. Anche gocce ottenereAgentFilterMemberId, che non aveva chiamate e parseInt'd un Membro di 19 cifre.

  18. · SecurityService

    Accettare una prenotazione sollevata per un altro agente

    # E ora gli onori di BehalfOfMemberId # ceduto su EDIT OPPORTUNITIES — il diritto che i cancelli gestiscono le opportunità elenco riservato, e già il diritto necessario per spostare un'opportunità tra gli agenti dopo il fatto. CREATE OPPORTUNITIES da solo ancora i file propri. Un chiamante senza di esso che nomina un agente è REFUSED piuttosto che avere il campo E' caduto. Registrare silenziosamente la prenotazione sotto il proprio nome sarebbe attributo un reclamo a qualcuno che non l'ha mai fatto, e mostrerebbe al direttore una richiesta credono di aver chiesto qualcun altro. L'agente nominato è convalidato contro commissioneEligibleMemberIds — lo stesso piscina VIEW LEADS applicarePrimaryAgent utilizza e la stessa piscina che il picker offre. Parcheggio una prenotazione su qualcuno che non può aprire il piombo si riserva per loro. L'attore della fila di storia rimane la persona che ha agito; la nota dice per chi era. E perché REQUEST SUBMITTED va ad approvatori, l'agente per cui è stato depositato è aggiunto esplicitamente — non sono un approvatore, quindi altrimenti il primo sarebbe udienza di un reclamo a loro nome è la sua approvazione o negazione. Richiede la migrazione KamoInitializerService aggiungendo CREATED BY MEMBER ID per avere eseguire prima, o la prima lettura di eventuali getti di prenotazione.

  19. · InitializerService

    Aggiunga..

    Registrazioni che hanno presentato una prenotazione quando non è l'agente che chiama, quindi qualcuno gestire le opportunità può sollevare uno per conto di un agente di vendita senza il record dover sostenere che l'agente l'ha fatto da solo. Nullable senza backfill, per il motivo PRIMARY AGENT MEMBER ID non ha preso nessuno: null significa "il richiedente l'ha archiviato da solo", ogni riga che predice questa colonna sinceramente era autofilizzato e copiare il richiedente in avrebbe inventato un fatto e mettere una linea "Filed by" sulla storia nessuno eseguito. Nessun indice — niente filtri o tipi su di esso, quindi si costerebbe ogni scrittura e comprare Non leggere. Questo deve essere implementato ed eseguire prima del cambiamento SecurityService che mappa il colonna: i servizi eseguono ddl-auto:none, e Hibernate nomina ogni colonna mappata in il suo SELECT, così il servizio sarebbe iniziare sano e poi gettare la prima lettura di qualsiasi prenotazione.

  20. · kamo-shared-library

    Lasciare un manager alzare una prenotazione per un agente

    Qualcuno che gestisce le opportunità può ora presentare una richiesta di prenotazione su una vendita Per conto dell'agente. CreareRiservazioneRichiesta porta suBehalfOfMemberId per esso. L'agente nominato diventa REQUESTED BY MEMBER ID, non la persona che l'ha presentato. Ogni tasto di regola a valle fuori da quella colonna — chi può chiedere un'estensione, chi la commissione segue, ciò che il filtro dell'elenco riservato corrisponde — quindi il rivendicare deve sedersi dove queste regole guardano, e in realtà è la pretesa dell'agente. Chi seduto alla tastiera va in un nuovo CREATED BY MEMBER ID piuttosto che essere piegato nella stessa colonna, quindi né il fatto deve essere rinviato dall'altro. Nullable, e null mantiene il proprio significato: il richiedente lo ha archiviato da solo. PRIMARY AGENT MEMBER ID è volutamente lasciato nullo su questo percorso. Significa "un l'approvazione ha spostato questo dall'agente che ha chiesto", e l'elenco riservato rende un amber "Riassegnato da" linea per esso — ma una richiesta presentata per un agente non è mai stato spostato da chiunque, così `reassigned` rimane falso e `onBehalfOf` dice il vero invece.

  21. · kamo-internal

    Nascondi i controlli di bilancio che non possono usare

    Equilibrio di credito, Lega giornaliera e Max Balance tutti agiscono su un equilibrio concesso, e un prodotto FFA non ha nessuno — l'accettazione ci menti e spende il proprio credito. Lasciandole modificabili ha invitato un manager a impostare numeri che non potrebbero mai legare. Ora rendono come un chip muto con un tooltip dicendo così. Soggiorno Max Daily Spend modificabile ed è la leva reale su un prodotto FFA: il backend conta ora un L'accettazione FFA come una spesa, quindi il tappo vale anche lì.

  22. · kamo-shared-library

    Fai libero per tutti l'accettazione spendibile, in modo che possa essere bloccato

    FFA ha bypassato il sistema di credito in uscita, che ha lasciato un manager senza leva sopra it: Max Daily Spend si sedeva dietro se (!ffa) e non poteva catturare un prodotto FFA, e "accettato oggi" non aveva righe da contare perché nulla è stato mai speso. Un'accettazione FFA ora inganna un credito e lo spende sul piombo nello stesso blocco come il reclamo, così il record di spesa esiste sempre e non può mai derivare da incarico. Max Daily Spend si sposta dal ramo solo credito e si applica a — libero per tutti i mezzi il membro non è stato concesso un saldo da pagare da, non che un manager non possa legare quanti prendono in un giorno. Deliberatamente ancora solo credito: l'interruttore di credito a livello org e il controllo del saldo. FFA non ha equilibrio di essere breve. Il tappo viene controllato dopo quelli, quindi un credito membro sia rotto che bloccato continua a segnalare INSUFFICIENT CREDITS. Nota AccettareRisultato.creditSpent è ora vero sul percorso FFA (è stato documentato come sempre falso). È esatto — un credito realmente è consumato — e raggiunge il accettare la risposta e la pubblicazione Assigned NATS payload. Assegnazione del piombo Tipologia ancora record AUTO ASSIGN per FFA, così la storia mantiene i due a parte.

  23. · kamo-internal

    Chiama il richiedente, sposta la linea org, accorcia il pulsante Apri org

    Tre regolazioni sulle superfici di supporto. "Open org as System User" è ora "Open Org", seduto subito dopo assegnare/riassegnare piuttosto che alla fine della fila — appartiene alla stessa domanda quelle risposte: questo è l'altra cosa che fai quando un biglietto atterra sulla tua scrivania e la risposta è dentro inquilino del cliente. Il tooltip ancora precisa che la scheda si apre come Utente di sistema, che la breve etichetta scende. mantiene il suo peso; è una porta in qualcun altro affari e non dovrebbe leggere come un fratello del calo di priorità. L'organizzazione si allontana dall'intestazione del biglietto e a sinistra del "+ New Ticket" fila, che lascia l'intestazione per il biglietto stesso. Con diverse schede aprire la barra delle schede porta invece il nuovo controllo della protezione, così la riga rende per l'organizzazione da sola — ogni scheda può essere un cliente diverso, e questo è esattamente quando vale la pena di dire. The il titolo della finestra ora legge "{persona} - {org}", costruito in un posto perché il il percorso del visitatore-rinomina spinge anche un titolo e una seconda espressione è come l'org tranquillamente cade dal momento in cui un visitatore anonimo dà il loro nome. Chat → Le righe di supporto sono intitolate dopo la persona che ha chiesto, sempre. Apertura del biglietto si unisce alla sua chat, quindi uno occupato accumula agenti, e titling dall'altro i partecipanti hanno rinominato la fila ogni volta che un collega l'ha guardato — lo stesso conversazione che si presenta come una persona diversa. Il nome del richiedente ora concorda con il volto già sulla fila.

  24. · kamo-internal

    Dire quale orologio è attiva la finestra di dialogo evento e mostrare l'ora di inizio

    Quattro cose che il compositore ha sbagliato, su /calendar e sulla pagina principale allo stesso modo. La zona era del browser. Questo è un fatto sul computer portatile, non sul membro: qualcuno il cui profilo dice Eastern e che sta lavorando da Denver ancora libri il loro giorno in Oriente, e il dialogo seme "3pm Mountain" con niente sullo schermo per rivelarlo. Nuovi eventi ora compongono il membro zona profilo, risolto attraverso il fuso orario/efficacia di SecurityService — che è esistito da agosto e non ha avuto il prossimo percorso di fronte a esso, così ogni chiamata 404'd dentro Next e cadde in UTC. La zona è denominata sul valore, sotto il raccoglitore, e accanto alla data nell'intestazione, sull'offset in realtà in vigore l'appuntamento dell'evento piuttosto che quello di oggi. I campi di inizio e di fine si sedevano fianco a fianco con una freccia tra di loro e senza etichette a tutti, due scatole non annunciate che condividono la larghezza della carta — a quella larghezza un ingresso datetime-local ha meno spazio rispetto al proprio contenuto bisogno, quindi la lettura e' stato tagliato. Con la carta guidata "Start time" e le uniche parole visibili essendo il Oggi / Domani / I pulsanti di tutto il giorno accanto a esso, niente sullo schermo ha detto un inizio il tempo era lì per essere aggiustato. Sono impilati di larghezza piena ora, ciascuno chiamato, e la carta è diretta "Quando". Un nuovo evento è iniziato in cima all'ora corrente, che è in passato per cinquantanove minuti su ogni sessanta; il callback della pagina principale ha aggiunto un'ora e ha mantenuto i minuti dispari, offrendo 4:37 pm. Entrambi ora utilizzano defaultEventStart — un'ora fuori, arrotondato fino al quarto d'ora. Il calendario predefinito era quello che il servizio elencato prima, e il servizio elenca prima di proposito il calendario condiviso dell'organizzazione, perché questo è il giusto ordine di lettura nella barra laterale dove è un filtro. Qui il primo ingresso è anche il default, quindi un nuovo evento è stato pubblicato org-wide a meno che il membro notato e optato per una decisione che non hanno mai preso. L'elemento primario il calendario conduce ora, e quello condiviso porta un distintivo "org-wide". Il compositore di callback principale non semi più la zona di piombo silenziosamente; offre come un interruttore a un solo tocco etichettato accanto al membro. Il contesto compositore è mescolato, che è portante di carico piuttosto che ordinato — costruito in linea era un oggetto fresco ogni render, così i calendari che arrivano dalla rete mid-typing resettare la finestra di dialogo e scartare ciò che il membro aveva inserito.

  25. · SecurityService

    Pubblicare la dichiarazione di Hibernate conta a Prometheus

    /actuator/prometheus ha già portato jdbc * e hikaricp * ma nessun hibernate *, perché Spring Boot 3 solo auto-configura quelle metriche quando E' sulla pista di classe. Aggiunto, plus hibernate.generate statistics. La ragione è concreta. La revisione di questo servizio per le query N+1 doveva essere effettuata da grepping per la navigazione di associazione, e questo metodo è sbagliato in entrambi indicazioni: supera i paesi, perché un nome di associazione come 'vendor' o 'utente' è pigro su alcune entità e desideroso di altri (9 di 67 siti segnalati essere ansioso e non ha bisogno di nulla), e sotto-conta male, perché vede .getX().getY() ma non iterazione su una collezione pigra — che è la maggior parte superficie reale. hibernate statements total risponde alla stessa domanda per misura. Un punto finale emettere 200 dichiarazioni per chiamata è visibile qualsiasi forma il codice prende, e essere apertamente in vista significa che ognuno di quei carichi pigri è altrimenti silenzioso. Costi un po' per cento. Vale la pena in un servizio in cui l'ultima revisione ha trovato quattro O(rows) punti finali separati.

  26. · kamo-internal

    Mostra la foto del richiedente su ogni riga di chat di supporto

    Ogni riga in Chat → Supporto indossava lo stesso glifo di supporto blu, che non è aiuto a tutto quando la lista è quello che si scansiona per decidere cosa prendere. Il volto è ora il Chi l'ha chiesto. Il glifo sopravvive per esattamente un caso, ed è un fatto dal server piuttosto che un'ipotesi: un visitatore anonimo web-chat non ha alcun record, quindi il biglietto nomina il membro SYSTEM dell'org — il proprietario — come suo richiedente. Mostrare quella foto avrebbe messo la persona sbagliata sulla conversazione, e sul marketing della piattaforma widget sarebbe il volto di chiunque stia leggendo la lista. La directory org del visualizzatore è ancora consultata prima, perché è la copia live — una membro che ha cambiato la loro foto un momento fa è già lì — e URL del server è il fallback che copre i richiedenti in altre organizzazioni, che quella directory non ha mai sentito parlare. Le iniziali deliberatamente non rientrano nel titolo della riga: su una riga di supporto titolo è la controparte, quindi un richiedente il server non potrebbe nominare sarebbe dato le iniziali dell'agente di supporto, sull'avatar che esiste per dire chi sta chiedendo. Con né un nome né una foto non c'è nessuno da disegnare, e il glifo è onesto.

  27. · MediaService

    Metti il viso e il nome del richiedente su ogni riga di chat di supporto

    Una chat → riga di supporto ha mostrato lo stesso glifo di supporto su ogni linea, quindi una coda di erano un muro di cerchi blu identici. La gente faccia effettivamente la scansione per è chi ha chiesto, quindi la riga ora porta l'ID del richiedente, il nome del display e la foto. La foto viene risolta qui piuttosto che lasciata al cliente, che è l'intero difficoltà: ogni altro avatar in questo feed è riempito dal visualizzatore directory di organizzazione, e un richiedente di supporto è — sulla scrivania della piattaforma — sempre membro di qualcun altro, in modo che la directory non restituisce nulla per esattamente le righe questo è per. Due letture in batch coprono una pagina, nello stesso spirito del pre-fetch del visitatore accanto a loro. Il file avatar è riletto da id invece di essere tolto membro.getAvatar(): Avatar è una gerarchia JOINED e l'associazione è pigro, quindi ciò che ritorna è una proxy del tipo BASE. istanza di AvatarPhoto è falso attraverso di esso anche dopo inizializzazione, e ogni foto caricata sarebbe cercato il vettore Creator Avatar Percorso. Caricamento da id dà la sottoclasse concreta e la sua estensione di file. requestorIsAmbiguous è il caso per cui il glifo sopravvive, ed è un caso specifico piuttosto che una siepe: un visitatore anonimo web-chat non ha alcun record, quindi il proprietario — come suo richiedente. La loro foto avrebbe messo la persona sbagliata sulla conversazione, e sul marketing della piattaforma widget sarebbe il volto di chiunque stia leggendo la lista.

  28. · kamo-internal

    Conto piscina sull'intestazione del prodotto, accettato oggi per membro

    Leads Disponibile è stato reso in ogni riga di un gruppo di prodotti, ma è un proprietà del (prodotto, mercato) pool — lo stesso numero ripetuto giù il colonna per tutti i membri come regole. Si sposta all'intestazione del gruppo, una volta, dove appartiene. La colonna liberata ora mostra ciò che era realmente mancante: quanti conduce ogni membro ha accettato fino ad oggi, reso come "3 / 10" contro il loro Max Daily Spend così rimanente headroom è leggibile a colpo d'occhio. Il conteggio proviene da /manage, che risolve "oggi" allo stesso modo in cui il cappello fa — il fuso orario del membro.

  29. · kamo-shared-library

    Risolvere l'URL fotografico di un membro dalla libreria condivisa

    La lista Chats → Support sta per mostrare il volto del richiedente, e un supporto richiedente è — sulla scrivania della piattaforma — sempre membro di qualcun altro. Ogni altro avatar in quel feed è riempito sul client dal org di VIEWER directory, che non ne ha mai sentito parlare, quindi questo deve essere risolto lato server di MediaService. Ciò significa che un secondo servizio nomina un oggetto avatar, e il percorso dell'oggetto è esattamente la cosa che non deve esistere due volte: era prefissata con qualsiasi ospite richiesta è arrivata, quindi una foto caricata su un dominio di org 404'd quando letta da un altro, degradando alle iniziali e guardando come "nessuna foto" piuttosto che come un bug. Quindi AvatarObjectPaths si muove qui e la copia di SecurityService diventa un delegare alias non tiene corde proprie. MemberAvatarUrls aggiunge il resto della risoluzione: membro-override prima dell'utente default, foto vs Avatar Creator deciso dal DISCRIMINATOR prima istanza di — una pigrizia avatar caricato è un proxy del tipo di base, quindi istanza di inviare ogni caricato fotografia al percorso vettoriale — e host → dominio tema. Un host che non è un dominio non produce URL piuttosto che un'ipotesi: nessuna immagine si degrada alle iniziali, uno rotto non lo fa. Aggiunge anche REQUESTOR ID alle due proiezioni di supporto chat-feed.

  30. · SecurityService

    Ritorna il conteggio giornaliero di ogni membro per prodotto

    Manage-Credits mostra Max Daily Spend ma nulla di quanto viene utilizzato, così un manager non poteva dire se un membro era un vantaggio dal loro cappello o aveva Non è iniziata. /Manage ora restituisce accettatoOggi membro chiaveId::vendorProductId. "Oggi" è risolto esattamente come CreditLeadAssignmentService lo risolve quando si applica cap — il fuso orario del MEMBER, all'inizio del giorno, contando lo stesso LeadCredit.date righe spent — quindi la figura è letteralmente il numero del tappo è testato contro piuttosto che una seconda opinione su che cosa è un giorno. Una domanda raggruppata per membro, non una per membro x prodotto. Nota FFA relazione prodotti 0: l'accettazione non spende credito, e il tappo fa non applicarli nemmeno (l'intero blocco di credito è dietro se (!ffa)), quindi il due colonne rimangono coerenti.

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