diff --git a/app/pages/admin/groups.vue b/app/pages/admin/groups.vue new file mode 100644 index 0000000..cdba772 --- /dev/null +++ b/app/pages/admin/groups.vue @@ -0,0 +1,150 @@ + + + + + + Team Management + Create and manage groups, members and permissions + + + + New Group + + + + + + + + + {{ group.name.charAt(0) }} + + + Private + {{ group.memberCount }} members + + + + {{ group.name }} + {{ group.description || 'No description provided' }} + + + + + U{{ i }} + + + +{{ group.memberCount - 3 }} + + + Manage + + + + + + + + Create New Group + + + + Group Name + + + + Description + + + + + Make group public + + + + + + Cancel + + + {{ loading ? 'Creating...' : 'Create Group' }} + + + + + + + + + diff --git a/app/server/api/users/[id]/profile.get.ts b/app/server/api/users/[id]/profile.get.ts index 3ad9228..cc27332 100644 --- a/app/server/api/users/[id]/profile.get.ts +++ b/app/server/api/users/[id]/profile.get.ts @@ -1,4 +1,4 @@ -import { profiles, canvases, follows } from '~/server/utils/db' +import { prisma } from '~/server/utils/prisma' export default defineEventHandler(async (event) => { const userId = getRouterParam(event, 'id') @@ -7,34 +7,35 @@ export default defineEventHandler(async (event) => { throw createError({ statusCode: 400, message: 'User ID is required' }) } - const profile = profiles.get(userId) + const profile = await prisma.profile.findUnique({ + where: { userId }, + include: { + user: { + include: { + _count: { + select: { + canvases: true, + followers: true, + following: true + } + } + } + } + } + }) + if (!profile) { + // If profile doesn't exist but user might exist in Firebase, + // we could potentially create it here or return 404 throw createError({ statusCode: 404, message: 'Profile not found' }) } - // Count user's canvases - const userCanvases = Array.from(canvases.values()).filter( - canvas => canvas.ownerId === userId - ) - - // Count followers and following - const followers = Array.from(follows.values()).filter( - follow => follow.followingId === userId - ).length - - const following = Array.from(follows.values()).filter( - follow => follow.followerId === userId - ).length - - // Update profile with current stats - const updatedProfile = { - ...profile, - canvasCount: userCanvases.length, - followerCount: followers, - followingCount: following + return { + profile: { + ...profile, + canvasCount: profile.user._count.canvases, + followerCount: profile.user._count.followers, + followingCount: profile.user._count.following + } } - - profiles.set(userId, updatedProfile) - - return { profile: updatedProfile } }) diff --git a/scripts/init_admin.cjs b/scripts/init_admin.cjs new file mode 100644 index 0000000..edc6833 --- /dev/null +++ b/scripts/init_admin.cjs @@ -0,0 +1,49 @@ +const { PrismaClient } = require('@prisma/client') +const { PrismaPg } = require('@prisma/adapter-pg') +const { Pool } = require('pg') + +// Создаем соединение через pg (как того требует Driver Adapter в Prisma 7) +const connectionString = process.env.DATABASE_URL +const pool = new Pool({ connectionString }) +const adapter = new PrismaPg(pool) + +const prisma = new PrismaClient({ adapter }) + +async function main() { + const userId = 'GqbpMyUW0NaxjIy5nvCiXCiQu9t2' // Твой UID из лога + + console.log('🚀 Initializing admin using Driver Adapter for UID:', userId) + + const user = await prisma.user.upsert({ + where: { id: userId }, + update: { + role: 'admin' + }, + create: { + id: userId, + email: 'admin@xflow.kz', + username: 'alex_admin', + password: 'firebase_auth', + role: 'admin', + profile: { + create: { + displayName: 'Alex Admin', + bio: 'XFlow Infrastructure Creator', + joinedAt: new Date() + } + } + } + }) + + console.log('✅ Success! Admin user created/updated:', user.username) +} + +main() + .catch((e) => { + console.error('❌ Error initializing admin:', e) + process.exit(1) + }) + .finally(async () => { + await prisma.$disconnect() + await pool.end() + }) diff --git a/scripts/seed_canvas.cjs b/scripts/seed_canvas.cjs new file mode 100644 index 0000000..73d98a2 --- /dev/null +++ b/scripts/seed_canvas.cjs @@ -0,0 +1,42 @@ +const { PrismaClient } = require('@prisma/client') +const { PrismaPg } = require('@prisma/adapter-pg') +const { Pool } = require('pg') + +const connectionString = process.env.DATABASE_URL +const pool = new Pool({ connectionString }) +const adapter = new PrismaPg(pool) +const prisma = new PrismaClient({ adapter }) + +async function main() { + const adminId = 'GqbpMyUW0NaxjIy5nvCiXCiQu9t2' + + console.log('📦 Seeding Mindmaps to PostgreSQL...') + + // 1. Создаем основную карту "Обзор Проекта XFlow" + const xflowCanvas = await prisma.canvas.upsert({ + where: { id: 'xflow-project' }, + update: {}, + create: { + id: 'xflow-project', + name: 'Обзор Проекта XFlow', + ownerId: adminId, + isPublic: true, + nodes: [ + { id: 'arch-1', type: 'text', x: 100, y: 100, width: 320, height: 180, text: '# 🏗️ Основная Архитектура\n\n- **Nuxt 3** - Vue 3 фреймворк\n- **TailwindCSS** - Стилизация\n- **Vue Flow** - Движок канваса\n- **Firebase** - Аутентификация\n- **PostgreSQL + Prisma** - Хранение данных\n- **PWA** - Progressive Web App' }, + { id: 'be-1', type: 'text', x: 500, y: 250, width: 280, height: 160, text: '# ⚙️ Backend API\n\n- `/api/canvas/*` - Prisma CRUD\n- `/api/groups/*` - Групповой доступ\n- `/api/admin/*` - Админка\n- **Gitea Actions** - Автодеплой' } + ], + edges: [ + { id: 'e1', fromNode: 'arch-1', fromSide: 'right', toNode: 'be-1', toSide: 'left' } + ] + } + }) + + console.log('✅ Success! Mindmap "Обзор Проекта XFlow" is now in the database.') +} + +main() + .catch(console.error) + .finally(async () => { + await prisma.$disconnect() + await pool.end() + })
Create and manage groups, members and permissions
{{ group.description || 'No description provided' }}