Skip to content

Commit

Permalink
improve example apps & update db doc (#1501)
Browse files Browse the repository at this point in the history
* add websockets example app

* make names more descriptive

* Update backends.md

* Update backends.md

* Update README.md

* fix naming post title

* Update web/docs/data-model/backends.md

Co-authored-by: Mihovil Ilakovac <[email protected]>

---------

Co-authored-by: Mihovil Ilakovac <[email protected]>
  • Loading branch information
vincanger and infomiho authored Oct 16, 2023
1 parent 5ddd407 commit 04d2d8b
Show file tree
Hide file tree
Showing 169 changed files with 523 additions and 6 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ app hackathonBetaSubmissions {
}

entity Submission {=psl
name String @id @unique
name String @id @unique
email String @unique
github String
description String
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
55 changes: 55 additions & 0 deletions examples/todo-app-in-typescript/src/client/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// =============================== IMPORTANT =================================
//
// This file is only used for Wasp IDE support. You can change it to configure
// your IDE checks, but none of these options will affect the TypeScript
// compiler. Proper TS compiler configuration in Wasp is coming soon :)
{
"compilerOptions": {
// JSX support
"jsx": "preserve",
"strict": true,
// Allow default imports.
"esModuleInterop": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
// Wasp needs the following settings enable IDE support in your source
// files. Editing them might break features like import autocompletion and
// definition lookup. Don't change them unless you know what you're doing.
//
// The relative path to the generated web app's root directory. This must be
// set to define the "paths" option.
"baseUrl": "../../../todo-app-in-typescript/.wasp/out/web-app",
"paths": {
// Resolve all "@wasp" imports to the generated source code.
"@wasp/*": [
"../../../todo-app-in-typescript/src/client/src/*"
],
// Resolve all non-relative imports to the correct node module. Source:
// https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
"*": [
// Start by looking for the definiton inside the node modules root
// directory...
"../../../todo-app-in-typescript/src/client/node_modules/*",
// ... If that fails, try to find it inside definitely-typed type
// definitions.
"../../../todo-app-in-typescript/src/client/node_modules/@types/*"
]
},
// Correctly resolve types: https://www.typescriptlang.org/tsconfig#typeRoots
"typeRoots": [
"../../../todo-app-in-typescript/.wasp/out/web-app/node_modules/@types"
],
// Since this TS config is used only for IDE support and not for
// compilation, the following directory doesn't exist. We need to specify
// it to prevent this error:
// https://stackoverflow.com/questions/42609768/typescript-error-cannot-write-file-because-it-would-overwrite-input-file
"outDir": "../../../todo-app-in-typescript/src/client/phantom"
},
"exclude": [
"../../../todo-app-in-typescript/src/client/phantom"
],
}
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions examples/websockets-realtime-voting/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/.wasp/
/.env.server
/.env.client
.DS_Store
1 change: 1 addition & 0 deletions examples/websockets-realtime-voting/.wasproot
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
File marking the root of Wasp project.
45 changes: 45 additions & 0 deletions examples/websockets-realtime-voting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Using Websockets in Wasp

This is an example real-time, Websockets app built with Wasp in TypeScript to showcase the ease of use and integration of Websockets in Wasp. It's really NEAT!

[![wasp websockets app](image.png)](https://www.youtube.com/watch?v=Twy-2P0Co6M)

You can try out a deployed version of the app here: https://websockets-client-production.up.railway.app/

This app also includes Wasp's integrated auth and a voting system (again, neat!).

## Running the app

*If you get stuck at any point, feel free to join our [Discord server](https://discord.gg/rzdnErX) and ask questions there. We are happy to help!*

First, clone the this repo:
```bash
git clone https://github.com/wasp-lang/wasp.git
```

Make sure you've downloaded and installed Wasp
```bash
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
```

Then navigate to the project directory
```bash
cd examples/websockets-realtime-voting
```

```bash
wasp db migrate-dev
```

start the app! (this also installs all dependencies)
```bash
wasp start
```

Check out the `src/server/websocket.ts` and `src/client/pages/MainPage.tsx` to see how Websockets are used in Wasp.

## Need Help?

Wasp Docs: https://wasp-lang.dev/docs

Feel free to join our [Discord server](https://discord.gg/rzdnErX) and ask questions there. We are happy to help!
Binary file added examples/websockets-realtime-voting/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions examples/websockets-realtime-voting/main.wasp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
app whereDoWeEat {
wasp: {
version: "^0.11.6"
},
title: "where-do-we-eat",
client: {
rootComponent: import { Layout } from "@client/Layout.jsx",
},
auth: {
userEntity: User,
onAuthFailedRedirectTo: "/login",
methods: {
usernameAndPassword: {}
}
},
dependencies: [
("flowbite", "1.6.6"),
("flowbite-react", "0.4.9")
],
webSocket: {
fn: import { webSocketFn } from "@server/ws-server.js",
}
}

entity User {=psl
id Int @id @default(autoincrement())
username String @unique
password String
psl=}

route RootRoute { path: "/", to: MainPage }
page MainPage {
component: import Main from "@client/MainPage.tsx",
authRequired: true
}

route LoginRoute { path: "/login", to: LoginPage }
page LoginPage {
component: import { LoginPage } from "@client/pages/LoginPage.jsx"
}

route RegisterRoute { path: "/signup", to: RegisterPage }
page RegisterPage {
component: import { SignupPage } from "@client/pages/SignupPage.jsx"
}
6 changes: 6 additions & 0 deletions examples/websockets-realtime-voting/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
3 changes: 3 additions & 0 deletions examples/websockets-realtime-voting/src/.waspignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore editor tmp files
**/*~
**/#*#
71 changes: 71 additions & 0 deletions examples/websockets-realtime-voting/src/client/Layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// @ts-check
import "./Main.css";

import { Flowbite, Dropdown, Navbar, Avatar } from "flowbite-react";
import Logo from "./logo.png";
import useAuth from "@wasp/auth/useAuth";
import logout from "@wasp/auth/logout";

const customTheme = {
button: {
color: {
primary: "bg-red-500 hover:bg-red-600",
},
},
};

export const Layout = ({ children }) => {
const { data: user } = useAuth();
return (
<Flowbite theme={{ theme: customTheme }}>
<div className="p-8">
<Navbar fluid rounded>
<Navbar.Brand href="https://flowbite-react.com">
<img
alt="Flowbite React Logo"
className="mr-3 h-6 sm:h-9"
src={Logo}
/>
<span className="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
Undecisive Fox App
</span>
</Navbar.Brand>
{user && (
<div className="flex md:order-2">
<Dropdown
inline
label={
<Avatar
alt="User settings"
img={`https://xsgames.co/randomusers/avatar.php?g=female&username=${user.username}`}
rounded
/>
}
>
<Dropdown.Header>
<span className="block text-sm">{user.username}</span>
</Dropdown.Header>
<Dropdown.Item>Dashboard</Dropdown.Item>
<Dropdown.Item>Settings</Dropdown.Item>
<Dropdown.Item>Earnings</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item onClick={logout}>Sign out</Dropdown.Item>
</Dropdown>
<Navbar.Toggle />
</div>
)}
{/* <Navbar.Collapse>
<Navbar.Link active href="#">
<p>Home</p>
</Navbar.Link>
<Navbar.Link href="#">About</Navbar.Link>
<Navbar.Link href="#">Services</Navbar.Link>
<Navbar.Link href="#">Pricing</Navbar.Link>
<Navbar.Link href="#">Contact</Navbar.Link>
</Navbar.Collapse> */}
</Navbar>
<div className="grid place-items-center mt-8">{children}</div>
</div>
</Flowbite>
);
};
3 changes: 3 additions & 0 deletions examples/websockets-realtime-voting/src/client/Main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
94 changes: 94 additions & 0 deletions examples/websockets-realtime-voting/src/client/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useState, useMemo, useEffect } from "react";
import { Button, Card } from "flowbite-react";
import {
useSocketListener,
useSocket,
ServerToClientPayload,
} from "@wasp/webSocket";
import useAuth from "@wasp/auth/useAuth";

const MainPage = () => {
const { data: user } = useAuth();
const [poll, setPoll] = useState<ServerToClientPayload<"updateState"> | null>(
null
);
const totalVotes = useMemo(() => {
return (
poll?.options.reduce((acc, option) => acc + option.votes.length, 0) ?? 0
);
}, [poll]);

const { socket } = useSocket();

useSocketListener("updateState", (newState) => {
setPoll(newState);
});

useEffect(() => {
socket.emit("askForStateUpdate");
}, []);

function handleVote(optionId: number) {
socket.emit("vote", optionId);
}

return (
<div className="w-full max-w-2xl mx-auto p-8">
<h1 className="text-2xl font-bold">{poll?.question ?? "Loading..."}</h1>
{poll && (
<p className="leading-relaxed text-gray-500">
Cast your vote for one of the options.
</p>
)}
{poll && (
<div className="mt-4 flex flex-col gap-4">
{poll.options.map((option) => (
<Card key={option.id} className="relative transition-all duration-300 min-h-[130px]">
<div className="z-10">
<div className="mb-2">
<h2 className="text-xl font-semibold">{option.text}</h2>
<p className="text-gray-700">{option.description}</p>
</div>
<div className="absolute bottom-5 right-5">
{user && !option.votes.includes(user.username) ? (
<Button onClick={() => handleVote(option.id)}>Vote</Button>
) : (
<Button disabled>Voted</Button>
)}
{!user}
</div>
{option.votes.length > 0 && (
<div className="mt-2 flex gap-2 flex-wrap max-w-[75%]">
{option.votes.map((vote) => (
<div
key={vote}
className="py-1 px-3 bg-gray-100 rounded-lg flex items-center justify-center shadow text-sm"
>
<div className="w-2 h-2 bg-green-500 rounded-full mr-2"></div>
<div className="text-gray-700">{vote}</div>
</div>
))}
</div>
)}
</div>
<div className="absolute top-5 right-5 p-2 text-sm font-semibold bg-gray-100 rounded-lg z-10">
{option.votes.length} / {totalVotes}
</div>
<div
className="absolute inset-0 bg-gradient-to-r from-yellow-400 to-orange-500 opacity-75 rounded-lg transition-all duration-300"
style={{
width: `${
totalVotes > 0
? (option.votes.length / totalVotes) * 100
: 0
}%`,
}}
></div>
</Card>
))}
</div>
)}
</div>
);
};
export default MainPage;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions examples/websockets-realtime-voting/src/client/pages/LoginPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { LoginForm } from "@wasp/auth/forms/Login";
import { Link } from "react-router-dom";

export function LoginPage() {
return (
<div>
<LoginForm />
<div className="text-center mt-4">
<Link to="/signup">Sign up instead</Link>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SignupForm } from "@wasp/auth/forms/Signup";

export function SignupPage() {
return <SignupForm />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="../../.wasp/out/web-app/node_modules/vite/client" />
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 04d2d8b

Please sign in to comment.