Lewati ke konten utama

Pengeditan kolaboratif

getSharedStore() menjadikan editor sebuah simpul dalam sesi kolaboratif.
Metode ini memancarkan setiap perubahan sebagai aliran aksi dan menerapkan aksi yang dikirim balik oleh editor lain — Anda yang menyediakan transport di antara editor (WebSocket, WebRTC, atau apa pun yang dapat membawa JSON).
Metode ini adalah salah satu metode ErdEditorElement, dan berpasangan dengan Penyimpanan jarak jauh saat perubahan yang diteruskan juga harus disimpan.

interface ErdEditorElement extends HTMLElement {
// ...
getSharedStore: (
config?: SharedStoreConfig & {
mouseTracker?: boolean;
focusTracker?: boolean;
}
) => SharedStore;
}

type SharedStoreConfig = {
getNickname?: () => string;
};

type SharedStore = {
connection: () => void;
disconnect: () => void;
dispatch: (actions: Array<AnyAction> | AnyAction) => void;
dispatchSync: (actions: Array<AnyAction> | AnyAction) => void;
subscribe: (fn: (value: AnyAction[]) => void) => Unsubscribe;
flushStreamBuffers: () => void;
destroy: () => void;
};

// example
const sharedStore = editor.getSharedStore();

Aksi adalah objek biasa yang dapat diserialisasi dan menggambarkan satu perubahan pada dokumen, sehingga aksi tetap utuh melewati JSON.stringify dalam perjalanannya ke transport.
Aksi tiba dalam batch: subscribe memberikan sebuah array kepada Anda, dan array itu merupakan satu unit — teruskan array itu secara utuh dan kirimkan secara utuh di sisi seberang.
Perlakukan aksi sebagai data opak dan teruskan apa adanya alih-alih membaca atau menulis ulangnya, karena data pencatatan yang dibawanya itulah yang menjaga editor tetap sinkron.

Sebagian dari apa yang dilakukan sebuah editor tetap berada di editor itu.
Membawa tabel, memo, atau grup tabel ke depan, seperti yang terjadi saat memilihnya, tidak dikirim.
Pilihan Statements, Header, dan Tables di tab Skema SQL juga tidak dikirim, karena pilihan itu milik jendela tempat pilihan tersebut dibuat.
Sejak 4.1.0, Penjelajah juga tetap berada di editornya: apakah panel itu terbuka, lebarnya, baris yang diciutkan, baris tempat fokus keyboard berada, posisi guliran pohonnya, serta pencarian dan opsinya tidak dikirim.
Sorotan yang diberikan pada konektor hubungan saat menuju sebuah kunci asing juga tidak dikirim.
Guliran, zoom, atau perpindahan tab dikirim, tetapi tidak pernah memindahkan area pandang atau tab pengguna lain. Hal ini termasuk guliran yang dibuat oleh lompatan dari Penjelajah dan perpindahan ke tab ERD saat Penjelajah dibuka dari tab lain.

Penguncian dibagikan: penguncian atau pembukaan kunci terakhir pada sebuah pengaturan berlaku di setiap editor, dan penguncian membawa nilai dari editor yang mengaktifkannya, sehingga setiap editor dan replika menyimpan nilai yang sama.
Karena itu, penguncian Viewport menyimpan area pandang editor yang mengaktifkannya, dan penguncian Canvas Type menyimpan tab terakhir yang dibuka editor tersebut sebelum tab Pengaturan, tempat penguncian diaktifkan.
Menonaktifkan penguncian Language, Table Name Case, Column Name Case, atau Bracket Type juga menetapkan pengaturan itu di setiap editor ke nilai yang ditampilkan di editor yang menonaktifkannya, sehingga semua editor tetap menyimpan satu nilai. Menonaktifkan Viewport atau Canvas Type tidak memindahkan area pandang atau tab siapa pun.

Perubahan pada skrip Before tables atau After tables dikirim secara utuh saat kotaknya kehilangan fokus. Hasil kedua skrip ditentukan secara terpisah, sehingga perubahan seorang kolaborator pada salah satunya tidak pernah menimpa yang lain.

