First commit
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
# production
|
||||
dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
@@ -0,0 +1,10 @@
|
||||
## Simple app for NextGraph
|
||||
|
||||
A simple app that use Refine providers compatible with NextGraph
|
||||
|
||||
## Quick start
|
||||
|
||||
```
|
||||
pnpm install
|
||||
pnpm run dev
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Web site created using refine" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<title>refine authentication example</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm run dev` or `yarn dev`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
--></body>
|
||||
</html>
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "antd-app",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "refine build",
|
||||
"dev": "refine dev",
|
||||
"refine": "refine",
|
||||
"start": "refine start",
|
||||
"build:orm": "rdf-orm build --input ./src/shapes/shex --output ./src/shapes/orm"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^5.5.1",
|
||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
||||
"@ng-org/orm": "0.1.2-alpha.19",
|
||||
"@ng-org/web": "0.1.2-alpha.13",
|
||||
"@ng-org/refine-providers": "workspace:*",
|
||||
"@refinedev/antd": "^6.0.3",
|
||||
"@refinedev/cli": "^2.16.52",
|
||||
"@refinedev/core": "^5.0.12",
|
||||
"@refinedev/react-router": "^2.0.4",
|
||||
"@uiw/react-md-editor": "^4.0.8",
|
||||
"antd": "^5.23.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-router": "^7.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ng-org/shex-orm": "0.1.2-alpha.8",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19.1.0",
|
||||
"@types/react-dom": "^19.1.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^5.4.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "refine authentication example",
|
||||
"name": "refine authentication example",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import {
|
||||
Refine,
|
||||
Authenticated,
|
||||
} from "@refinedev/core";
|
||||
import {
|
||||
useNotificationProvider,
|
||||
ThemedLayout,
|
||||
ErrorComponent,
|
||||
RefineThemes,
|
||||
} from "@refinedev/antd";
|
||||
import {
|
||||
DashboardOutlined,
|
||||
} from "@ant-design/icons";
|
||||
|
||||
import routerProvider, {
|
||||
NavigateToResource,
|
||||
CatchAllNavigate,
|
||||
UnsavedChangesNotifier,
|
||||
DocumentTitleHandler,
|
||||
} from "@refinedev/react-router";
|
||||
import { BrowserRouter, Routes, Route, Outlet, Navigate } from "react-router";
|
||||
import { App as AntdApp, ConfigProvider } from "antd";
|
||||
|
||||
import "@ant-design/v5-patch-for-react-19";
|
||||
import "@refinedev/antd/dist/reset.css";
|
||||
|
||||
import { authProvider, dataProvider, liveProvider } from "@ng-org/refine-providers";
|
||||
|
||||
import dataModels from "./shapes/data-models";
|
||||
import AuthPage from "./components/AuthPage";
|
||||
import { PostList, PostCreate, PostEdit, PostShow } from "../src/pages/posts";
|
||||
import { DashboardPage } from "../src/pages/dashboard";
|
||||
|
||||
import { getSession } from "./utils/initNg";
|
||||
|
||||
const App: React.FC = () => (
|
||||
<BrowserRouter basename={import.meta.env.MODE === 'production' ? '/nextgraph-refine-app/' : '/'}>
|
||||
<ConfigProvider theme={RefineThemes.Blue}>
|
||||
<AntdApp>
|
||||
<Refine
|
||||
// authProvider={authProvider}
|
||||
dataProvider={dataProvider({ dataModels, getSession })}
|
||||
liveProvider={liveProvider({ dataModels })}
|
||||
routerProvider={routerProvider}
|
||||
resources={[
|
||||
// {
|
||||
// name: "dashboard",
|
||||
// list: "/",
|
||||
// meta: {
|
||||
// label: "Dashboard",
|
||||
// icon: <DashboardOutlined />,
|
||||
// },
|
||||
// },
|
||||
{
|
||||
name: "posts",
|
||||
list: "/posts",
|
||||
create: "/posts/create",
|
||||
show: "/posts/show/:id",
|
||||
edit: "/posts/edit/:id",
|
||||
meta: {
|
||||
canDelete: true,
|
||||
},
|
||||
},
|
||||
]}
|
||||
notificationProvider={useNotificationProvider}
|
||||
options={{
|
||||
syncWithLocation: true,
|
||||
warnWhenUnsavedChanges: true,
|
||||
liveMode: "auto",
|
||||
disableTelemetry: true,
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route
|
||||
element={
|
||||
// <Authenticated
|
||||
// key="authenticated-routes"
|
||||
// fallback={<CatchAllNavigate to="/login" />}
|
||||
// >
|
||||
<ThemedLayout>
|
||||
<Outlet />
|
||||
</ThemedLayout>
|
||||
// </Authenticated>
|
||||
}
|
||||
>
|
||||
<Route index element={<Navigate to="/" />} />
|
||||
{/* <Route index element={<DashboardPage />} /> */}
|
||||
|
||||
<Route path="/posts">
|
||||
<Route index element={<PostList />} />
|
||||
<Route path="create" element={<PostCreate />} />
|
||||
<Route path="edit/:id" element={<PostEdit />} />
|
||||
<Route path="show/:id" element={<PostShow />} />
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
{/* <Route
|
||||
element={
|
||||
<Authenticated key="auth-pages" fallback={<Outlet />}>
|
||||
<NavigateToResource resource="posts" />
|
||||
</Authenticated>
|
||||
}
|
||||
>
|
||||
<Route path="/login" element={<AuthPage />} />
|
||||
<Route path="/register" element={<AuthPage />} />
|
||||
</Route> */}
|
||||
|
||||
<Route
|
||||
element={
|
||||
// <Authenticated key="catch-all">
|
||||
<ThemedLayout>
|
||||
<Outlet />
|
||||
</ThemedLayout>
|
||||
// </Authenticated>
|
||||
}
|
||||
>
|
||||
<Route path="*" element={<ErrorComponent />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
<UnsavedChangesNotifier />
|
||||
<DocumentTitleHandler />
|
||||
</Refine>
|
||||
</AntdApp>
|
||||
</ConfigProvider>
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,172 @@
|
||||
import type { CSSProperties } from "react";
|
||||
|
||||
import {
|
||||
type LoginPageProps,
|
||||
type LoginFormTypes,
|
||||
} from "@refinedev/core";
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Layout,
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
type CardProps,
|
||||
type LayoutProps,
|
||||
type FormProps,
|
||||
theme,
|
||||
} from "antd";
|
||||
import { useLogin, useTranslate } from "@refinedev/core";
|
||||
import { ThemedTitle } from "@refinedev/antd";
|
||||
|
||||
export const layoutStyles: CSSProperties = {};
|
||||
|
||||
export const containerStyles: CSSProperties = {
|
||||
maxWidth: "400px",
|
||||
margin: "auto",
|
||||
padding: "32px",
|
||||
boxShadow:
|
||||
"0px 2px 4px rgba(0, 0, 0, 0.02), 0px 1px 6px -1px rgba(0, 0, 0, 0.02), 0px 1px 2px rgba(0, 0, 0, 0.03)",
|
||||
};
|
||||
|
||||
export const headStyles: CSSProperties = {
|
||||
borderBottom: 0,
|
||||
padding: 0,
|
||||
};
|
||||
|
||||
export const bodyStyles: CSSProperties = { padding: 0 };
|
||||
|
||||
export const titleStyles: CSSProperties = {
|
||||
textAlign: "center",
|
||||
marginBottom: 0,
|
||||
fontSize: "24px",
|
||||
lineHeight: "32px",
|
||||
fontWeight: 700,
|
||||
overflowWrap: "break-word",
|
||||
hyphens: "manual",
|
||||
textOverflow: "unset",
|
||||
whiteSpace: "pre-wrap",
|
||||
};
|
||||
|
||||
type LoginProps = LoginPageProps<LayoutProps, CardProps, FormProps>;
|
||||
|
||||
export const AuthPage: React.FC<LoginProps> = ({
|
||||
contentProps,
|
||||
wrapperProps,
|
||||
renderContent,
|
||||
formProps,
|
||||
title,
|
||||
hideForm,
|
||||
mutationVariables,
|
||||
}) => {
|
||||
const { token } = theme.useToken();
|
||||
const [form] = Form.useForm<LoginFormTypes>();
|
||||
const translate = useTranslate();
|
||||
|
||||
const { mutate: login, isPending } = useLogin<LoginFormTypes>();
|
||||
|
||||
const PageTitle =
|
||||
title === false ? null : (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
marginBottom: "32px",
|
||||
fontSize: "20px",
|
||||
}}
|
||||
>
|
||||
{title ?? <ThemedTitle collapsed={false} />}
|
||||
</div>
|
||||
);
|
||||
|
||||
const CardContent = (
|
||||
<Card
|
||||
// title={CardTitle}
|
||||
styles={{
|
||||
header: headStyles,
|
||||
body: bodyStyles,
|
||||
}}
|
||||
style={{
|
||||
...containerStyles,
|
||||
backgroundColor: token.colorBgElevated,
|
||||
}}
|
||||
{...(contentProps ?? {})}
|
||||
>
|
||||
<Form<LoginFormTypes>
|
||||
layout="vertical"
|
||||
form={form}
|
||||
onFinish={(values) => login({ ...values, ...mutationVariables })}
|
||||
requiredMark={false}
|
||||
initialValues={{
|
||||
brokerUrl: 'https://nextgraph.eu'
|
||||
}}
|
||||
{...formProps}
|
||||
>
|
||||
<Form.Item
|
||||
name="brokerUrl"
|
||||
label={translate("pages.login.fields.brokerUrl", "Broker URL")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: translate(
|
||||
"pages.login.errors.requiredBrokerUrl",
|
||||
"Broker URL is required",
|
||||
),
|
||||
},
|
||||
{
|
||||
type: "url",
|
||||
message: translate(
|
||||
"pages.login.errors.validBrokerUrl",
|
||||
"Invalid broker URL",
|
||||
),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
size="large"
|
||||
placeholder={translate("pages.login.fields.brokerUrl", "Broker URL")}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
htmlType="submit"
|
||||
loading={isPending}
|
||||
block
|
||||
>
|
||||
{translate("pages.login.signin", "Sign in")}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
);
|
||||
|
||||
return (
|
||||
<Layout style={layoutStyles} {...(wrapperProps ?? {})}>
|
||||
<Row
|
||||
justify="center"
|
||||
align={hideForm ? "top" : "middle"}
|
||||
style={{
|
||||
padding: "16px 0",
|
||||
minHeight: "100dvh",
|
||||
paddingTop: hideForm ? "15dvh" : "16px",
|
||||
}}
|
||||
>
|
||||
<Col xs={22}>
|
||||
{renderContent ? (
|
||||
renderContent(CardContent, PageTitle)
|
||||
) : (
|
||||
<>
|
||||
{PageTitle}
|
||||
{CardContent}
|
||||
</>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthPage;
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
import App from "./App";
|
||||
|
||||
const container = document.getElementById("root");
|
||||
// eslint-disable-next-line
|
||||
const root = createRoot(container!);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useGetIdentity, usePermissions } from "@refinedev/core";
|
||||
import { Row, Col, Card, Avatar, Typography, Space } from "antd";
|
||||
const { Text } = Typography;
|
||||
|
||||
export const DashboardPage: React.FC = () => {
|
||||
const { data: identity } = useGetIdentity<{
|
||||
id: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
}>();
|
||||
const permissions = usePermissions<string[], { permissions: string[] }>({
|
||||
params: { permissions: ["admin"] },
|
||||
});
|
||||
|
||||
return (
|
||||
<Row gutter={20}>
|
||||
<Col span={6}>
|
||||
<Card
|
||||
title="Identity"
|
||||
style={{ height: "300px", borderRadius: "15px" }}
|
||||
headStyle={{ textAlign: "center" }}
|
||||
>
|
||||
<Space align="center" direction="horizontal">
|
||||
<Avatar size="large" src={identity?.avatar} />
|
||||
<Text>{identity?.name}</Text>
|
||||
</Space>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Card
|
||||
title="Permissions"
|
||||
style={{ height: "300px", borderRadius: "15px" }}
|
||||
headStyle={{ textAlign: "center" }}
|
||||
>
|
||||
<Text>{permissions.data}</Text>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Create, useForm } from "@refinedev/antd";
|
||||
import { Form, Input } from "antd";
|
||||
import MDEditor from "@uiw/react-md-editor";
|
||||
import type { Note } from "../../shapes/orm/post.typings";
|
||||
|
||||
export const PostCreate = () => {
|
||||
const { formProps, saveButtonProps } = useForm<Note>();
|
||||
|
||||
return (
|
||||
<Create saveButtonProps={saveButtonProps}>
|
||||
<Form {...formProps} layout="vertical">
|
||||
<Form.Item
|
||||
label="Title"
|
||||
name="title"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder="Enter a post title" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Content"
|
||||
name="content"
|
||||
>
|
||||
<MDEditor data-color-mode="light" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Create>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { Edit, useForm, RefreshButton } from "@refinedev/antd";
|
||||
import { useNavigation, useNotification, type LiveEvent } from "@refinedev/core";
|
||||
import { Alert, Form, Input } from "antd";
|
||||
import MDEditor from "@uiw/react-md-editor";
|
||||
import type { Note } from "../../shapes/orm/post.typings";
|
||||
|
||||
export const PostEdit = () => {
|
||||
const [deprecated, setDeprecated] = useState<boolean>(false);
|
||||
|
||||
const { list } = useNavigation();
|
||||
const { open } = useNotification();
|
||||
|
||||
const onLiveEvent = useCallback((event: LiveEvent) => {
|
||||
console.log('onLiveEvent', event);
|
||||
if (event.type === "deleted") {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "This post has been deleted",
|
||||
});
|
||||
list("posts");
|
||||
} else if (event.type === "updated") {
|
||||
setDeprecated(true);
|
||||
}
|
||||
}, [open, list]);
|
||||
|
||||
const { formProps, saveButtonProps, query: queryResult } = useForm<Note>({
|
||||
liveMode: 'manual',
|
||||
onLiveEvent,
|
||||
});
|
||||
|
||||
const handleRefresh = () => {
|
||||
queryResult?.refetch();
|
||||
setDeprecated(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Edit saveButtonProps={saveButtonProps}>
|
||||
<Form {...formProps} layout="vertical">
|
||||
{deprecated && (
|
||||
<Alert
|
||||
message="This post has been updated. Refresh to see changes."
|
||||
type="warning"
|
||||
style={{ marginBottom: 20 }}
|
||||
action={<RefreshButton size="small" onClick={handleRefresh} />}
|
||||
/>
|
||||
)}
|
||||
<Form.Item
|
||||
label="Title"
|
||||
name="title"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Content"
|
||||
name="content"
|
||||
>
|
||||
<MDEditor data-color-mode="light" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Edit>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./list";
|
||||
export * from "./create";
|
||||
export * from "./edit";
|
||||
export * from "./show";
|
||||
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
List,
|
||||
useTable,
|
||||
EditButton,
|
||||
ShowButton,
|
||||
DeleteButton,
|
||||
CreateButton,
|
||||
} from "@refinedev/antd";
|
||||
import { useNavigation } from "@refinedev/core";
|
||||
import { Table, Space } from "antd";
|
||||
import type { Note } from "../../shapes/orm/post.typings";
|
||||
|
||||
const shortenNuri = (nuri: string) => {
|
||||
return nuri?.split(':')[3]?.slice(0, 7);
|
||||
};
|
||||
|
||||
export const PostList = () => {
|
||||
const { tableProps } = useTable<Note>();
|
||||
const { show } = useNavigation();
|
||||
|
||||
return (
|
||||
<List headerButtons={<CreateButton />}>
|
||||
<Table
|
||||
{...tableProps}
|
||||
rowKey="@graph"
|
||||
onRow={(record) => ({
|
||||
onClick: () => show("posts", record["@graph"]),
|
||||
style: { cursor: "pointer" },
|
||||
})}
|
||||
>
|
||||
<Table.Column dataIndex="@graph" title="ID" render={shortenNuri} />
|
||||
<Table.Column dataIndex="title" title="Title" />
|
||||
<Table.Column dataIndex="content" title="Content" />
|
||||
<Table.Column<Note>
|
||||
title="Actions"
|
||||
dataIndex="actions"
|
||||
align="right"
|
||||
render={(_, record) => (
|
||||
<Space onClick={(e) => e.stopPropagation()}>
|
||||
<EditButton hideText size="small" recordItemId={record['@graph']} />
|
||||
<ShowButton hideText size="small" recordItemId={record['@graph']} />
|
||||
<DeleteButton hideText size="small" recordItemId={record['@graph']} />
|
||||
</Space>
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import { useCallback } from "react";
|
||||
import { useShow, useNavigation, useNotification, type LiveEvent } from "@refinedev/core";
|
||||
import { Show, MarkdownField } from "@refinedev/antd";
|
||||
import { Typography } from "antd";
|
||||
import type { Note } from "../../shapes/orm/post.typings";
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
export const PostShow = () => {
|
||||
const { list } = useNavigation();
|
||||
const { open } = useNotification();
|
||||
|
||||
const onLiveEvent = useCallback((event: LiveEvent) => {
|
||||
if (event.type === "deleted") {
|
||||
open?.({
|
||||
type: "error",
|
||||
message: "This post has been deleted",
|
||||
});
|
||||
list("posts");
|
||||
}
|
||||
}, [open, list]);
|
||||
|
||||
const { query: queryResult } = useShow<Note>({ liveMode: "auto", onLiveEvent });
|
||||
const { data, isLoading } = queryResult;
|
||||
const record = data?.data;
|
||||
|
||||
return (
|
||||
<Show isLoading={isLoading}>
|
||||
<Title level={5}>Id</Title>
|
||||
<Text>{record?.['@graph']}</Text>
|
||||
<Title level={5}>Title</Title>
|
||||
<Text>{record?.title}</Text>
|
||||
<Title level={5}>Content</Title>
|
||||
<MarkdownField value={record?.content} />
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { DataModels } from "@ng-org/refine-providers";
|
||||
import { NoteShapeType } from "./orm/post.shapeTypes";
|
||||
|
||||
const dataModels : DataModels = {
|
||||
posts: {
|
||||
shapeType: NoteShapeType
|
||||
}
|
||||
}
|
||||
|
||||
export default dataModels;
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { Schema } from "@ng-org/shex-orm";
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* postSchema: Schema for post
|
||||
* =============================================================================
|
||||
*/
|
||||
export const postSchema = {
|
||||
"https://www.w3.org/ns/activitystreams#Note": {
|
||||
iri: "https://www.w3.org/ns/activitystreams#Note",
|
||||
predicates: [
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
literals: ["https://www.w3.org/ns/activitystreams#Note"],
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "https://www.w3.org/ns/activitystreams#title",
|
||||
readablePredicate: "title",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "https://www.w3.org/ns/activitystreams#content",
|
||||
readablePredicate: "content",
|
||||
},
|
||||
],
|
||||
},
|
||||
} as const satisfies Schema;
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { ShapeType } from "@ng-org/shex-orm";
|
||||
import { postSchema } from "./post.schema";
|
||||
import type { Note } from "./post.typings";
|
||||
|
||||
// ShapeTypes for post
|
||||
export const NoteShapeType = {
|
||||
schema: postSchema,
|
||||
shape: "https://www.w3.org/ns/activitystreams#Note",
|
||||
} as const satisfies ShapeType<Note>;
|
||||
@@ -0,0 +1,37 @@
|
||||
export type IRI = string;
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* Typescript Typings for post
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note Type
|
||||
*/
|
||||
export interface Note {
|
||||
/**
|
||||
* The graph NURI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
* The subject IRI.
|
||||
*/
|
||||
readonly "@id": IRI;
|
||||
/**
|
||||
* Original IRI: http://www.w3.org/1999/02/22-rdf-syntax-ns#type
|
||||
*/
|
||||
"@type": "https://www.w3.org/ns/activitystreams#Note";
|
||||
/**
|
||||
* The title of the post
|
||||
*
|
||||
* Original IRI: https://www.w3.org/ns/activitystreams#title
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* The content of the post
|
||||
*
|
||||
* Original IRI: https://www.w3.org/ns/activitystreams#content
|
||||
*/
|
||||
content?: string;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
PREFIX as: <https://www.w3.org/ns/activitystreams#>
|
||||
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
|
||||
as:Note {
|
||||
a [as:Note] ;
|
||||
as:title xsd:string
|
||||
// rdfs:comment "The title of the post" ;
|
||||
as:content xsd:string ?
|
||||
// rdfs:comment "The content of the post" ;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ng, init, Session } from "@ng-org/web";
|
||||
import { initNg } from "@ng-org/orm";
|
||||
|
||||
export let session: Session | undefined;
|
||||
|
||||
init(
|
||||
async (event: any) => {
|
||||
session = event.session;
|
||||
// The ORM needs to have access to ng,
|
||||
// the interface to the engine running in WASM.
|
||||
initNg(ng, session!);
|
||||
},
|
||||
true,
|
||||
[],
|
||||
);
|
||||
|
||||
export const getSession = () => session;
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler"
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
});
|
||||
Reference in New Issue
Block a user