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({93 rpcAddr: ENV.url,94 apiKey: ENV.apiKey,95 });9697 // subscribe document event of "PresenceChanged"(="peers-changed")98 doc.subscribe('presence', (event) => {99 if (event.type !== DocEventType.PresenceChanged) {100 setPeers(displayPeers(doc.getPresences()));101 }102 });103104 /**105 * `attachDoc` is a helper function to attach the document into the client.106 */107 async function attachDoc(108 doc: Document<{ content: JSONArray<ContentTypes> }>,109 callback: (props: any) => void,110 ) {111 // 01. activate client112 await client.activate();113 // 02. attach the document into the client with presence114 await client.attach(doc, {115 initialPresence: {116 userName: createRandomPeers(),117 },118 });119120 // 03. create default content if not exists.121 doc.update((root) => {122 if (!root.content) {123 root.content = defaultContent;124 }125 }, 'create default content if not exists');126127 // 04. subscribe doc's change event from local and remote.128 doc.subscribe(() => {129 callback(doc.getRoot().content);130 });131132 // 05. set content to the attached document.133 callback(doc.getRoot().content);134 }135136 attachDoc(doc, (content) => setContent(content));137 }, []);138139 return (140 <main className={styles.main}>141 <p>142 peers : [143 {peers.map((man: string, i: number) => {144 return <span key={i}> {man}, </span>;145 })}{' '}146 ]147 </p>148 <Scheduler content={content} actions={actions} />149 </main>150 );151}
- User 1
- User 2
- User 1
- User 2
Event Log