Compare commits
1 Commits
feature/ru
...
organizati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72999d8832 |
@@ -10,21 +10,19 @@
|
||||
"cojson-storage-indexeddb",
|
||||
"cojson-storage-sqlite",
|
||||
"cojson-transport-ws",
|
||||
"create-jazz-app",
|
||||
"jazz-browser",
|
||||
"jazz-browser-auth-clerk",
|
||||
"jazz-browser-media-images",
|
||||
"jazz-nodejs",
|
||||
"jazz-react",
|
||||
"jazz-react-auth-clerk",
|
||||
"jazz-react-core",
|
||||
"jazz-react-native",
|
||||
"jazz-react-native-auth-clerk",
|
||||
"jazz-react-native-media-images",
|
||||
"jazz-run",
|
||||
"jazz-svelte",
|
||||
"jazz-tools",
|
||||
"jazz-vue",
|
||||
"jazz-worker"
|
||||
"jazz-vue"
|
||||
]
|
||||
],
|
||||
"access": "public",
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"jazz-tools": patch
|
||||
---
|
||||
|
||||
Return field name on \_edits
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"jazz-tools": patch
|
||||
---
|
||||
|
||||
Simplify the .create calls by accepting directly "Account | Group" as second param
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"cojson": patch
|
||||
---
|
||||
|
||||
Add a crypto entry to optionally import the crypto modules
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"jazz-react": minor
|
||||
"jazz-svelte": minor
|
||||
---
|
||||
|
||||
Change the way the JazzProvider is created and make the hooks available as top-level imports.
|
||||
|
||||
This is a breaking change.
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
"jazz-worker": minor
|
||||
---
|
||||
|
||||
- Renamed `jazz-nodejs` to `jazz-worker`
|
||||
- Dropped support for Node.js versions before v22
|
||||
- Added support for all the runtimes that support WASM and WebSocket clients
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"jazz-tools": patch
|
||||
---
|
||||
|
||||
Optimize the subscribe to resolve the CoValues stored in memory synchronously
|
||||
5
.changeset/warm-bananas-tie.md
Normal file
5
.changeset/warm-bananas-tie.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"jazz-tools": patch
|
||||
---
|
||||
|
||||
Remove the requirement of calling super.migrate when defining the account migration
|
||||
@@ -1,31 +1,5 @@
|
||||
# jazz-example-book-shelf
|
||||
|
||||
## 0.1.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-browser-media-images@0.8.50
|
||||
|
||||
## 0.1.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-browser-media-images@0.8.49
|
||||
|
||||
## 0.1.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-browser-media-images@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.1.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -38,4 +38,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
||||
|
||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/components/JazzAndAuth.tsx](./src/components/JazzAndAuth.tsx).
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/components/JazzAndAuth.tsx](./src/components/JazzAndAuth.tsx).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-example-book-shelf",
|
||||
"version": "0.1.38",
|
||||
"version": "0.1.35",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -11,9 +11,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-browser-media-images": "workspace:0.8.50",
|
||||
"jazz-react": "workspace:0.8.50",
|
||||
"jazz-tools": "workspace:0.8.50",
|
||||
"jazz-browser-media-images": "workspace:0.8.45",
|
||||
"jazz-react": "workspace:0.8.45",
|
||||
"jazz-tools": "workspace:0.8.45",
|
||||
"next": "14.2.5",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
import { Button } from "@/components/Button";
|
||||
import { Container } from "@/components/Container";
|
||||
import { useAccount } from "@/components/JazzAndAuth";
|
||||
import RatingInput from "@/components/RatingInput";
|
||||
import { BookReview, ListOfBookReviews } from "@/schema";
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { Group, ImageDefinition } from "jazz-tools";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import { BookCover } from "@/components/BookCover";
|
||||
import { Container } from "@/components/Container";
|
||||
import { useCoState } from "@/components/JazzAndAuth";
|
||||
import Rating from "@/components/Rating";
|
||||
import RatingInput from "@/components/RatingInput";
|
||||
import { BookReview } from "@/schema";
|
||||
import clsx from "clsx";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
|
||||
const BookReviewTitle = ({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { Container } from "@/components/Container";
|
||||
import { useAccount } from "@/components/JazzAndAuth";
|
||||
import UserProfile from "@/components/UserProfile";
|
||||
import { JazzAccount } from "@/schema";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
|
||||
export default function Home() {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Button } from "@/components/Button";
|
||||
import { useAccount } from "@/components/JazzAndAuth";
|
||||
import PlusIcon from "@/components/icons/PlusIcon";
|
||||
import { BookReview } from "@/schema";
|
||||
import clsx from "clsx";
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { ProgressiveImg } from "jazz-react";
|
||||
import { ChangeEvent, useRef } from "react";
|
||||
import { Group, ImageDefinition } from "jazz-tools";
|
||||
import { ChangeEvent, useRef, useState } from "react";
|
||||
|
||||
const BookCoverContainer = ({
|
||||
children,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { BookCoverReadOnly } from "@/components/BookCover";
|
||||
import { BookCover, BookCoverReadOnly } from "@/components/BookCover";
|
||||
import { useCoState } from "@/components/JazzAndAuth";
|
||||
import StarIcon from "@/components/icons/StarIcon";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import Link from "next/link";
|
||||
import { BookReview } from "../schema";
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { JazzAccount } from "@/schema";
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
|
||||
const Jazz = createJazzReactApp({
|
||||
AccountSchema: JazzAccount,
|
||||
});
|
||||
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
export function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, authState] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<>
|
||||
<JazzProvider
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
AccountSchema={JazzAccount}
|
||||
// replace `you@example.com` with your email as a temporary API key
|
||||
peer="wss://cloud.jazz.tools/?key=you@example.com"
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
{authState.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Jazz Book Shelf" state={authState} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: JazzAccount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { Button } from "@/components/Button";
|
||||
import { Container } from "@/components/Container";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { useAccount } from "@/components/JazzAndAuth";
|
||||
import Link from "next/link";
|
||||
|
||||
export function Nav() {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import { BookReviewThumbnail } from "@/components/BookReviewThumbnail";
|
||||
import { Button } from "@/components/Button";
|
||||
import { useCoState } from "@/components/JazzAndAuth";
|
||||
import { JazzAccount, JazzProfile, ListOfBookReviews } from "@/schema";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
|
||||
export default function UserProfile({ id }: { id: ID<JazzAccount> }) {
|
||||
|
||||
@@ -1,34 +1,5 @@
|
||||
# chat-rn-clerk
|
||||
|
||||
## 1.0.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react-native@0.8.50
|
||||
- jazz-react-native-auth-clerk@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-react-native-media-images@0.8.50
|
||||
|
||||
## 1.0.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react-native@0.8.49
|
||||
- jazz-react-native-auth-clerk@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-react-native-media-images@0.8.49
|
||||
|
||||
## 1.0.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-react-native@0.8.48
|
||||
- jazz-react-native-auth-clerk@0.8.48
|
||||
- jazz-react-native-media-images@0.8.48
|
||||
|
||||
## 1.0.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.40",
|
||||
"version": "1.0.37",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,28 +1,5 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react-native@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
|
||||
## 1.0.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react-native@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
|
||||
## 1.0.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-react-native@0.8.48
|
||||
|
||||
## 1.0.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.37",
|
||||
"version": "1.0.34",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
# chat-vue
|
||||
|
||||
## 0.0.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-vue@0.8.50
|
||||
|
||||
## 0.0.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-vue@0.8.49
|
||||
|
||||
## 0.0.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-browser@0.8.48
|
||||
- jazz-vue@0.8.48
|
||||
|
||||
## 0.0.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.29",
|
||||
"version": "0.0.26",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.124
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-browser-media-images@0.8.50
|
||||
|
||||
## 0.0.123
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-browser-media-images@0.8.49
|
||||
|
||||
## 0.0.122
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-browser-media-images@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.0.121
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -34,4 +34,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
||||
|
||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.124",
|
||||
"version": "0.0.121",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { inIframe, onChatLoad } from "@/util.ts";
|
||||
import { useIframeHashRouter } from "hash-slash";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { ChatScreen } from "./chatScreen.tsx";
|
||||
import { JazzAndAuth } from "./jazz.tsx";
|
||||
import { useAccount } from "./main.tsx";
|
||||
import { Chat } from "./schema.ts";
|
||||
import { ThemeProvider } from "./themeProvider.tsx";
|
||||
import { AppContainer, TopBar } from "./ui.tsx";
|
||||
|
||||
export function App() {
|
||||
@@ -38,13 +34,3 @@ export function App() {
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<ThemeProvider>
|
||||
<StrictMode>
|
||||
<JazzAndAuth>
|
||||
<App />
|
||||
</JazzAndAuth>
|
||||
</StrictMode>
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useState } from "react";
|
||||
import { useAccount, useCoState } from "./main.tsx";
|
||||
import { Chat, Message } from "./schema.ts";
|
||||
import {
|
||||
BubbleBody,
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
|
||||
export function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<>
|
||||
<JazzProvider
|
||||
auth={auth}
|
||||
peer="wss://cloud.jazz.tools/?key=chat-example-jazz@garden.co"
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
{state.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Jazz Chat" state={state} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
36
examples/chat/src/main.tsx
Normal file
36
examples/chat/src/main.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { ThemeProvider } from "@/themeProvider.tsx";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { App } from "./app.tsx";
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://cloud.jazz.tools/?key=chat-example-jazz@garden.co"
|
||||
>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
{state.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Jazz Chat" state={state} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<ThemeProvider>
|
||||
<StrictMode>
|
||||
<JazzAndAuth>
|
||||
<App />
|
||||
</JazzAndAuth>
|
||||
</StrictMode>
|
||||
</ThemeProvider>,
|
||||
);
|
||||
@@ -1,31 +1,5 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 0.0.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-react-auth-clerk@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
|
||||
## 0.0.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-react-auth-clerk@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
|
||||
## 0.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
- jazz-react-auth-clerk@0.8.48
|
||||
|
||||
## 0.0.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.23",
|
||||
"version": "0.0.20",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@clerk/clerk-react": "^5.4.1",
|
||||
"jazz-react": "workspace:*",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.50",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.45",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { useAccount } from "./main";
|
||||
|
||||
function App() {
|
||||
const { me, logOut } = useAccount();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ClerkProvider, SignInButton, useClerk } from "@clerk/clerk-react";
|
||||
import { createJazzReactApp } from "jazz-react";
|
||||
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
import { JazzProvider } from "jazz-react";
|
||||
|
||||
// Import your publishable key
|
||||
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
|
||||
@@ -13,6 +13,9 @@ if (!PUBLISHABLE_KEY) {
|
||||
throw new Error("Add your Clerk publishable key to the .env.local file");
|
||||
}
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const clerk = useClerk();
|
||||
const [auth, state] = useJazzClerkAuth(clerk);
|
||||
@@ -23,12 +26,12 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
<div key={error}>{error}</div>
|
||||
))}
|
||||
{clerk.user && auth ? (
|
||||
<JazzProvider
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://cloud.jazz.tools/?key=minimal-auth-clerk-example@garden.co"
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
) : (
|
||||
<SignInButton />
|
||||
)}
|
||||
|
||||
@@ -1,28 +1,5 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-svelte@0.8.50
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-svelte@0.8.49
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-svelte@0.8.48
|
||||
|
||||
## 0.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.6",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { SharedFile } from '$lib/schema';
|
||||
import { FileStream } from 'jazz-tools';
|
||||
import { File, FileDown, Trash2, Link2 } from 'lucide-svelte';
|
||||
import { useAccount } from 'jazz-svelte';
|
||||
import { useAccount } from '$lib/jazz';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { formatFileSize } from '$lib/utils';
|
||||
|
||||
|
||||
7
examples/file-share-svelte/src/lib/jazz.ts
Normal file
7
examples/file-share-svelte/src/lib/jazz.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createJazzApp } from 'jazz-svelte';
|
||||
import { FileShareAccount } from './schema';
|
||||
|
||||
export const { useAccount, useCoState, useAcceptInvite, useAccountOrGuest, Provider } =
|
||||
createJazzApp({
|
||||
AccountSchema: FileShareAccount
|
||||
});
|
||||
@@ -1,17 +1,8 @@
|
||||
<script lang="ts" module>
|
||||
declare module 'jazz-svelte' {
|
||||
interface Register {
|
||||
Account: FileShareAccount;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { JazzProvider } from 'jazz-svelte';
|
||||
import { Provider } from '$lib/jazz';
|
||||
import { PasskeyAuthBasicUI, usePasskeyAuth } from 'jazz-svelte';
|
||||
import { Toaster } from 'svelte-sonner';
|
||||
import '../app.css';
|
||||
import { FileShareAccount } from '$lib/schema';
|
||||
|
||||
let { children } = $props();
|
||||
const auth = usePasskeyAuth({
|
||||
@@ -33,13 +24,9 @@
|
||||
</div>
|
||||
{/if}
|
||||
{#if auth.current}
|
||||
<JazzProvider
|
||||
AccountSchema={FileShareAccount}
|
||||
auth={auth.current}
|
||||
peer="wss://cloud.jazz.tools/?key=file-share-svelte@garden.co"
|
||||
>
|
||||
<Provider auth={auth.current} peer="wss://cloud.jazz.tools/?key=file-share-svelte@garden.co">
|
||||
<div class="min-h-screen bg-gray-100">
|
||||
{@render children()}
|
||||
</div>
|
||||
</JazzProvider>
|
||||
</Provider>
|
||||
{/if}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { useAccount, useCoState } from 'jazz-svelte';
|
||||
import { useAccount, useCoState } from '$lib/jazz';
|
||||
import { SharedFile, ListOfSharedFiles } from '$lib/schema';
|
||||
import { createInviteLink } from 'jazz-svelte';
|
||||
import { FileStream } from 'jazz-tools';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { useAccount, useCoState } from 'jazz-svelte';
|
||||
import { useAccount, useCoState } from '$lib/jazz';
|
||||
import { SharedFile } from '$lib/schema';
|
||||
import { File, FileDown, Link2 } from 'lucide-svelte';
|
||||
import type { ID } from 'jazz-tools';
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
# form
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-browser-media-images@0.8.50
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-browser-media-images@0.8.49
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-browser-media-images@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.0.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -15,8 +15,6 @@ which has the same structure as `BubbleTeaOrder`, but with all fields set to `op
|
||||
When the user is ready to submit the order, we treat `DraftBubbleTeaOrder` as a "real order" by
|
||||
converting it into a `BubbleTeaOrder`.
|
||||
|
||||
[See the full guide here.](https://jazz.tools/docs/react/design-patterns/form)
|
||||
|
||||
## Installing & running the example locally
|
||||
|
||||
(This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
|
||||
@@ -49,4 +47,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
||||
|
||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.0.19",
|
||||
"version": "0.0.16",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useIframeHashRouter } from "hash-slash";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { CreateOrder } from "./CreateOrder.tsx";
|
||||
import { EditOrder } from "./EditOrder.tsx";
|
||||
import { Orders } from "./Orders.tsx";
|
||||
import { useAccount } from "./main";
|
||||
import { BubbleTeaOrder } from "./schema.ts";
|
||||
|
||||
function App() {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useIframeHashRouter } from "hash-slash";
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useState } from "react";
|
||||
import { Errors } from "./Errors.tsx";
|
||||
import { LinkToHome } from "./LinkToHome.tsx";
|
||||
import { OrderForm } from "./OrderForm.tsx";
|
||||
import { useAccount, useCoState } from "./main.tsx";
|
||||
import {
|
||||
BubbleTeaOrder,
|
||||
DraftBubbleTeaOrder,
|
||||
@@ -32,9 +32,9 @@ export function CreateOrder() {
|
||||
// reset the draft
|
||||
me.root.draft = DraftBubbleTeaOrder.create(
|
||||
{
|
||||
addOns: ListOfBubbleTeaAddOns.create([], me),
|
||||
addOns: ListOfBubbleTeaAddOns.create([], { owner: me }),
|
||||
},
|
||||
me,
|
||||
{ owner: me },
|
||||
);
|
||||
|
||||
router.navigate("/");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { useAccount } from "./main.tsx";
|
||||
|
||||
export function DraftIndicator() {
|
||||
const { me } = useAccount({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { LinkToHome } from "./LinkToHome.tsx";
|
||||
import { OrderForm } from "./OrderForm.tsx";
|
||||
import { OrderThumbnail } from "./OrderThumbnail.tsx";
|
||||
import { useCoState } from "./main.tsx";
|
||||
import { BubbleTeaOrder } from "./schema.ts";
|
||||
|
||||
export function EditOrder(props: { id: ID<BubbleTeaOrder> }) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { DraftIndicator } from "./DraftIndicator.tsx";
|
||||
import { OrderThumbnail } from "./OrderThumbnail.tsx";
|
||||
import { useAccount } from "./main.tsx";
|
||||
|
||||
export function Orders() {
|
||||
const { me } = useAccount({
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
import { JazzAccount } from "./schema.ts";
|
||||
|
||||
const Jazz = createJazzReactApp({
|
||||
AccountSchema: JazzAccount,
|
||||
});
|
||||
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, authState] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<>
|
||||
<JazzProvider
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://cloud.jazz.tools/?key=form-example@garden.co"
|
||||
AccountSchema={JazzAccount}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
|
||||
{authState.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Form" state={authState} />
|
||||
@@ -25,12 +30,6 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: JazzAccount;
|
||||
}
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<JazzAndAuth>
|
||||
|
||||
@@ -69,19 +69,18 @@ export class AccountRoot extends CoMap {
|
||||
export class JazzAccount extends Account {
|
||||
root = co.ref(AccountRoot);
|
||||
|
||||
migrate() {
|
||||
const account = this;
|
||||
|
||||
migrate(this: JazzAccount) {
|
||||
if (!this._refs.root) {
|
||||
const orders = ListOfBubbleTeaOrders.create([], account);
|
||||
const ownership = { owner: this };
|
||||
const orders = ListOfBubbleTeaOrders.create([], ownership);
|
||||
const draft = DraftBubbleTeaOrder.create(
|
||||
{
|
||||
addOns: ListOfBubbleTeaAddOns.create([], account),
|
||||
addOns: ListOfBubbleTeaAddOns.create([], ownership),
|
||||
},
|
||||
account,
|
||||
ownership,
|
||||
);
|
||||
|
||||
this.root = AccountRoot.create({ draft, orders }, account);
|
||||
this.root = AccountRoot.create({ draft, orders }, ownership);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-browser-media-images@0.8.50
|
||||
|
||||
## 0.0.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-browser-media-images@0.8.49
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-browser-media-images@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.21",
|
||||
"version": "0.0.18",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import ImageUpload from "./ImageUpload.tsx";
|
||||
import { useAccount } from "./main";
|
||||
|
||||
function App() {
|
||||
const { me, logOut } = useAccount();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { ProgressiveImg, useAccount } from "jazz-react";
|
||||
import { ProgressiveImg } from "jazz-react";
|
||||
import { ImageDefinition } from "jazz-tools";
|
||||
import { ChangeEvent, useRef } from "react";
|
||||
import { useAccount } from "./main.tsx";
|
||||
|
||||
function Image({ image }: { image: ImageDefinition }) {
|
||||
return (
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
import { JazzAccount } from "./schema.ts";
|
||||
|
||||
const Jazz = createJazzReactApp({
|
||||
AccountSchema: JazzAccount,
|
||||
});
|
||||
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, authState] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<>
|
||||
<JazzProvider
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://cloud.jazz.tools/?key=image-upload-example@garden.co"
|
||||
AccountSchema={JazzAccount}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
|
||||
{authState.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Image upload" state={authState} />
|
||||
@@ -25,12 +30,6 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: JazzAccount;
|
||||
}
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<JazzAndAuth>
|
||||
|
||||
@@ -1,29 +1,5 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [43378ef]
|
||||
- cojson@0.8.50
|
||||
- cojson-transport-ws@0.8.50
|
||||
|
||||
## 0.0.91
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [25dfd90]
|
||||
- cojson@0.8.49
|
||||
- cojson-transport-ws@0.8.49
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [10ea733]
|
||||
- cojson@0.8.48
|
||||
- cojson-transport-ws@0.8.48
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector",
|
||||
"private": true,
|
||||
"version": "0.0.92",
|
||||
"version": "0.0.89",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -16,8 +16,8 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.8.50",
|
||||
"cojson-transport-ws": "workspace:0.8.50",
|
||||
"cojson": "workspace:0.8.45",
|
||||
"cojson-transport-ws": "workspace:0.8.45",
|
||||
"hash-slash": "workspace:0.2.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
||||
@@ -1,28 +1,5 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
|
||||
## 0.0.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
|
||||
## 0.0.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.0.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -34,4 +34,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
||||
|
||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx cojson-simple-sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/2_main.tsx](./src/2_main.tsx).
|
||||
You can also run a local sync server by running `npx cojson-simple-sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/2_main.tsx](./src/2_main.tsx).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.44",
|
||||
"version": "0.0.41",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -18,8 +18,8 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-react": "workspace:0.8.50",
|
||||
"jazz-tools": "workspace:0.8.50",
|
||||
"jazz-react": "workspace:0.8.45",
|
||||
"jazz-tools": "workspace:0.8.45",
|
||||
"lucide-react": "^0.274.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
|
||||
@@ -10,20 +10,26 @@ import { PlayerControls } from "./components/PlayerControls";
|
||||
import "./index.css";
|
||||
|
||||
import { MusicaAccount } from "@/1_schema";
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
import { useUploadExampleData } from "./lib/useUploadExampleData";
|
||||
|
||||
/**
|
||||
* Walkthrough: The top-level provider `<JazzProvider/>`
|
||||
* Walkthrough: The top-level provider `<Jazz.Provider/>`
|
||||
*
|
||||
* This shows how to use the top-level provider `<JazzProvider/>`,
|
||||
* This shows how to use the top-level provider `<Jazz.Provider/>`,
|
||||
* which provides the rest of the app with a controlled account (used through `useAccount` later).
|
||||
* Here we use `DemoAuth` which is great for prototyping you app without wasting time on figuring out
|
||||
* the best way to do auth.
|
||||
*
|
||||
* `<JazzProvider/>` also runs our account migration
|
||||
* `<Jazz.Provider/>` also runs our account migration
|
||||
*/
|
||||
|
||||
const Jazz = createJazzReactApp({
|
||||
AccountSchema: MusicaAccount,
|
||||
});
|
||||
|
||||
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
|
||||
|
||||
function Main() {
|
||||
const mediaPlayer = useMediaPlayer();
|
||||
|
||||
@@ -64,25 +70,18 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<JazzProvider
|
||||
<Jazz.Provider
|
||||
storage={["singleTabOPFS", "indexedDB"]}
|
||||
auth={auth}
|
||||
peer={peer}
|
||||
AccountSchema={MusicaAccount}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
<DemoAuthBasicUI appName="Jazz Music Player" state={state} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: MusicaAccount;
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<JazzAndAuth>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { createInviteLink, useAccount, useCoState } from "jazz-react";
|
||||
import { createInviteLink } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { Playlist } from "./1_schema";
|
||||
import { useAccount, useCoState } from "./2_main";
|
||||
import { createNewPlaylist, uploadMusicTracks } from "./4_actions";
|
||||
import { MediaPlayer } from "./5_useMediaPlayer";
|
||||
import { FileUploadButton } from "./components/FileUploadButton";
|
||||
|
||||
@@ -29,23 +29,25 @@ export async function uploadMusicTracks(
|
||||
for (const file of files) {
|
||||
// The ownership object defines the user that owns the created coValues
|
||||
// We are creating a group for each CoValue in order to be able to share them via Playlist
|
||||
const group = Group.create(account);
|
||||
const ownership = {
|
||||
owner: Group.create({ owner: account }),
|
||||
};
|
||||
|
||||
const data = await getAudioFileData(file);
|
||||
|
||||
// We transform the file blob into a FileStream
|
||||
// making it a collaborative value that is encrypted, easy
|
||||
// to share across devices and users and available offline!
|
||||
const fileStream = await FileStream.createFromBlob(file, group);
|
||||
const fileStream = await FileStream.createFromBlob(file, ownership);
|
||||
|
||||
const musicTrack = MusicTrack.create(
|
||||
{
|
||||
file: fileStream,
|
||||
duration: data.duration,
|
||||
waveform: MusicTrackWaveform.create({ data: data.waveform }, group),
|
||||
waveform: MusicTrackWaveform.create({ data: data.waveform }, ownership),
|
||||
title: file.name,
|
||||
},
|
||||
group,
|
||||
ownership,
|
||||
);
|
||||
|
||||
// The newly created musicTrack can be associated to the
|
||||
@@ -58,14 +60,16 @@ export async function createNewPlaylist(account: MusicaAccount) {
|
||||
// Since playlists are meant to be shared we associate them
|
||||
// to a group which will contain the keys required to get
|
||||
// access to the "owned" values
|
||||
const playlistGroup = Group.create(account);
|
||||
const playlistGroup = Group.create({ owner: account });
|
||||
|
||||
const ownership = { owner: playlistGroup };
|
||||
|
||||
const playlist = Playlist.create(
|
||||
{
|
||||
title: "New Playlist",
|
||||
tracks: ListOfTracks.create([], playlistGroup),
|
||||
tracks: ListOfTracks.create([], ownership),
|
||||
},
|
||||
playlistGroup,
|
||||
ownership,
|
||||
);
|
||||
|
||||
// Again, we associate the new playlist to the
|
||||
@@ -108,6 +112,7 @@ export async function addTrackToPlaylist(
|
||||
*
|
||||
* Doing this for backwards compatibility for when the Group inheritance wasn't possible
|
||||
*/
|
||||
const ownership = { owner: playlist._owner };
|
||||
const blob = await FileStream.loadAsBlob(track._refs.file.id, account);
|
||||
const waveform = await MusicTrackWaveform.load(
|
||||
track._refs.waveform.id,
|
||||
@@ -119,16 +124,13 @@ export async function addTrackToPlaylist(
|
||||
|
||||
const trackClone = MusicTrack.create(
|
||||
{
|
||||
file: await FileStream.createFromBlob(blob, playlist._owner),
|
||||
file: await FileStream.createFromBlob(blob, ownership),
|
||||
duration: track.duration,
|
||||
waveform: MusicTrackWaveform.create(
|
||||
{ data: waveform.data },
|
||||
playlist._owner,
|
||||
),
|
||||
waveform: MusicTrackWaveform.create({ data: waveform.data }, ownership),
|
||||
title: track.title,
|
||||
sourceTrack: track,
|
||||
},
|
||||
playlist._owner,
|
||||
ownership,
|
||||
);
|
||||
|
||||
playlist.tracks?.push(trackClone);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { MusicTrack, Playlist } from "@/1_schema";
|
||||
import { usePlayMedia } from "@/lib/audio/usePlayMedia";
|
||||
import { usePlayState } from "@/lib/audio/usePlayState";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { FileStream, ID } from "jazz-tools";
|
||||
import { useRef, useState } from "react";
|
||||
import { useAccount } from "./2_main";
|
||||
import { updateActivePlaylist, updateActiveTrack } from "./4_actions";
|
||||
import { getNextTrack, getPrevTrack } from "./lib/getters";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useAcceptInvite, useAccount } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useCallback } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Playlist } from "./1_schema";
|
||||
import { useAcceptInvite, useAccount } from "./2_main";
|
||||
|
||||
export function InvitePage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { useAccount } from "@/2_main";
|
||||
import { Button } from "./ui/button";
|
||||
|
||||
export function LogoutButton() {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MusicTrack, Playlist } from "@/1_schema";
|
||||
import { useAccount, useCoState } from "@/2_main";
|
||||
import { addTrackToPlaylist } from "@/4_actions";
|
||||
import {
|
||||
DropdownMenu,
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { MoreHorizontal } from "lucide-react";
|
||||
import { MusicTrackTitleInput } from "./MusicTrackTitleInput";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MusicTrack } from "@/1_schema";
|
||||
import { useCoState } from "@/2_main";
|
||||
import { updateMusicTrackTitle } from "@/4_actions";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { MusicTrack } from "@/1_schema";
|
||||
import { useAccount, useCoState } from "@/2_main";
|
||||
import { MediaPlayer } from "@/5_useMediaPlayer";
|
||||
import { useMediaEndListener } from "@/lib/audio/useMediaEndListener";
|
||||
import { usePlayState } from "@/lib/audio/usePlayState";
|
||||
import { useKeyboardListener } from "@/lib/useKeyboardListener";
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { Pause, Play, SkipBack, SkipForward } from "lucide-react";
|
||||
import { Waveform } from "./Waveform";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Playlist } from "@/1_schema";
|
||||
import { useCoState } from "@/2_main";
|
||||
import { updatePlaylistTitle } from "@/4_actions";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { useAccount } from "@/2_main";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
|
||||
export function SidePanel() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MusicTrack, MusicTrackWaveform } from "@/1_schema";
|
||||
import { useCoState } from "@/2_main";
|
||||
import { usePlayerCurrentTime } from "@/lib/audio/usePlayerCurrentTime";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useCoState } from "jazz-react";
|
||||
|
||||
export function Waveform(props: { track: MusicTrack; height: number }) {
|
||||
const { track, height } = props;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
// eslint-disable-next-line react-compiler/react-compiler
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect } from "react";
|
||||
import { MusicaAccount } from "../1_schema";
|
||||
import { useAccount } from "../2_main";
|
||||
import { uploadMusicTracks } from "../4_actions";
|
||||
|
||||
export function useUploadExampleData() {
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
# jazz-example-onboarding
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
- jazz-browser-media-images@0.8.50
|
||||
|
||||
## 0.0.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
- jazz-browser-media-images@0.8.49
|
||||
|
||||
## 0.0.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-browser-media-images@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.0.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -32,4 +32,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
||||
|
||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx cojson-simple-sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
You can also run a local sync server by running `npx cojson-simple-sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-onboarding",
|
||||
"private": true,
|
||||
"version": "0.0.25",
|
||||
"version": "0.0.22",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Button } from "@/components/Button.tsx";
|
||||
import { useAcceptInvite, useAccount, useCoState } from "@/main.tsx";
|
||||
import { EmployeeList } from "@/pages/EmployeeList.tsx";
|
||||
import { EmployeeOnboading } from "@/pages/EmployeeOnboarding.tsx";
|
||||
import { NewEmployee } from "@/pages/NewEmployee.tsx";
|
||||
import { CoEmployee, EmployeeCoList } from "@/schema.ts";
|
||||
import { useAcceptInvite, useAccount, useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import App from "@/App.tsx";
|
||||
import "@/index.css";
|
||||
import { HRAccount } from "@/schema.ts";
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
|
||||
const Jazz = createJazzReactApp({
|
||||
AccountSchema: HRAccount,
|
||||
});
|
||||
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
|
||||
|
||||
const peer =
|
||||
(new URL(window.location.href).searchParams.get(
|
||||
"peer",
|
||||
@@ -15,9 +20,9 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, authState] = useDemoAuth();
|
||||
return (
|
||||
<>
|
||||
<JazzProvider AccountSchema={HRAccount} auth={auth} peer={peer}>
|
||||
<Jazz.Provider auth={auth} peer={peer}>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
{authState.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Jazz Onboarding" state={authState} />
|
||||
)}
|
||||
@@ -25,12 +30,6 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: HRAccount;
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<JazzAndAuth>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { NavLink } from "@/components/NavLink.tsx";
|
||||
import { NavigateButton } from "@/components/NavigateBack.tsx";
|
||||
import { Stack } from "@/components/Stack.tsx";
|
||||
import { useCoState } from "@/main.tsx";
|
||||
import { CoEmployee, EmployeeCoList } from "@/schema.ts";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
|
||||
export function EmployeeList({
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Button } from "@/components/Button.tsx";
|
||||
import { NavigateBack } from "@/components/NavigateBack.tsx";
|
||||
import { Stack } from "@/components/Stack.tsx";
|
||||
import { TextInput } from "@/components/TextInput.tsx";
|
||||
import { useCoState } from "@/main.tsx";
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ProgressiveImg, createInviteLink } from "jazz-react";
|
||||
import { CoMap, ID } from "jazz-tools";
|
||||
import { ChangeEvent, ReactNode, useCallback } from "react";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Button } from "@/components/Button.tsx";
|
||||
import { NavigateBack } from "@/components/NavigateBack.tsx";
|
||||
import { Stack } from "@/components/Stack.tsx";
|
||||
import { TextInput } from "@/components/TextInput.tsx";
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { useAccount, useCoState } from "@/main.tsx";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
@@ -1,28 +1,5 @@
|
||||
# organization
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.50
|
||||
- jazz-tools@0.8.50
|
||||
|
||||
## 0.0.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.49
|
||||
- jazz-tools@0.8.49
|
||||
|
||||
## 0.0.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [635e824]
|
||||
- Updated dependencies [0a85982]
|
||||
- jazz-tools@0.8.48
|
||||
- jazz-react@0.8.48
|
||||
|
||||
## 0.0.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -37,4 +37,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
|
||||
|
||||
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.14",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useAcceptInvite, useAccount } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useAcceptInvite, useAccount } from "./main.tsx";
|
||||
import { Organization } from "./schema.ts";
|
||||
|
||||
export function AcceptInvitePage() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { Layout } from "./Layout.tsx";
|
||||
import { CreateOrganization } from "./components/CreateOrganization.tsx";
|
||||
import { Heading } from "./components/Heading.tsx";
|
||||
import { useAccount } from "./main.tsx";
|
||||
|
||||
export function HomePage() {
|
||||
const { me } = useAccount({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { UserIcon } from "lucide-react";
|
||||
import { useAccount } from "./main.tsx";
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
const { me, logOut } = useAccount({
|
||||
|
||||
@@ -1,22 +1,34 @@
|
||||
import { useCoState } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { useParams } from "react-router";
|
||||
import { Layout } from "./Layout.tsx";
|
||||
import { CreateProject } from "./components/CreateProject.tsx";
|
||||
import { Heading } from "./components/Heading.tsx";
|
||||
import { InviteLink } from "./components/InviteLink.tsx";
|
||||
import { OrganizationMembers } from "./components/OrganizationMembers.tsx";
|
||||
import { RequestJoinButton } from "./components/RequestJoinButton.tsx";
|
||||
import { useCoState } from "./main.tsx";
|
||||
import { Organization } from "./schema.ts";
|
||||
|
||||
export function OrganizationPage() {
|
||||
const paramOrganizationId = useParams<{ organizationId: ID<Organization> }>()
|
||||
.organizationId;
|
||||
|
||||
const organization = useCoState(Organization, paramOrganizationId, {
|
||||
projects: [],
|
||||
});
|
||||
const organization = useCoState(Organization, paramOrganizationId, {});
|
||||
|
||||
if (!organization) return <p>Loading organization...</p>;
|
||||
const organizationWithContent = useCoState(
|
||||
Organization,
|
||||
paramOrganizationId,
|
||||
{
|
||||
content: {
|
||||
projects: [],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!organization) {
|
||||
return <p>Loading organization...</p>;
|
||||
}
|
||||
|
||||
const readOnlyAccess = organization && !organizationWithContent;
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
@@ -28,44 +40,46 @@ export function OrganizationPage() {
|
||||
<div className="flex justify-between items-center">
|
||||
<h2>Members</h2>
|
||||
|
||||
{organization._owner?.myRole() === "admin" && (
|
||||
<InviteLink organization={organization} />
|
||||
{readOnlyAccess && (
|
||||
<RequestJoinButton organizationId={organization.id} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="divide-y">
|
||||
<OrganizationMembers organization={organization} />
|
||||
</div>
|
||||
{organizationWithContent && (
|
||||
<div className="divide-y">
|
||||
<OrganizationMembers organization={organizationWithContent} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border shadow-sm bg-white dark:bg-stone-925">
|
||||
<div className="border-b px-4 py-5 sm:px-6">
|
||||
<h2>Projects</h2>
|
||||
</div>
|
||||
<div className="divide-y">
|
||||
{organization.projects.length > 0 ? (
|
||||
organization.projects.map((project) =>
|
||||
project ? (
|
||||
<strong
|
||||
key={project.id}
|
||||
className="px-4 py-5 sm:px-6 font-medium block"
|
||||
>
|
||||
{project.name}
|
||||
</strong>
|
||||
) : null,
|
||||
)
|
||||
) : (
|
||||
<p className="col-span-full text-center px-4 py-8 sm:px-6">
|
||||
You have no projects yet.
|
||||
</p>
|
||||
)}
|
||||
<div className="p-4 sm:p-6">
|
||||
<CreateProject organization={organization} />
|
||||
{organizationWithContent && (
|
||||
<div className="rounded-lg border shadow-sm bg-white dark:bg-stone-925">
|
||||
<div className="border-b px-4 py-5 sm:px-6">
|
||||
<h2>Projects</h2>
|
||||
</div>
|
||||
<div className="divide-y">
|
||||
{organizationWithContent.content.projects.length > 0 ? (
|
||||
organizationWithContent.content.projects.map((project) =>
|
||||
project ? (
|
||||
<strong
|
||||
key={project.id}
|
||||
className="px-4 py-5 sm:px-6 font-medium block"
|
||||
>
|
||||
{project.name}
|
||||
</strong>
|
||||
) : null,
|
||||
)
|
||||
) : (
|
||||
<p className="col-span-full text-center px-4 py-8 sm:px-6">
|
||||
You have no projects yet.
|
||||
</p>
|
||||
)}
|
||||
<div className="p-4 sm:p-6">
|
||||
<CreateProject organization={organization} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div></div>
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
import { DraftOrganization, ListOfProjects, Organization } from "../schema.ts";
|
||||
import { useAccount, useCoState } from "../main.tsx";
|
||||
import { DraftOrganization, createOrganization } from "../schema.ts";
|
||||
import { Errors } from "./Errors.tsx";
|
||||
import { OrganizationForm } from "./OrganizationForm.tsx";
|
||||
|
||||
@@ -25,16 +25,17 @@ export function CreateOrganization() {
|
||||
|
||||
const group = Group.create({ owner: me });
|
||||
|
||||
me.root.organizations.push(draft as Organization);
|
||||
const organization = createOrganization(me, draft.name ?? "");
|
||||
|
||||
me.root.organizations.push(organization);
|
||||
me.root.draftOrganization = DraftOrganization.create(
|
||||
{
|
||||
projects: ListOfProjects.create([], { owner: group }),
|
||||
name: "",
|
||||
},
|
||||
{ owner: group },
|
||||
);
|
||||
|
||||
navigate(`/organizations/${draft.id}`);
|
||||
navigate(`/organizations/${organization.id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -11,11 +11,14 @@ export function CreateProject({
|
||||
const onSave = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!organization?.projects) return;
|
||||
if (!organization?.content?.projects) return;
|
||||
|
||||
if (name.length > 0) {
|
||||
const project = Project.create({ name }, { owner: organization._owner });
|
||||
organization.projects.push(project);
|
||||
const project = Project.create(
|
||||
{ name },
|
||||
{ owner: organization.content._owner },
|
||||
);
|
||||
organization.content.projects.push(project);
|
||||
setName("");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import { createInviteLink } from "jazz-react";
|
||||
import { CheckIcon, CopyIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Organization } from "../schema.ts";
|
||||
|
||||
export function InviteLink({ organization }: { organization: Organization }) {
|
||||
const [inviteLink, setInviteLink] = useState<string>();
|
||||
let [copyCount, setCopyCount] = useState(0);
|
||||
let copied = copyCount > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (organization) {
|
||||
setInviteLink(createInviteLink(organization, "writer"));
|
||||
}
|
||||
}, [organization.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (copyCount > 0) {
|
||||
let timeout = setTimeout(() => setCopyCount(0), 1000);
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}
|
||||
}, [copyCount]);
|
||||
|
||||
const copyUrl = () => {
|
||||
if (inviteLink) {
|
||||
navigator.clipboard.writeText(inviteLink).then(() => {
|
||||
setCopyCount((count) => count + 1);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 text-blue-500 dark:text-blue-400"
|
||||
onClick={copyUrl}
|
||||
>
|
||||
{copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}
|
||||
Copy invite link
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,31 @@
|
||||
import { useCoState } from "jazz-react";
|
||||
import { Account, Group, ID } from "jazz-tools";
|
||||
import { Organization } from "../schema.ts";
|
||||
import { useCoState } from "../main.tsx";
|
||||
import {
|
||||
JoinOrganizationRequest,
|
||||
ListOfJoinOrganizationRequests,
|
||||
Organization,
|
||||
OrganizationContent,
|
||||
acceptJoinOrganizationRequest,
|
||||
} from "../schema.ts";
|
||||
|
||||
export function OrganizationMembers({
|
||||
organization,
|
||||
}: { organization: Organization }) {
|
||||
const group = organization._owner.castAs(Group);
|
||||
const privateContent = useCoState(
|
||||
OrganizationContent,
|
||||
organization._refs.content.id,
|
||||
{},
|
||||
);
|
||||
const joinRequests = useCoState(
|
||||
ListOfJoinOrganizationRequests,
|
||||
organization._refs.joinRequests.id,
|
||||
[{}],
|
||||
);
|
||||
|
||||
if (!privateContent) return null;
|
||||
|
||||
const group = privateContent._owner.castAs(Group);
|
||||
const myRole = group.myRole();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -16,6 +36,10 @@ export function OrganizationMembers({
|
||||
role={member.role}
|
||||
/>
|
||||
))}
|
||||
{myRole === "admin" &&
|
||||
joinRequests?.map((request) => (
|
||||
<JoinRequest key={request.id} request={request} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -33,3 +57,31 @@ function Member({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function JoinRequest({
|
||||
request,
|
||||
}: {
|
||||
request: JoinOrganizationRequest;
|
||||
}) {
|
||||
const account = useCoState(Account, request._refs.account.id, {
|
||||
profile: {},
|
||||
});
|
||||
|
||||
function handleAccept() {
|
||||
acceptJoinOrganizationRequest(request);
|
||||
}
|
||||
|
||||
if (!account?.profile) return;
|
||||
|
||||
return (
|
||||
<div className="px-4 py-4 sm:px-6 flex justify-between items-center">
|
||||
<strong className="font-medium">{account.profile.name}</strong>
|
||||
<button
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-4 rounded"
|
||||
onClick={handleAccept}
|
||||
>
|
||||
Accept
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { UsersIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { useAccount } from "../main.tsx";
|
||||
import { Organization } from "../schema.ts";
|
||||
|
||||
export function OrganizationSelector({ className }: { className?: string }) {
|
||||
|
||||
43
examples/organization/src/components/RequestJoinButton.tsx
Normal file
43
examples/organization/src/components/RequestJoinButton.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ID } from "jazz-tools";
|
||||
import { useAccount, useCoState } from "../main.tsx";
|
||||
import { Organization, requestJoinOrganization } from "../schema.ts";
|
||||
|
||||
export function RequestJoinButton({
|
||||
organizationId,
|
||||
}: { organizationId: ID<Organization> }) {
|
||||
const organization = useCoState(Organization, organizationId, {
|
||||
joinRequests: [{}],
|
||||
});
|
||||
|
||||
const { me } = useAccount();
|
||||
|
||||
if (!organization) return null;
|
||||
|
||||
const alreadyRequested = organization.joinRequests.some(
|
||||
(request) => request._refs.account.id === me.id,
|
||||
);
|
||||
|
||||
if (alreadyRequested) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 text-blue-500 dark:text-blue-400"
|
||||
disabled
|
||||
>
|
||||
Waiting for approval
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 text-blue-500 dark:text-blue-400"
|
||||
onClick={() => {
|
||||
requestJoinOrganization(me, organization);
|
||||
}}
|
||||
>
|
||||
Request to join
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DemoAuthBasicUI, JazzProvider, useDemoAuth } from "jazz-react";
|
||||
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
@@ -8,6 +8,11 @@ import { HomePage } from "./HomePage.tsx";
|
||||
import { OrganizationPage } from "./OrganizationPage.tsx";
|
||||
import { JazzAccount } from "./schema.ts";
|
||||
|
||||
const Jazz = createJazzReactApp({
|
||||
AccountSchema: JazzAccount,
|
||||
});
|
||||
|
||||
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
|
||||
function Router() {
|
||||
const router = createHashRouter([
|
||||
{
|
||||
@@ -32,13 +37,12 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<JazzProvider
|
||||
AccountSchema={JazzAccount}
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://cloud.jazz.tools/?key=organization-example@garden.co"
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
</Jazz.Provider>
|
||||
|
||||
{authState.state !== "signedIn" && (
|
||||
<DemoAuthBasicUI appName="Organization" state={authState} />
|
||||
@@ -47,12 +51,6 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: JazzAccount;
|
||||
}
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<JazzAndAuth>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createInviteLink, parseInviteLink } from "jazz-react";
|
||||
import { Account, CoList, CoMap, Group, co } from "jazz-tools";
|
||||
|
||||
export class Project extends CoMap {
|
||||
@@ -7,13 +8,19 @@ export class Project extends CoMap {
|
||||
export class ListOfProjects extends CoList.Of(co.ref(Project)) {}
|
||||
|
||||
export class Organization extends CoMap {
|
||||
// everyone is a reader
|
||||
name = co.string;
|
||||
content = co.ref(OrganizationContent); // limited access
|
||||
joinRequests = co.ref(ListOfJoinOrganizationRequests); // writeOnly access
|
||||
joinRequestsInviteLink = co.string;
|
||||
}
|
||||
|
||||
export class OrganizationContent extends CoMap {
|
||||
projects = co.ref(ListOfProjects);
|
||||
}
|
||||
|
||||
export class DraftOrganization extends CoMap {
|
||||
name = co.optional.string;
|
||||
projects = co.ref(ListOfProjects);
|
||||
|
||||
validate() {
|
||||
const errors: string[] = [];
|
||||
@@ -28,8 +35,24 @@ export class DraftOrganization extends CoMap {
|
||||
}
|
||||
}
|
||||
|
||||
export class JoinOrganizationRequest extends CoMap {
|
||||
organization = co.ref(Organization);
|
||||
account = co.ref(Account);
|
||||
}
|
||||
|
||||
export class ListOfOrganizations extends CoList.Of(co.ref(Organization)) {}
|
||||
|
||||
export class ListOfJoinOrganizationRequests extends CoList.Of(
|
||||
co.ref(JoinOrganizationRequest),
|
||||
) {
|
||||
removeRequest(request: JoinOrganizationRequest) {
|
||||
const index = this.findIndex((r) => r?.id === request.id);
|
||||
if (index !== -1) {
|
||||
this.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class JazzAccountRoot extends CoMap {
|
||||
organizations = co.ref(ListOfOrganizations);
|
||||
draftOrganization = co.ref(DraftOrganization);
|
||||
@@ -45,24 +68,18 @@ export class JazzAccount extends Account {
|
||||
};
|
||||
const draftOrganization = DraftOrganization.create(
|
||||
{
|
||||
projects: ListOfProjects.create([], draftOrganizationOwnership),
|
||||
name: "",
|
||||
},
|
||||
draftOrganizationOwnership,
|
||||
);
|
||||
|
||||
const initialOrganizationOwnership = {
|
||||
owner: Group.create({ owner: this }),
|
||||
};
|
||||
const organizations = ListOfOrganizations.create(
|
||||
[
|
||||
Organization.create(
|
||||
{
|
||||
name: this.profile?.name
|
||||
? `${this.profile.name}'s projects`
|
||||
: "Your projects",
|
||||
projects: ListOfProjects.create([], initialOrganizationOwnership),
|
||||
},
|
||||
initialOrganizationOwnership,
|
||||
createOrganization(
|
||||
this,
|
||||
this.profile?.name
|
||||
? `${this.profile.name}'s projects`
|
||||
: "Your projects",
|
||||
),
|
||||
],
|
||||
{ owner: this },
|
||||
@@ -78,3 +95,93 @@ export class JazzAccount extends Account {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createOrganization(account: Account, name: string) {
|
||||
const organizationOwnership = {
|
||||
owner: Group.create({ owner: account }),
|
||||
};
|
||||
|
||||
// We give read only access to everyone so that guests can see the organization name
|
||||
// and request to join
|
||||
organizationOwnership.owner.addMember("everyone", "reader");
|
||||
|
||||
const joinRequestsGroup = Group.create({ owner: account });
|
||||
|
||||
const joinRequests = ListOfJoinOrganizationRequests.create([], {
|
||||
owner: joinRequestsGroup,
|
||||
});
|
||||
|
||||
// We give write only access to the join requests so that only the organization admins
|
||||
// can see and manage join requests
|
||||
const joinRequestsInviteLink = createInviteLink(joinRequests, "writeOnly");
|
||||
|
||||
const contentOwnership = {
|
||||
owner: Group.create({ owner: account }),
|
||||
};
|
||||
|
||||
const projects = ListOfProjects.create([], contentOwnership);
|
||||
const content = OrganizationContent.create({ projects }, contentOwnership);
|
||||
|
||||
const organization = Organization.create(
|
||||
{ name, joinRequests, joinRequestsInviteLink, content },
|
||||
organizationOwnership,
|
||||
);
|
||||
|
||||
return organization;
|
||||
}
|
||||
|
||||
export async function acceptJoinOrganizationRequest(
|
||||
joinRequest: JoinOrganizationRequest,
|
||||
) {
|
||||
const result = await joinRequest.ensureLoaded({
|
||||
organization: {
|
||||
joinRequests: [],
|
||||
content: {},
|
||||
},
|
||||
account: {},
|
||||
});
|
||||
|
||||
if (!result) return;
|
||||
|
||||
const { organization, account } = result;
|
||||
|
||||
organization.joinRequests.removeRequest(joinRequest);
|
||||
|
||||
const organizationContentGroup = organization.content._owner.castAs(Group);
|
||||
organizationContentGroup.addMember(account, "writer");
|
||||
}
|
||||
|
||||
export async function requestJoinOrganization(
|
||||
account: JazzAccount,
|
||||
organization: Organization,
|
||||
) {
|
||||
const parsedLink = parseInviteLink<ListOfJoinOrganizationRequests>(
|
||||
organization.joinRequestsInviteLink,
|
||||
);
|
||||
|
||||
if (!parsedLink) return;
|
||||
|
||||
const joinRequests = await account.acceptInvite(
|
||||
parsedLink.valueID,
|
||||
parsedLink.inviteSecret,
|
||||
ListOfJoinOrganizationRequests,
|
||||
);
|
||||
|
||||
if (!joinRequests) return;
|
||||
|
||||
const joinRequestsGroup = joinRequests._owner.castAs(Group);
|
||||
const joinRequest = JoinOrganizationRequest.create(
|
||||
{ organization, account },
|
||||
{ owner: joinRequestsGroup },
|
||||
);
|
||||
|
||||
joinRequests.push(joinRequest);
|
||||
|
||||
const result = await account.ensureLoaded({ root: { organizations: [] } });
|
||||
|
||||
if (!result) return;
|
||||
|
||||
const { root } = result;
|
||||
|
||||
root.organizations.push(organization);
|
||||
}
|
||||
|
||||
@@ -1,23 +1,5 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 0.0.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.8.50
|
||||
|
||||
## 0.0.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.8.49
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.8.48
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user