Calendar
This demo shows the real-time collaborative version of a Calendar with Yorkie and Next.js.
page.tsx
1/**2 * yorkie-js-sdk must be loaded on client-side3 */4'use client';56import styles from './styles/page.module.css';7import React, { useEffect, useState } from 'react';89import { ContentTypes, ENVtypes } from './utils/types';10import { displayPeers, createRandomPeers } from './utils/handlePeers';11import { parseDate } from './utils/parseDate';12import yorkie, { Document, JSONArray, DocEventType } from '@yorkie-js/sdk';13import Scheduler from './Scheduler';1415// parseDate() value's format = "DD-MM-YYYY"16const defaultContent: JSONArray<ContentTypes> = [17 {18 date: parseDate(new Date()).replace(/^\d{2}/, '01'),19 text: 'payday',20 },21 {22 date: parseDate(new Date()).replace(/^\d{2}/, '17'),23 text: "Garry's birthday",24 },25];2627const ENV: ENVtypes = {28 url: process.env.NEXT_PUBLIC_YORKIE_API_ADDR!,29 apiKey: process.env.NEXT_PUBLIC_YORKIE_API_KEY!,30};3132const documentKey = `next.js-Scheduler-${parseDate(new Date())}`;3334/**35 * main page36 */37export default function Editor() {38 const [peers, setPeers] = useState<Array<string>>([]);39 const [content, setContent] = useState<Array<ContentTypes>>(defaultContent);4041 // create Yorkie Document with useState value42 const [doc] = useState<Document<{ content: JSONArray<ContentTypes> }>>(43 () =>44 new yorkie.Document<{ content: JSONArray<ContentTypes> }>(documentKey),45 );4647 const actions = {48 // push new content to Yorkie's database49 addContent(date: string, text: string) {50 doc.update((root) => {51 root.content.push({ date, text });52 });53 },5455 // delete selected content at Yorkie's database56 deleteContent(date: string) {57 doc.update((root) => {58 let target;59 for (const item of root.content) {60 if (item.date === date) {61 target = item as any;62 break;63 }64 }6566 if (target) {67 root.content.deleteByID!(target.getID());68 }69 });70 },7172 // edit selected content at Yorkie's database73 updateContent(date: string, text: string) {74 doc.update((root) => {75 let target;76 for (const item of root.content) {77 if (item.date === date) {78 target = item;79 break;80 }81 }8283 if (target) {84 target.text = text;85 }86 });87 },88 };8990 useEffect(() => {91 // create Yorkie Client at client-side92 const client = new yorkie.Client(ENV.url, {93 apiKey: ENV.apiKey,94 });9596 window.addEventListener('beforeunload', () => {97 client.deactivate({ keepalive: true });98 });99100 // subscribe document event of "PresenceChanged"(="peers-changed")101 doc.subscribe('presence', (event) => {102 if (event.type !== DocEventType.PresenceChanged) {103 setPeers(displayPeers(doc.getPresences()));104 }105 });106107 /**108 * `attachDoc` is a helper function to attach the document into the client.109 */110 async function attachDoc(111 doc: Document<{ content: JSONArray<ContentTypes> }>,112 callback: (props: any) => void,113 ) {114 // 01. activate client115 await client.activate();116 // 02. attach the document into the client with presence117 await client.attach(doc, {118 initialPresence: {119 userName: createRandomPeers(),120 },121 });122123 // 03. create default content if not exists.124 doc.update((root) => {125 if (!root.content) {126 root.content = defaultContent;127 }128 }, 'create default content if not exists');129130 // 04. subscribe doc's change event from local and remote.131 doc.subscribe(() => {132 callback(doc.getRoot().content);133 });134135 // 05. set content to the attached document.136 callback(doc.getRoot().content);137 }138139 attachDoc(doc, (content) => setContent(content));140 }, []);141142 return (143 <main className={styles.main}>144 <p>145 peers : [146 {peers.map((man: string, i: number) => {147 return <span key={i}> {man}, </span>;148 })}{' '}149 ]150 </p>151 <Scheduler content={content} actions={actions} />152 </main>153 );154}
- User 1
- User 2
- User 1
- User 2
Event Log