Enable management of media outlet articles including creation, editing, and deletion

Adds article management functionality to media outlets, including API endpoints for creating, updating, and deleting articles, and integrates these features into the client-side UI with dialogs and mutations.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9a264234-c5d7-4dcc-adf3-a954b149b30d
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/9a264234-c5d7-4dcc-adf3-a954b149b30d/QTw0kIA
This commit is contained in:
kimjaehyeon0101
2025-10-14 10:01:14 +00:00
parent 4f0b4c7e1d
commit 3829c9bc87
4 changed files with 370 additions and 15 deletions

View File

@ -152,6 +152,49 @@ export async function registerRoutes(app: Express): Promise<Server> {
}
});
app.patch('/api/articles/:id', isAuthenticated, async (req: any, res) => {
try {
const user = req.user;
if (!user || (user.role !== 'admin' && user.role !== 'superadmin')) {
return res.status(403).json({ message: "Insufficient permissions" });
}
const article = await storage.getArticleById(req.params.id);
if (!article) {
return res.status(404).json({ message: "Article not found" });
}
const articleData = insertArticleSchema.partial().parse(req.body);
const updated = await storage.updateArticle(req.params.id, articleData);
res.json(updated);
} catch (error) {
console.error("Error updating article:", error);
res.status(500).json({ message: "Failed to update article" });
}
});
app.delete('/api/articles/:id', isAuthenticated, async (req: any, res) => {
try {
const user = req.user;
if (!user || (user.role !== 'admin' && user.role !== 'superadmin')) {
return res.status(403).json({ message: "Insufficient permissions" });
}
const article = await storage.getArticleById(req.params.id);
if (!article) {
return res.status(404).json({ message: "Article not found" });
}
await storage.deleteArticle(req.params.id);
res.status(204).send();
} catch (error) {
console.error("Error deleting article:", error);
res.status(500).json({ message: "Failed to delete article" });
}
});
// Prediction market routes
app.get('/api/prediction-markets', async (req, res) => {
try {

View File

@ -52,8 +52,10 @@ export interface IStorage {
getArticles(): Promise<Article[]>;
getArticlesByOutlet(mediaOutletId: string): Promise<Article[]>;
getArticleBySlug(slug: string): Promise<Article | undefined>;
getArticleById(id: string): Promise<Article | undefined>;
createArticle(article: InsertArticle): Promise<Article>;
updateArticle(id: string, article: Partial<InsertArticle>): Promise<Article>;
deleteArticle(id: string): Promise<void>;
getFeaturedArticles(limit?: number): Promise<Article[]>;
// Prediction market operations
@ -205,6 +207,15 @@ export class DatabaseStorage implements IStorage {
.orderBy(desc(articles.publishedAt))
.limit(limit);
}
async getArticleById(id: string): Promise<Article | undefined> {
const [article] = await db.select().from(articles).where(eq(articles.id, id));
return article;
}
async deleteArticle(id: string): Promise<void> {
await db.delete(articles).where(eq(articles.id, id));
}
// Prediction market operations
async getPredictionMarkets(articleId?: string): Promise<PredictionMarket[]> {