Skip to content

Commit 793e46b

Browse files
committed
Page for showing own nodes with ability to delete them
1 parent 200f166 commit 793e46b

8 files changed

Lines changed: 160 additions & 4 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use server"
2+
3+
import {cookies} from "next/headers";
4+
import {createClient} from "@/utils/supabase/server";
5+
import {NodeDefinitionPreview} from "@/model/NodeDefinition";
6+
7+
export default async function(creatorId: string, teamId: number): Promise<NodeDefinitionPreview[]> {
8+
9+
const cookieStore = cookies()
10+
const supabase = createClient(cookieStore, process.env.SUPABASE_SERVICE_KEY)
11+
12+
let { data, error } = await supabase
13+
.from("node_definition")
14+
.select("id, " +
15+
"name: definition->name, " +
16+
"icon: definition->icon, " +
17+
"shortDescription: definition->shortDescription, " +
18+
"executionMode: definition->executionMode"
19+
)
20+
.eq("created_by", creatorId)
21+
.eq("team_id", teamId)
22+
.returns<NodeDefinitionPreview[]>()
23+
24+
if (error || !data) {
25+
throw Error(error?.message || "Error getting node definitions for user")
26+
}
27+
28+
return data
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use server"
2+
3+
import {cookies} from "next/headers";
4+
import {createClient} from "@/utils/supabase/server";
5+
6+
export default async function(nodeDefinitionId: number): Promise<void> {
7+
8+
const cookieStore = cookies()
9+
const supabase = createClient(cookieStore)
10+
11+
const response = await supabase
12+
.from("node_definition")
13+
.delete()
14+
.eq("id", nodeDefinitionId)
15+
16+
if (response.error) {
17+
throw Error("Error while deleting node to team: " + response.error.message)
18+
}
19+
20+
return
21+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import getNodeDefinitionsFromUser from "@/actions/shop/get-node-definition-previews-from-user";
2+
import {cookies} from "next/headers";
3+
import {createClient} from "@/utils/supabase/server";
4+
import {redirect} from "next/navigation";
5+
import {NodeDefinitionPreview} from "@/model/NodeDefinition";
6+
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/components/ui/card";
7+
import {Badge} from "@/components/ui/badge";
8+
import Link from "next/link";
9+
import {ArrowRight, Trash2} from "lucide-react";
10+
import {Button} from "@/components/ui/button";
11+
import {getTranslations} from "next-intl/server";
12+
import {Tooltip, TooltipContent, TooltipTrigger} from "@/components/ui/tooltip";
13+
import removeNodeDefinitionPermanently from "@/actions/shop/remove-node-definition-permanently";
14+
15+
export default async function OwnNodesPage({ params }: { params: { teamId: number } }) {
16+
17+
const t = await getTranslations("shop")
18+
19+
const cookieStore = cookies()
20+
const supabase = createClient(cookieStore)
21+
const {data: userData, error} = await supabase.auth.getUser()
22+
if (error || !userData.user || !userData.user.id) {
23+
redirect("/authenticate")
24+
}
25+
26+
const nodeDefinitions = await getNodeDefinitionsFromUser(userData.user.id, params.teamId)
27+
28+
async function handleRemoveNode(nodeId: number) {
29+
"use server"
30+
31+
removeNodeDefinitionPermanently(nodeId).then(() => {
32+
console.log("Node removed successfully")
33+
})
34+
35+
console.log("Removing node with id: ", nodeId)
36+
}
37+
38+
return <>
39+
<h2 className="text-3xl font-bold">{t("node.own-nodes")}</h2>
40+
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
41+
{nodeDefinitions.map((node: NodeDefinitionPreview) => (
42+
<Card key={node.id} className="group hover:shadow-lg transition-shadow">
43+
<CardHeader>
44+
<div className="flex items-start justify-between">
45+
<div>
46+
<CardTitle className="text-lg">{node.name}</CardTitle>
47+
<CardDescription>{node.shortDescription}</CardDescription>
48+
</div>
49+
<Badge variant="secondary">{node.executionMode}</Badge>
50+
</div>
51+
</CardHeader>
52+
<CardContent>
53+
<div className="flex items-center justify-between">
54+
<Link href={`/${params.teamId}/shop/node/${node.id}`}
55+
className="inline-flex items-center text-sm text-primary hover:underline">
56+
{t("node.viewDetails")}
57+
<ArrowRight className="ml-1 h-4 w-4"/>
58+
</Link>
59+
{node.id && <form action={handleRemoveNode.bind(null, node.id)} method="POST">
60+
<Tooltip delayDuration={0}>
61+
<TooltipTrigger>
62+
<Button
63+
variant="ghost"
64+
size="icon"
65+
type="submit"
66+
className="h-8 w-8 text-muted-foreground hover:bg-destructive transition-colors"
67+
>
68+
<Trash2 className="h-4 w-4"/>
69+
<span className="sr-only">Remove node</span>
70+
</Button>
71+
</TooltipTrigger>
72+
<TooltipContent>
73+
{t("node.removeNodePermanently")}
74+
</TooltipContent>
75+
</Tooltip>
76+
</form>}
77+
</div>
78+
</CardContent>
79+
</Card>
80+
))}
81+
</div>
82+
</>
83+
}

src/components/sidebar/AppBreadcrumbs.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export default function AppBreadcrumbs({ teamId, userId }: AppBreadcrumbsProps)
3838
const shopSavedNodesPath = `/${teamId}/shop/saved-nodes`
3939
const shopCreateNodePath = `/${teamId}/shop/create-node`
4040
const shopDetailsPath = `/${teamId}/shop/node`
41+
const shopOwnNodesPath = `/${teamId}/shop/own-nodes`
4142

4243
const newBreadcrumbs: BreadcrumbModel[] = []
4344

@@ -133,6 +134,11 @@ export default function AppBreadcrumbs({ teamId, userId }: AppBreadcrumbsProps)
133134
})
134135
}
135136
}
137+
} else if (pathname.startsWith(shopOwnNodesPath)) {
138+
newBreadcrumbs.push({
139+
name: t('ownNodes'),
140+
href: shopOwnNodesPath
141+
});
136142
}
137143
}
138144