Apa pun yang dilakukan di mode Alur pada tab Visualisasi bukanlah perubahan dokumen, sehingga editor yang berada di Alur tidak mengirim perubahan apa pun ke editor lain, dan perubahan yang dikirim editor lain tetap diterapkan selama editor itu berada di sana.
Satu-satunya pengecualian adalah meninggalkan Alur menuju tab lain: perpindahan tab itu dikirim seperti perpindahan tab lainnya.
Tombol tautan eksternal pada kartu, hasil Pencarian Cepat yang dipilih setelah #, @, atau :, serta membuka Penjelajah semuanya meninggalkan Alur menuju tab ERD. Guliran yang dibuat tombol kartu atau hasil Pencarian Cepat di sana juga dikirim.

Dua editor dalam satu halaman​

Sambungan dari subscribe ke dispatch di sini menggantikan jaringan, sehingga Anda dapat melihat bentuk sebuah sesi tanpa transport yang menghalangi.

const editor1 = document.createElement('erd-editor');
const editor2 = document.createElement('erd-editor');

const sharedStore1 = editor1.getSharedStore({
getNickname: () => 'editor1',
});
const sharedStore2 = editor2.getSharedStore({
getNickname: () => 'editor2',
});

sharedStore1.subscribe(actions => {
sharedStore2.dispatch(actions);
});

sharedStore2.subscribe(actions => {
sharedStore1.dispatch(actions);
});

Kedua editor di sini dimulai dari dokumen baru yang sama dan kosong, sehingga keduanya tidak perlu diisi data awal.
Dengan tiga editor atau lebih, kirim batch dari setiap editor ke semua editor lainnya: editor tidak pernah meneruskan apa yang diterimanya.

Mengisi data awal kolaborator​

Shared store meneruskan perubahan saat perubahan itu dibuat dan tidak pernah memberikan dokumen dalam keadaannya saat ini kepada editor yang bergabung, sehingga editor yang bergabung ke sesi yang sudah berjalan harus diberi dokumen terlebih dahulu.
Sejak 4.0.0, isi data awalnya dengan runtimeValue dari editor yang sudah berada di sesi, bukan dengan value atau file yang disimpan.

editor2.setInitialValue(editor1.runtimeValue);

const sharedStore2 = editor2.getSharedStore();

Nilai runtime masih memuat apa yang telah dihapus sejak dokumen dibuka, sehingga saat editor lain kemudian membatalkan sebuah penghapusan, editor yang bergabung mengembalikan tabel itu beserta nama dan kolomnya.
value adalah bentuk yang tersimpan di file, tanpa entitas yang dihapus, sehingga editor yang bergabung dan diisi data awal darinya, atau dari file, justru akan mengembalikan tabel kosong tanpa nama.
Tetap tulis value ke penyimpanan: runtimeValue hanya untuk mengisi data awal editor lain, tampilan kedua, atau replicationStore.
Editor di VS Code, Obsidian, IDE JetBrains, dan aplikasi web mengisi data awal tampilan kedua dari dokumen yang terbuka dengan cara ini.

setInitialValue tidak diteruskan, sehingga mengisi data awal editor yang bergabung tidak mengubah apa pun di editor lain.
Sejak 4.0.0, metode ini juga membuang register kolaborasi editor, yang menentukan hasil perubahan serentak. Jika shared store editor itu sudah pernah memiliki subscriber, store meminta register milik editor lain lagi, seperti pada subscribe pertamanya, sehingga editor yang dimuat ulang di tengah sesi menentukan hasil perubahan dengan cara yang sama seperti editor lain.
Menetapkan value mempertahankan register tersebut, tetapi tidak seperti setInitialValue, penetapan ini diteruskan: begitu editor memiliki shared store, setiap editor di sesi memuat dokumen yang ditetapkan, jadi jangan pernah mengisi data awal editor yang bergabung dengan cara itu.

Mencampur rilis​

Editor hanya menerapkan tipe aksi yang dikenal rilisnya sendiri, sehingga dalam sesi yang mencampur rilis, editor yang lebih lama melewatkan apa pun yang dibawa oleh tipe yang lebih baru.

Sejak 3.10.0, perubahan pada ON DELETE atau ON UPDATE sebuah hubungan dibawa oleh salah satu dari dua tipe aksi baru, relationship.changeOnDelete dan relationship.changeOnUpdate, dan relationship.add dapat membawa keduanya. Relai yang meneruskan aksi apa adanya tidak memerlukan apa pun yang baru untuk keduanya.
Editor rilis sebelum 3.10.0 mengabaikan tipe aksi dan field tersebut: editor itu tidak pernah mengetahui ON DELETE atau ON UPDATE sebuah hubungan, dan dokumen yang disimpan darinya tidak memiliki keduanya. Hubungan yang ditambahkan editor yang lebih lama tiba tanpa keduanya, sehingga keduanya bernilai awal Not set.

