update from mon table to hirarch. table
This commit is contained in:
5
api/drizzle.config.ts
Normal file
5
api/drizzle.config.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { defineConfig } from 'drizzle-kit';
|
||||
export default defineConfig({
|
||||
dialect: 'postgresql', // 'mysql' | 'sqlite' | 'turso'
|
||||
schema: './src/db/schema.ts',
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { relations } from 'drizzle-orm';
|
||||
import * as t from 'drizzle-orm/pg-core';
|
||||
import { pgEnum, pgTable as table } from 'drizzle-orm/pg-core';
|
||||
|
||||
@@ -24,10 +25,75 @@ export const deck = table(
|
||||
inserted: t.timestamp('inserted', { mode: 'date' }).defaultNow(),
|
||||
updated: t.timestamp('updated', { mode: 'date' }).defaultNow(),
|
||||
},
|
||||
table => [t.uniqueIndex('deck_idx').on(table.id)],
|
||||
(table) => [t.uniqueIndex('deck_idx').on(table.id)],
|
||||
);
|
||||
export type InsertDeck = typeof deck.$inferInsert;
|
||||
export type SelectDeck = typeof deck.$inferSelect;
|
||||
|
||||
export const decks_table = table('decks', {
|
||||
id: t.integer('id').primaryKey().generatedAlwaysAsIdentity(),
|
||||
name: t.varchar('name').notNull(),
|
||||
boxOrder: t.varchar('box_order').notNull().default('shuffle'),
|
||||
user: t.varchar('user').notNull(),
|
||||
inserted: t.timestamp('inserted', { mode: 'date' }).defaultNow(),
|
||||
updated: t.timestamp('updated', { mode: 'date' }).defaultNow(),
|
||||
});
|
||||
export type InsertDecks = typeof decks_table.$inferInsert;
|
||||
export type SelectDecks = typeof decks_table.$inferSelect;
|
||||
|
||||
export const images_table = table('images', {
|
||||
id: t.integer('id').primaryKey().generatedAlwaysAsIdentity(),
|
||||
deckId: t.integer('deck_id').references(() => decks_table.id),
|
||||
name: t.varchar('name').notNull(),
|
||||
bildid: t.varchar('bildid').notNull(),
|
||||
inserted: t.timestamp('inserted', { mode: 'date' }).defaultNow(),
|
||||
updated: t.timestamp('updated', { mode: 'date' }).defaultNow(),
|
||||
});
|
||||
export type InsertImages = typeof images_table.$inferInsert;
|
||||
export type SelectImages = typeof images_table.$inferSelect;
|
||||
|
||||
export const boxes_table = table('boxes', {
|
||||
id: t.integer('id').primaryKey().generatedAlwaysAsIdentity(),
|
||||
imageId: t.integer('image_id').references(() => images_table.id),
|
||||
x1: t.real('x1').notNull(),
|
||||
x2: t.real('x2').notNull(),
|
||||
y1: t.real('y1').notNull(),
|
||||
y2: t.real('y2').notNull(),
|
||||
due: t.integer('due'),
|
||||
ivl: t.real('ivl'),
|
||||
factor: t.real('factor'),
|
||||
reps: t.integer('reps'),
|
||||
lapses: t.integer('lapses'),
|
||||
isGraduated: t.integer('is_graduated').notNull().default(0),
|
||||
inserted: t.timestamp('inserted', { mode: 'date' }).defaultNow(),
|
||||
updated: t.timestamp('updated', { mode: 'date' }).defaultNow(),
|
||||
});
|
||||
export type InsertBoxes = typeof boxes_table.$inferInsert;
|
||||
export type SelectBoxes = typeof boxes_table.$inferSelect;
|
||||
|
||||
// Relations (optional, aber hilfreich für Abfragen)
|
||||
export const decksRelations = relations(decks_table, ({ many }) => ({
|
||||
images: many(images_table),
|
||||
}));
|
||||
|
||||
export const imagesRelations = relations(images_table, ({ one, many }) => ({
|
||||
deck: one(decks_table, {
|
||||
fields: [images_table.deckId],
|
||||
references: [decks_table.id],
|
||||
}),
|
||||
boxes: many(boxes_table),
|
||||
}));
|
||||
|
||||
export const boxesRelations = relations(boxes_table, ({ one }) => ({
|
||||
image: one(images_table, {
|
||||
fields: [boxes_table.imageId],
|
||||
references: [images_table.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
// -------------------------------------
|
||||
// USERS
|
||||
// -------------------------------------
|
||||
export const users = table(
|
||||
'users',
|
||||
{
|
||||
@@ -39,7 +105,7 @@ export const users = table(
|
||||
lastLogin: t.timestamp('lastLogin', { mode: 'date' }).defaultNow(),
|
||||
numberOfLogins: t.integer('numberOfLogins').default(1), // Neue Spalte
|
||||
},
|
||||
table => [t.uniqueIndex('users_idx').on(table.id)],
|
||||
(table) => [t.uniqueIndex('users_idx').on(table.id)],
|
||||
);
|
||||
export type InsertUser = typeof users.$inferInsert;
|
||||
export type SelectUser = typeof users.$inferSelect;
|
||||
|
||||
@@ -25,36 +25,7 @@ export class DecksController {
|
||||
async getDecks(@Request() req) {
|
||||
const user: User = req['user'];
|
||||
const entries = await this.drizzleService.getDecks(user);
|
||||
const decks = {};
|
||||
for (const entry of entries) {
|
||||
const deckname = entry.deckname!!;
|
||||
if (!decks[deckname]) {
|
||||
decks[deckname] = {
|
||||
name: deckname,
|
||||
images: [],
|
||||
};
|
||||
}
|
||||
if (entry.bildname && entry.bildid) {
|
||||
decks[deckname].images.push({
|
||||
name: entry.bildname,
|
||||
bildid: entry.bildid,
|
||||
id: entry.id,
|
||||
x1: entry.x1,
|
||||
x2: entry.x2,
|
||||
y1: entry.y1,
|
||||
y2: entry.y2,
|
||||
due: entry.due,
|
||||
ivl: entry.ivl,
|
||||
factor: entry.factor,
|
||||
reps: entry.reps,
|
||||
lapses: entry.lapses,
|
||||
isGraduated: Boolean(entry.isGraduated),
|
||||
inserted: new Date(entry.inserted!!),
|
||||
updated: new Date(entry.updated!!),
|
||||
});
|
||||
}
|
||||
}
|
||||
return Object.values(decks);
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@@ -66,43 +37,6 @@ export class DecksController {
|
||||
return this.drizzleService.createDeck(data.deckname, user);
|
||||
}
|
||||
|
||||
@Get(':deckname')
|
||||
async getDeck(@Request() req, @Param('deckname') deckname: string) {
|
||||
const user: User = req['user'];
|
||||
const entries = await this.drizzleService.getDeckByName(deckname, user);
|
||||
if (entries.length === 0) {
|
||||
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
const deck = {
|
||||
name: deckname,
|
||||
images: [] as any,
|
||||
};
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.bildname && entry.bildid) {
|
||||
deck.images.push({
|
||||
name: entry.bildname,
|
||||
bildid: entry.bildid,
|
||||
id: entry.id,
|
||||
x1: entry.x1,
|
||||
x2: entry.x2,
|
||||
y1: entry.y1,
|
||||
y2: entry.y2,
|
||||
due: entry.due,
|
||||
ivl: entry.ivl,
|
||||
factor: entry.factor,
|
||||
reps: entry.reps,
|
||||
lapses: entry.lapses,
|
||||
isGraduated: Boolean(entry.isGraduated),
|
||||
inserted: new Date(entry.inserted!!),
|
||||
updated: new Date(entry.updated!!),
|
||||
});
|
||||
}
|
||||
}
|
||||
return deck;
|
||||
}
|
||||
|
||||
@Delete(':deckname')
|
||||
async deleteDeck(@Request() req, @Param('deckname') deckname: string) {
|
||||
const user: User = req['user'];
|
||||
@@ -122,9 +56,21 @@ export class DecksController {
|
||||
);
|
||||
}
|
||||
const user: User = req['user'];
|
||||
return this.drizzleService.renameDeck(oldDeckname, data.newDeckName, user);
|
||||
return this.drizzleService.updateDeck(
|
||||
oldDeckname,
|
||||
{ newName: data.newDeckName },
|
||||
user,
|
||||
);
|
||||
}
|
||||
@Put(':oldDeckname/update')
|
||||
async updateDeck(
|
||||
@Request() req,
|
||||
@Param('oldDeckname') oldDeckname: string,
|
||||
@Body() data: { newDeckName: string; boxOrder?: 'shuffle' | 'position' },
|
||||
) {
|
||||
const user: User = req['user'];
|
||||
return this.drizzleService.updateDeck(oldDeckname, data, user);
|
||||
}
|
||||
|
||||
@Post('image')
|
||||
async updateImage(@Request() req, @Body() data: any) {
|
||||
if (!data) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,58 +76,58 @@ export class ProxyController {
|
||||
// --------------------
|
||||
// Cleanup Endpoint
|
||||
// --------------------
|
||||
@Post('cleanup')
|
||||
async cleanupEndpoint(
|
||||
@Body() data: { dryrun?: boolean },
|
||||
@Res() res: express.Response,
|
||||
) {
|
||||
try {
|
||||
const user = res.req['user']; // Benutzerinformationen aus dem Request
|
||||
// @Post('cleanup')
|
||||
// async cleanupEndpoint(
|
||||
// @Body() data: { dryrun?: boolean },
|
||||
// @Res() res: express.Response,
|
||||
// ) {
|
||||
// try {
|
||||
// const user = res.req['user']; // Benutzerinformationen aus dem Request
|
||||
|
||||
// 2. Nur Benutzer mit der spezifischen E-Mail dürfen fortfahren
|
||||
if (user.email !== 'andreas.knuth@gmail.com') {
|
||||
throw new HttpException('Zugriff verweigert.', HttpStatus.FORBIDDEN);
|
||||
}
|
||||
// // 2. Nur Benutzer mit der spezifischen E-Mail dürfen fortfahren
|
||||
// if (user.email !== 'andreas.knuth@gmail.com') {
|
||||
// throw new HttpException('Zugriff verweigert.', HttpStatus.FORBIDDEN);
|
||||
// }
|
||||
|
||||
// 1. Abrufen der distinct bildid aus der Datenbank
|
||||
const usedIds = await this.drizzleService.getDistinctBildIds(user);
|
||||
// 3. Verarbeitung des dryrun Parameters
|
||||
const dryrun = data.dryrun !== undefined ? data.dryrun : true;
|
||||
if (typeof dryrun !== 'boolean') {
|
||||
throw new HttpException(
|
||||
"'dryrun' muss ein boolescher Wert sein.",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
// // 1. Abrufen der distinct bildid aus der Datenbank
|
||||
// const usedIds = await this.drizzleService.getDistinctBildIds(user);
|
||||
// // 3. Verarbeitung des dryrun Parameters
|
||||
// const dryrun = data.dryrun !== undefined ? data.dryrun : true;
|
||||
// if (typeof dryrun !== 'boolean') {
|
||||
// throw new HttpException(
|
||||
// "'dryrun' muss ein boolescher Wert sein.",
|
||||
// HttpStatus.BAD_REQUEST,
|
||||
// );
|
||||
// }
|
||||
|
||||
// 4. Aufruf des Flask-Backend-Endpunkts
|
||||
const response = await fetch('http://localhost:5000/api/cleanup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ dryrun, usedIds }),
|
||||
});
|
||||
// // 4. Aufruf des Flask-Backend-Endpunkts
|
||||
// const response = await fetch('http://localhost:5000/api/cleanup', {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// body: JSON.stringify({ dryrun, usedIds }),
|
||||
// });
|
||||
|
||||
const result = await response.json();
|
||||
// const result = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new HttpException(
|
||||
result.error || 'Cleanup failed',
|
||||
response.status,
|
||||
);
|
||||
}
|
||||
// if (!response.ok) {
|
||||
// throw new HttpException(
|
||||
// result.error || 'Cleanup failed',
|
||||
// response.status,
|
||||
// );
|
||||
// }
|
||||
|
||||
// 5. Rückgabe der Ergebnisse an den Client
|
||||
return res.status(HttpStatus.OK).json(result);
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
'Interner Serverfehler',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
// // 5. Rückgabe der Ergebnisse an den Client
|
||||
// return res.status(HttpStatus.OK).json(result);
|
||||
// } catch (error) {
|
||||
// if (error instanceof HttpException) {
|
||||
// throw error;
|
||||
// }
|
||||
// throw new HttpException(
|
||||
// 'Interner Serverfehler',
|
||||
// HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user