-
-
Notifications
You must be signed in to change notification settings - Fork 62
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
Showing
38 changed files
with
16,949 additions
and
1 deletion.
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 |
---|---|---|
@@ -1,2 +1,3 @@ | ||
node_modules | ||
runtimes | ||
runtimes | ||
examples/social-network/frontend |
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 @@ | ||
#we need to explicitly exclude them as they're not relevant to the source code | ||
sonar.exclusions=examples/**/* |
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,19 @@ | ||
# Social Network Example | ||
|
||
This example was created as part of the [talk Fran Mendez did at QCon Plus 2021](https://plus.qconferences.com/plus2021/speakers/fran-mendez). | ||
|
||
Here's an overview of what this example is about: | ||
|
||
![](./architecture.jpg) | ||
|
||
## Run it | ||
|
||
There are three services. All of them can be started by running: | ||
|
||
``` | ||
npm run dev | ||
``` | ||
|
||
You'll have to customize the `db.json` file with your own data (especially the Slack IDs). | ||
|
||
For the notifications service, you'll have to configure the Slack API URL in the `.env` file. Head over https://api.slack.com/messaging/webhooks to know more. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,46 @@ | ||
{ | ||
"likes": [ | ||
], | ||
"users": { | ||
"1": { | ||
"id": 1, | ||
"slackId": "<@U34F2JRRS>", | ||
"coverImageUrl": "https://pbs.twimg.com/profile_banners/87489271/1617659258/1500x500", | ||
"imageUrl": "https://pbs.twimg.com/profile_images/1373387614238179328/cB1gp6Lh_400x400.jpg", | ||
"name": "Fran Mendez" | ||
}, | ||
"2": { | ||
"id": 2, | ||
"slackId": "<@UD698Q5LM>", | ||
"coverImageUrl": "https://pbs.twimg.com/profile_banners/407861759/1632725036/1500x500", | ||
"imageUrl": "https://pbs.twimg.com/profile_images/1435858354967093254/carWrDQa_400x400.jpg", | ||
"name": "Lukasz Gornicki" | ||
} | ||
}, | ||
"posts": [ | ||
{ | ||
"id": 1, | ||
"userId": 1, | ||
"imageUrl": "https://images.unsplash.com/photo-1466637574441-749b8f19452f?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=880&q=80", | ||
"text": "Cooking at home with some friends and good wine 🍷" | ||
}, | ||
{ | ||
"id": 11, | ||
"userId": 2, | ||
"imageUrl": "https://images.unsplash.com/photo-1502599213010-875782f9bf52?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=697&q=80", | ||
"text": "The best of working remotely? Hacking on my favorite coffee-shop 🥤🤙🏽<br /><br /><strong>#lifestyle</strong>" | ||
}, | ||
{ | ||
"id": 2, | ||
"userId": 1, | ||
"imageUrl": "https://images.unsplash.com/photo-1503919545889-aef636e10ad4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=687&q=80", | ||
"text": "Going to the forest 🌳🦌 with my little homie 👧🏻" | ||
}, | ||
{ | ||
"id": 10, | ||
"userId": 2, | ||
"imageUrl": "https://images.unsplash.com/photo-1586348943529-beaae6c28db9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=512&q=80", | ||
"text": "I was missing a bit of this. Holidays, finally!" | ||
} | ||
] | ||
} |
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,34 @@ | ||
# 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 | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# vercel | ||
.vercel |
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 @@ | ||
# Next.js + Tailwind CSS Example | ||
|
||
This example shows how to use [Tailwind CSS](https://tailwindcss.com/) [(v2.2)](https://blog.tailwindcss.com/tailwindcss-2-2) with Next.js. It follows the steps outlined in the official [Tailwind docs](https://tailwindcss.com/docs/guides/nextjs). | ||
|
||
It uses the new [`Just-in-Time Mode`](https://tailwindcss.com/docs/just-in-time-mode) for Tailwind CSS. | ||
|
||
## Preview | ||
|
||
Preview the example live on [StackBlitz](http://stackblitz.com/): | ||
|
||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-tailwindcss) | ||
|
||
## Deploy your own | ||
|
||
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): | ||
|
||
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-tailwindcss&project-name=with-tailwindcss&repository-name=with-tailwindcss) | ||
|
||
## How to use | ||
|
||
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: | ||
|
||
```bash | ||
npx create-next-app --example with-tailwindcss with-tailwindcss-app | ||
# or | ||
yarn create next-app --example with-tailwindcss with-tailwindcss-app | ||
``` | ||
|
||
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). |
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,9 @@ | ||
export default function Avatar({ imageUrl, name, className='' }) { | ||
return ( | ||
<img | ||
className={`inline-block h-10 w-10 rounded-full ${className}`} | ||
src={imageUrl} | ||
alt={name} | ||
/> | ||
) | ||
} |
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,37 @@ | ||
import { MailIcon } from '@heroicons/react/solid' | ||
import classNames from 'classnames' | ||
|
||
export default function Header({profile}) { | ||
return ( | ||
<div> | ||
<div> | ||
<img className="h-32 w-full object-cover lg:h-48" src={profile.coverImageUrl} alt="" /> | ||
</div> | ||
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:pl-8 lg:pr-4"> | ||
<div className="-mt-12 sm:-mt-16 sm:flex sm:items-end sm:space-x-5"> | ||
<div className="flex"> | ||
<img | ||
className="h-24 w-24 rounded-full ring-4 ring-white sm:h-32 sm:w-32" | ||
src={profile.imageUrl} | ||
alt="" | ||
/> | ||
</div> | ||
<div className="mt-6 sm:flex-1 sm:min-w-0 sm:flex sm:items-center sm:justify-end sm:space-x-6 sm:pb-1"> | ||
<div className="sm:block mt-6 min-w-0 flex-1"> | ||
<h1 className="text-2xl font-bold text-gray-900 truncate">{profile.name}</h1> | ||
</div> | ||
<div className="mt-6 flex flex-col justify-stretch space-y-3 sm:flex-row sm:space-y-0 sm:space-x-4"> | ||
<button | ||
type="button" | ||
className="inline-flex justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500" | ||
> | ||
<MailIcon className="-ml-1 mr-2 h-5 w-5 text-gray-400" aria-hidden="true" /> | ||
<span>Message</span> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
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,59 @@ | ||
import { useContext, useEffect, useState } from 'react' | ||
import { HeartIcon } from '@heroicons/react/outline' | ||
import { HeartIcon as HeartIconSolid } from '@heroicons/react/solid' | ||
import WS from '../helpers/ws' | ||
import UserContext from '../context/user' | ||
import Avatar from './Avatar' | ||
|
||
export default function Post({ post, user }) { | ||
const loggedInUser = useContext(UserContext) | ||
const [liked, setLiked] = useState(!!post.likes.find(l => l.postId === post.id && l.userId === loggedInUser.id)) | ||
const [likeCount, setLikes] = useState(post.likes.filter(l => l.postId === post.id).length) | ||
|
||
const onLike = () => { | ||
if (liked) { | ||
WS.send('dislike', { postId: post.id, userId: loggedInUser.id }) | ||
setLiked(false) | ||
} else { | ||
WS.send('like', { postId: post.id, userId: loggedInUser.id }) | ||
setLiked(true) | ||
} | ||
} | ||
|
||
useEffect(() => { | ||
if (typeof window !== 'undefined') { | ||
WS.listen('likes_count_updated', (data) => { | ||
if (data.postId === post.id) { | ||
setLikes(data.totalCount) | ||
} | ||
}) | ||
} | ||
}, []) | ||
|
||
return ( | ||
<div className="mb-16"> | ||
<div className="mb-4"> | ||
<Avatar imageUrl={user.imageUrl} name={user.name} className="mr-4" /> | ||
<strong>{user.name}</strong> | ||
</div> | ||
<p className="text-gray-700 my-2" dangerouslySetInnerHTML={{__html: post.text}} /> | ||
<img className="w-full object-cover max-h-96" src={post.imageUrl} alt="" /> | ||
<div className="mt-2"> | ||
<button | ||
type="button" | ||
className={`inline-flex items-center px-3 py-2 text-md font-medium ${liked ? 'text-red-600' : 'text-gray-700'} bg-white hover:text-red-600 focus:outline-none`} | ||
onClick={onLike} | ||
> | ||
{ | ||
liked ? ( | ||
<HeartIconSolid className="-ml-0.5 mr-2 h-4 w-4" aria-hidden="true" /> | ||
) : ( | ||
<HeartIcon className="-ml-0.5 mr-2 h-4 w-4" aria-hidden="true" /> | ||
) | ||
} | ||
{likeCount} | ||
</button> | ||
</div> | ||
</div> | ||
) | ||
} |
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,3 @@ | ||
import { createContext } from 'react' | ||
|
||
export default createContext() |
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,34 @@ | ||
export default class WS { | ||
static ws | ||
static listeners = {} | ||
|
||
static init() { | ||
this.ws = new WebSocket('ws://localhost:3001/') | ||
|
||
this.ws.addEventListener('open', () => { | ||
console.log('WS client connected to server!') | ||
}) | ||
|
||
this.ws.addEventListener('message', (event) => { | ||
try { | ||
const json = JSON.parse(event.data) | ||
console.log(json) | ||
if (this.listeners[json.type]) { | ||
this.listeners[json.type].forEach(listener => listener(json.data)) | ||
} | ||
} catch (e) { | ||
console.error('Unable to decode the WebSocket message:') | ||
console.error(e) | ||
} | ||
}) | ||
} | ||
|
||
static listen(eventName, fn) { | ||
this.listeners[eventName] = this.listeners[eventName] || [] | ||
this.listeners[eventName].push(fn) | ||
} | ||
|
||
static send(eventName, payload) { | ||
this.ws.send(JSON.stringify({ type: eventName, data: payload })) | ||
} | ||
} |
Oops, something went wrong.