-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4bd7a07
commit 6272388
Showing
22 changed files
with
2,379 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
NEXT_PUBLIC_YORKIE_API_ADDR='http://localhost:8080' | ||
NEXT_PUBLIC_YORKIE_API_KEY='' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
NEXT_PUBLIC_YORKIE_API_ADDR='https://api.yorkie.dev' | ||
NEXT_PUBLIC_YORKIE_API_KEY='cedaovjuioqlk4pjqn6g' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module.exports = { | ||
rules: { | ||
'prettier/prettier': [ | ||
'error', | ||
{ | ||
endOfLine: 'auto', | ||
}, | ||
], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Yorkie Next.js react-calendar Example | ||
|
||
<p> | ||
<a href="https://yorkie.dev/yorkie-js-sdk/examples/nextjs-scheduler/" target="_blank"> | ||
<img src="https://img.shields.io/badge/preview-message?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMTUiIHZpZXdCb3g9IjAgMCAyNCAxNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTYuODU3MTcgMi43ODE5OUwxMS4yNzUxIDkuMTI2NzhDMTEuNTU0NCA5LjUyODAxIDEyLjEwNjIgOS42MjY3NiAxMi41MDc0IDkuMzQ3NDRDMTIuNTkzNCA5LjI4NzUgMTIuNjY4MSA5LjIxMjggMTIuNzI4MSA5LjEyNjc4TDE3LjE0NiAyLjc4MTk5QzE3LjcwNDggMS45Nzk1NCAxNy41MDcyIDAuODc2MTMxIDE2LjcwNDggMC4zMTc0OTRDMTYuNDA4IDAuMTEwODM3IDE2LjA1NSAwIDE1LjY5MzIgMEg4LjMxMDAxQzcuMzMyMiAwIDYuNTM5NTUgMC43OTI2NTQgNi41Mzk1NSAxLjc3MDQ2QzYuNTM5NjggMi4xMzIxMSA2LjY1MDUxIDIuNDg1MTEgNi44NTcxNyAyLjc4MTk5WiIgZmlsbD0iIzUxNEM0OSIvPgo8cGF0aCBkPSJNMTMuODA4OSAxNC4yMzg4QzE0LjEyMzEgMTQuNDE4IDE0LjQ4NDcgMTQuNDk2NiAxNC44NDUgMTQuNDY0MkwyMi45MjYgMTMuNzM1QzIzLjU3NTMgMTMuNjc2NSAyNC4wNTQgMTMuMTAyNyAyMy45OTU1IDEyLjQ1MzVDMjMuOTkyNCAxMi40MTkyIDIzLjk4NzggMTIuMzg1MSAyMy45ODE3IDEyLjM1MTNDMjMuNzM4OSAxMC45OTY4IDIzLjI2MTEgOS42OTUyNyAyMi41Njk5IDguNTA1NDZDMjEuODc4NiA3LjMxNTY1IDIwLjk4NDggNi4yNTU3NyAxOS45Mjg2IDUuMzczOTFDMTkuNDI4MiA0Ljk1NjE0IDE4LjY4MzkgNS4wMjMwNyAxOC4yNjYyIDUuNTIzNTZDMTguMjQ0MiA1LjU0OTkgMTguMjIzMyA1LjU3NzI2IDE4LjIwMzYgNS42MDU1MUwxMy41NjcgMTIuMjY0MUMxMy4zNjAzIDEyLjU2MSAxMy4yNDk1IDEyLjkxNCAxMy4yNDk1IDEzLjI3NThWMTMuMjUzN0MxMy4yNDk1IDEzLjQ1NjIgMTMuMzAxNiAxMy42NTU0IDEzLjQwMDggMTMuODMxOUMxMy41MDUgMTQuMDA1NCAxMy42NTIxIDE0LjE0OTMgMTMuODI4MSAxNC4yNDk2IiBmaWxsPSIjRkRDNDMzIi8+CjxwYXRoIGQ9Ik0xMC42NDE2IDEzLjc0MzRDMTAuNTM3NSAxMy45NTU5IDEwLjM3MiAxNC4xMzIyIDEwLjE2NjUgMTQuMjQ5NEwxMC4xOTE1IDE0LjIzNTFDOS44NzczNCAxNC40MTQzIDkuNTE1NjkgMTQuNDkyOSA5LjE1NTQ0IDE0LjQ2MDVMMS4wNzQ0MSAxMy43MzEzQzEuMDQwMTggMTMuNzI4MyAxLjAwNjA3IDEzLjcyMzcgMC45NzIyMjUgMTMuNzE3NkMwLjMzMDYyIDEzLjYwMjUgLTAuMDk2MzExOSAxMi45ODkyIDAuMDE4NzI0MiAxMi4zNDc2QzAuMjYxNTIyIDEwLjk5MyAwLjczOTM1NCA5LjY5MTU2IDEuNDMwNDYgOC41MDE2M0MyLjEyMTU3IDcuMzExNjkgMy4wMTU1MSA2LjI1MjA2IDQuMDcxODQgNS4zNzAwOEM0LjA5ODE4IDUuMzQ4MDYgNC4xMjU1NCA1LjMyNzE5IDQuMTUzNzkgNS4zMDc0N0M0LjY4ODc2IDQuOTM1IDUuNDI0MjcgNS4wNjY3MSA1Ljc5Njg3IDUuNjAxNjhMMTAuNDMzNCAxMi4yNjA0QzEwLjY0MDEgMTIuNTU3MyAxMC43NTA5IDEyLjkxMDMgMTAuNzUwOSAxMy4yNzIxVjEzLjI0MzJDMTAuNzUwOSAxMy40Nzk3IDEwLjY3OTggMTMuNzExIDEwLjU0NjggMTMuOTA2NyIgZmlsbD0iI0ZEQzQzMyIvPgo8L3N2Zz4K&color=FEF3D7" alt="Live Preview" /> | ||
</a> | ||
</p> | ||
|
||
<img width="500" alt="Next.js react-calendar" src="thumbnail.jpg"/> | ||
|
||
## How to run demo | ||
|
||
At project root, run below command to start Yorkie server and Envoy proxy. | ||
|
||
```bash | ||
$ docker-compose up -f docker/docker-compose.yml up --build -d | ||
``` | ||
|
||
Then install dependencies and run the demo. | ||
|
||
```bash | ||
$ npm install | ||
``` | ||
|
||
Now you can run the demo. | ||
|
||
```bash | ||
$ npm run dev | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
'use client'; | ||
|
||
import React, { useState } from 'react'; | ||
import './styles/calendar.css'; | ||
import styles from './styles/page.module.css'; | ||
|
||
import { EditorPropsTypes, CalendarValue } from './utils/types'; | ||
import { parseDate } from './utils/parseDate'; | ||
import Calendar from 'react-calendar'; | ||
|
||
/** | ||
* handle calendar component | ||
*/ | ||
export default function Scheduler(props: EditorPropsTypes) { | ||
const { content, actions } = props; | ||
const [date, onChange] = useState<CalendarValue>(new Date()); | ||
const [text, setText] = useState<string>('Enter text here!'); | ||
|
||
const currentDate = date ? parseDate(new Date(date.toString())) : ''; | ||
|
||
const eventHandler = (event: string) => { | ||
let flag = false; | ||
switch (event) { | ||
case 'PUSH': | ||
flag = false; | ||
content.forEach((item) => { | ||
if (item.date === currentDate) { | ||
flag = !flag; | ||
return 0; | ||
} | ||
}); | ||
|
||
flag | ||
? actions.updateContent(currentDate, text) | ||
: actions.addContent(currentDate, text); | ||
|
||
setText('Enter text here!'); | ||
break; | ||
case 'DELETE': | ||
actions.deleteContent(currentDate); | ||
break; | ||
} | ||
}; | ||
|
||
return ( | ||
<article> | ||
<div> | ||
<Calendar | ||
onChange={onChange} | ||
value={date} | ||
locale="en-EN" | ||
showNeighboringMonth={false} | ||
formatDay={(locale, date) => | ||
date.toLocaleString('en', { day: 'numeric' }) | ||
} | ||
tileClassName={({ date }) => | ||
content.find((item) => item.date === parseDate(date)) | ||
? 'highlight' | ||
: '' | ||
} | ||
/> | ||
<p>selected day : {currentDate}</p> | ||
<div className={styles.memo}> | ||
{content.map((item, i: number) => { | ||
if (item.date === currentDate) { | ||
return <p key={i}>{item.text}</p>; | ||
} | ||
})} | ||
</div> | ||
<div className={styles.inputForm_editor}> | ||
<h3>input form</h3> | ||
<textarea | ||
className={styles.textArea} | ||
value={text} | ||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => | ||
setText(e.target.value) | ||
} | ||
/> | ||
</div> | ||
<button className="button" onClick={() => eventHandler('PUSH')}> | ||
push | ||
</button> | ||
<button className="button" onClick={() => eventHandler('DELETE')}> | ||
pop | ||
</button> | ||
</div> | ||
</article> | ||
); | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import './styles/globals.css'; | ||
import type { Metadata } from 'next'; | ||
|
||
export const metadata: Metadata = { | ||
title: 'Next.js react-calendar example', | ||
description: 'example of yorkie-js-sdk with next.js & react-calendar', | ||
icons: { | ||
icon: './favicon.ico', | ||
}, | ||
}; | ||
|
||
/** | ||
* default root layout of service | ||
*/ | ||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<html lang="en"> | ||
<body>{children}</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** | ||
* 404-not found | ||
*/ | ||
export default function notFound() { | ||
return <h1>404 not found</h1>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/** | ||
* yorkie-js-sdk must be loaded on client-side | ||
*/ | ||
'use client'; | ||
|
||
import styles from './styles/page.module.css'; | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { ContentTypes, ENVtypes } from './utils/types'; | ||
import { displayPeers, createRandomPeers } from './utils/handlePeers'; | ||
import { parseDate } from './utils/parseDate'; | ||
import yorkie, { Document, JSONArray, DocEventType } from 'yorkie-js-sdk'; | ||
import Scheduler from './Scheduler'; | ||
|
||
// parseDate() value's format = "DD-MM-YYYY" | ||
const defaultContent: JSONArray<ContentTypes> = [ | ||
{ | ||
date: parseDate(new Date()).replace(/^\d{2}/, '01'), | ||
text: 'payday', | ||
}, | ||
{ | ||
date: parseDate(new Date()).replace(/^\d{2}/, '17'), | ||
text: "Garry's birthday", | ||
}, | ||
]; | ||
|
||
const ENV: ENVtypes = { | ||
url: process.env.NEXT_PUBLIC_YORKIE_API_ADDR!, | ||
apiKey: process.env.NEXT_PUBLIC_YORKIE_API_KEY!, | ||
}; | ||
|
||
const documentKey = `next.js-Scheduler-${parseDate(new Date())}`; | ||
|
||
/** | ||
* main page | ||
*/ | ||
export default function Editor() { | ||
const [peers, setPeers] = useState<Array<string>>([]); | ||
const [content, setContent] = useState<Array<ContentTypes>>(defaultContent); | ||
|
||
// create Yorkie Document with useState value | ||
const [doc] = useState<Document<{ content: JSONArray<ContentTypes> }>>( | ||
() => | ||
new yorkie.Document<{ content: JSONArray<ContentTypes> }>(documentKey), | ||
); | ||
|
||
const actions = { | ||
// push new content to Yorkie's database | ||
addContent(date: string, text: string) { | ||
doc.update((root) => { | ||
root.content.push({ date, text }); | ||
}); | ||
}, | ||
|
||
// delete selected content at Yorkie's database | ||
deleteContent(date: string) { | ||
doc.update((root) => { | ||
let target; | ||
for (const item of root.content) { | ||
if (item.date === date) { | ||
target = item as any; | ||
break; | ||
} | ||
} | ||
|
||
if (target) { | ||
root.content.deleteByID!(target.getID()); | ||
} | ||
}); | ||
}, | ||
|
||
// edit selected content at Yorkie's database | ||
updateContent(date: string, text: string) { | ||
doc.update((root) => { | ||
let target; | ||
for (const item of root.content) { | ||
if (item.date === date) { | ||
target = item; | ||
break; | ||
} | ||
} | ||
|
||
if (target) { | ||
target.text = text; | ||
} | ||
}); | ||
}, | ||
}; | ||
|
||
useEffect(() => { | ||
// create Yorkie Client at client-side | ||
const client = new yorkie.Client(ENV.url, { | ||
apiKey: ENV.apiKey, | ||
}); | ||
|
||
// subscribe document event of "PresenceChanged"(="peers-changed") | ||
doc.subscribe('presence', (event) => { | ||
if (event.type !== DocEventType.PresenceChanged) { | ||
setPeers(displayPeers(doc.getPresences())); | ||
} | ||
}); | ||
|
||
/** | ||
* `attachDoc` is a helper function to attach the document into the client. | ||
*/ | ||
async function attachDoc( | ||
doc: Document<{ content: JSONArray<ContentTypes> }>, | ||
callback: (props: any) => void, | ||
) { | ||
// 01. activate client | ||
await client.activate(); | ||
// 02. attach the document into the client with presence | ||
await client.attach(doc, { | ||
initialPresence: { | ||
userName: createRandomPeers(), | ||
}, | ||
}); | ||
|
||
// 03. create default content if not exists. | ||
doc.update((root) => { | ||
if (!root.content) { | ||
root.content = defaultContent; | ||
} | ||
}, 'create default content if not exists'); | ||
|
||
// 04. subscribe doc's change event from local and remote. | ||
doc.subscribe((event) => { | ||
callback(doc.getRoot().content); | ||
}); | ||
|
||
// 05. set content to the attached document. | ||
callback(doc.getRoot().content); | ||
} | ||
|
||
attachDoc(doc, (content) => setContent(content)); | ||
}, []); | ||
|
||
return ( | ||
<main className={styles.main}> | ||
<p> | ||
peers : [ | ||
{peers.map((man: string, i: number) => { | ||
return <span key={i}> {man}, </span>; | ||
})}{' '} | ||
] | ||
</p> | ||
<Scheduler content={content} actions={actions} /> | ||
</main> | ||
); | ||
} |
Oops, something went wrong.