src/components/sidebar/AppSidebar.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {redirect} from "next/navigation";
1818
import {Page, Profile} from "@/model/database/database.types";
1919
import getAllowedPages from "@/actions/get-allowed-pages";
2020
import {getTranslations} from "next-intl/server";
21-
import type {LucideIcon} from "lucide-react"
21+
import {BookUser, LucideIcon} from "lucide-react"
2222
import {
2323
Award,
2424
ChartColumn,
@@ -193,6 +193,14 @@ export default async function AppSidebar({ teamId, profile, ...props }: AppSideb
193193
</Link>
194194
</SidebarMenuButton>
195195
</SidebarMenuItem>
196+
<SidebarMenuItem>
197+
<SidebarMenuButton asChild tooltip={t("ownNodes")}>
198+
<Link href={`/${teamId}/shop/own-nodes`}>
199+
<BookUser />
200+
<span>{ t("ownNodes") }</span>
201+
</Link>
202+
</SidebarMenuButton>
203+
</SidebarMenuItem>
196204
</SidebarMenu>
197205
</SidebarGroup>
198206
</SidebarContent>

src/i18n/dictionaries/de.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
"shopGroupTitle": "Shop",
5858
"shop": "Shop",
5959
"addedNodes": "Gespeicherte Aktivitäten",
60-
"createNode": "Aktivität erstellen"
60+
"createNode": "Aktivität erstellen",
61+
"ownNodes": "Eigene Aktivitäten"
6162
},
6263
"userNav": {
6364
"settings": "Einstellungen",
@@ -354,6 +355,8 @@
354355
},
355356
"node": {
356357
"viewDetails": "Details anzeigen",
358+
"own-nodes": "Eigene Aktivitäten",
359+
"removeNodePermanently": "Aktivität dauerhaft entfernen",
357360
"details": {
358361
"addToEditor": "Zum Editor hinzufügen",
359362
"removeFromEditor": "Vom Editor entfernen",

src/i18n/dictionaries/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
"shopGroupTitle": "Shop",
5858
"shop": "Shop",
5959
"addedNodes": "Saved Activities",
60-
"createNode": "Create Activity"
60+
"createNode": "Create Activity",
61+
"ownNodes": "My Activities"
6162
},
6263
"userNav": {
6364
"settings": "Settings",
@@ -354,6 +355,8 @@
354355
},
355356
"node": {
356357
"viewDetails": "View details",
358+
"own-nodes": "My Activities",
359+
"removeNodePermanently": "Remove activity permanently",
357360
"details": {
358361
"addToEditor": "Add to editor",
359362
"removeFromEditor": "Remove from editor",

src/i18n/dictionaries/sr.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
"shopGroupTitle": "Prodavnica",
5757
"shop": "Prodavnica",
5858
"addedNodes": "Dodate aktivnosti",
59-
"createNode": "Kreiraj aktivnost"
59+
"createNode": "Kreiraj aktivnost",
60+
"ownNodes": "Moje aktivnosti"
6061
},
6162
"userNav": {
6263
"settings": "Podešavanja",
@@ -353,6 +354,8 @@
353354
},
354355
"node": {
355356
"viewDetails": "Pogledaj detalje",
357+
"own-nodes": "Moje aktivnosti",
358+
"removeNodePermanently": "Trajno ukloni aktivnost",
356359
"details": {
357360
"addToEditor": "Dodaj u editor",
358361
"removeFromEditor": "Ukloni iz editora",

0 commit comments

Comments
 (0)