Setiap perubahan lain yang dikirim editor 3.10.0 dibawa oleh tipe aksi yang sudah dikenal editor yang lebih lama.
Replace All di Temukan dan Ganti mengirim perubahannya sebagai satu batch berisi aksi penggantian nama, komentar, dan memo yang sama dengan yang dikirim oleh pengeditan manual. Opsi tampilan Alternate Key dan Referential Actions dibawa oleh aksi settings.changeShow yang sudah ada.

Sejak 4.0.0, perubahan berikut dibawa oleh tipe aksi baru, dan relai yang meneruskan aksi apa adanya tidak memerlukan apa pun yang baru untuk perubahan tersebut:

  • grup tabel yang ditambahkan, dipindahkan, diubah ukurannya, diganti namanya, diubah warnanya, atau dihapus: tableGroup.add, tableGroup.move, tableGroup.moveTo, tableGroup.resize, tableGroup.changeName, tableGroup.changeColor, dan tableGroup.remove; tabel yang masuk ke atau keluar dari grup: table.changeGroup;
  • klik Save di Petakan Kolom pada hubungan yang sudah ada, yang menetapkan kedua daftar kolomnya sekaligus: relationship.changeColumns;
  • penguncian yang diaktifkan atau dinonaktifkan: settings.changeLockSettings;
  • perubahan pada skrip Before tables atau After tables di tab Skema SQL: settings.changeDDLScript.

Opsi tampilan Table Groups dan Memos dibawa oleh aksi settings.changeShow yang sudah ada.
settings.changeIgnoreSaveSettings, yang dikirim sakelar Save Scroll Information dan Save Zoom Information sebelum penguncian menggantikannya, tidak lagi dikirim, dan settings.changeRelationshipOptimization sudah dihapus. Editor 4.0.0 yang menerima salah satunya tidak mengubah apa pun.

Editor rilis sebelum 4.0.0 mengabaikan tipe aksi baru: editor itu tidak pernah melihat grup tabel atau tabel mana yang ada di dalamnya, meskipun penyeretan grup tetap memindahkan tabel grup itu di editor tersebut, karena penyeretan juga mengirim table.move milik tabel-tabelnya.
Editor itu mempertahankan kolom lama sebuah hubungan setelah klik Save di Petakan Kolom, dan saat sebuah kolom dari pemetaan lama itu dihapus di editor tersebut, hubungan itu hilang di setiap editor. Editor itu tidak memiliki penguncian maupun skrip.
Dokumen yang disimpan darinya tidak memiliki satu pun dari semua ini, dan editor 4.0.0 membukanya dengan setiap penguncian aktif.
Pastikan setiap editor dalam sesi, dan setiap replicationStore yang menyimpan dokumennya, menggunakan 4.0.0 atau yang lebih baru.

Editor 4.1.0 tidak mengirim tipe aksi baru, sehingga editor dan replika 4.0.0 dan 4.1.0 berbagi sesi tanpa ada yang terlewat.
Temukan dan Ganti di editor itu juga mencari nama indeks dan nama grup tabel, dan Replace serta Replace All mengganti namanya melalui aksi index.changeName dan tableGroup.changeName yang sudah diterapkan editor 4.0.0.

SharedStoreConfig​

getNickname​

Mengatur nama panggilan yang ditampilkan di samping kursor mouse pengguna ini di editor lain.
Pengguna lain melihat user saat nama panggilan tidak ada atau kosong.

editor.getSharedStore({
getNickname: () => 'nickname...',
});

mouseTracker​

Menyiarkan kursor mouse pengguna ini ke editor lain. Nilai defaultnya true.
Kursor yang dikirim pengguna lain selalu ditampilkan di kanvas ERD.

editor.getSharedStore({ mouseTracker: false });

focusTracker​

Menyiarkan apa yang sedang dikerjakan pengguna ini. Nilai defaultnya true.
Tabel dan sel yang Anda fokuskan, tabel, memo, dan grup tabel yang Anda pilih, serta kotak yang Anda seret di kanvas dikirim ke editor lain dan digambar di sana.
Setiap pengguna mendapat warnanya sendiri agar Anda dapat membedakan mereka: garis tepi pada tabel yang difokuskan, garis bawah pada sel yang difokuskan, cincin di sekeliling tabel, memo, dan grup tabel yang dipilih, serta persegi panjang putus-putus untuk kotak seret.
Kehadiran yang datang dari pengguna lain selalu digambar di kanvas Anda, baik opsi ini aktif maupun tidak.
Di mode Alur pada tab Visualisasi, fokus dan pilihan pengguna lain digambar pada kartu tabel, tetapi kotak seret mereka tidak. Tabel yang Anda pilih di sana tetap dikirim; kotak yang Anda seret di sana tidak.

editor.getSharedStore({ focusTracker: false });

Nonaktifkan kedua pelacak untuk menggunakan shared store sebagai relai biasa yang tidak memublikasikan kehadirannya sendiri.
Kehadiran yang dikirim editor lain tetap diterima dan digambar.
Inilah yang dilakukan editor di VS Code, Obsidian, IDE JetBrains, dan Google Drive.

editor.getSharedStore({ mouseTracker: false, focusTracker: false });

Kursor, fokus, pilihan, dan kotak seret dibawa oleh aliran yang sama dengan perubahan dokumen, tetapi semuanya bersifat sementara.
Semuanya tidak pernah masuk ke dokumen, riwayat pembatalan, atau editor.value, sehingga transport bebas membuangnya dan replicationStore mengabaikannya.

SharedStore​

connection, disconnect​

Kedua metode ini mengatur status koneksi saat ini.
Selama koneksi terputus, perubahan ditampung dalam buffer secara internal.
Perubahan yang ditampung dalam buffer dipancarkan ke subscriber setelah transmisi kembali memungkinkan.
Status defaultnya terhubung (connection).

sharedStore.connection();
sharedStore.disconnect();

dispatch, dispatchSync​

Menerapkan perubahan dari instans editor lain ke instans editor saat ini.

sharedStore.dispatch(actions); // async
sharedStore.dispatchSync(actions); // sync

subscribe​

Berlangganan perubahan di editor.
Tidak ada yang keluar dari editor hingga ada setidaknya satu subscriber, dan perubahan yang dibuat sebelum itu ditampung dalam buffer.
Subscribe pertama juga meminta register kolaborasi dari editor lain, yang menentukan hasil perubahan serentak, sehingga editor yang terlambat bergabung menentukan hasilnya dengan cara yang sama.
Subscribe tidak membawa dokumen, jadi isi data awal editor yang terlambat bergabung terlebih dahulu.
Sejak 4.0.0, store meminta lagi setiap kali setInitialValue memuat dokumen ke editornya setelah subscribe pertama itu.

const unsubscribe = sharedStore.subscribe(actions => {
// send...
});

flushStreamBuffers​

Mengirim batch aliran yang masih ditahan store ini sekarang juga, alih-alih setelah periode senyapnya.
Sejak 3.9.2, metode ini berfungsi pada store dari getSharedStore; di 3.9.1, metode ini ada pada tipe tetapi tidak melakukan apa pun.
Memindahkan tabel, memo, atau grup tabel, mengubah warnanya, mengubah ukuran memo, serta menggulir atau melakukan zoom pada area pandang masing-masing tiba sebagai aliran perubahan kecil. Mengubah ukuran grup tabel tidak demikian: perubahan itu dikirim sekali, saat penyeretan berakhir.
Store mengumpulkan setiap aliran menjadi satu batch dan menahannya hingga aliran itu senyap selama 200ms. Store melakukannya dalam dua tahap, sehingga batch keluar sekitar 400ms setelah perubahan terakhir.
Panggilan metode ini mengakhiri penantian itu di kedua tahap. Selama store terhubung, subscriber menerima batch sebelum panggilan itu selesai. Panggilan saat tidak ada yang ditahan tidak mengirim apa pun.
destroy, baik milik store maupun milik editor, membuang batch yang masih ditahan, jadi panggil metode ini terlebih dahulu saat Anda melepaskan store dan editor lain harus tetap menerima perubahan terakhir, seperti saat tab ditutup.

sharedStore.flushStreamBuffers();
sharedStore.destroy();

destroy​

Menghancurkan instans sharedStore sepenuhnya.
Editor itu sendiri tidak disentuh, sehingga dokumen tetap dapat diedit setelah sesi ditinggalkan.
Pelacak mouse dan fokus berhenti setelah sharedStore terakhir yang diberikan editor dihancurkan.
Batch aliran yang masih ditahan store ikut dibuang; panggil flushStreamBuffers terlebih dahulu untuk mengirimnya.

sharedStore.destroy();