- Implemented admin page for manual articles with fields for title, module, difficulty, tags, summary, content, steps, and relations. - Added preview functionality for markdown content. - Created list view for recent manuals with edit and view options. - Developed detail view for individual manuals displaying content, steps, and related guides. - Established database schema for manual articles, steps, and relations with appropriate indexing. - Seeded initial manual articles and steps for core functionalities. - Normalized newline characters in existing manual content. - Added additional manuals and steps for enhanced user guidance.
74 lines
3.1 KiB
PL/PgSQL
74 lines
3.1 KiB
PL/PgSQL
-- 161_manual_module.sql
|
|
-- Manual module: articles, steps and contextual relations
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE IF NOT EXISTS manual_articles (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
title VARCHAR(255) NOT NULL,
|
|
slug VARCHAR(255) NOT NULL UNIQUE,
|
|
content TEXT NOT NULL,
|
|
summary TEXT,
|
|
module VARCHAR(80) NOT NULL,
|
|
tags JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
difficulty VARCHAR(20) NOT NULL DEFAULT 'beginner' CHECK (difficulty IN ('beginner', 'advanced')),
|
|
use_count INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
deleted_at TIMESTAMP WITH TIME ZONE DEFAULT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS manual_steps (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
manual_id UUID NOT NULL REFERENCES manual_articles(id) ON DELETE CASCADE,
|
|
step_number INTEGER NOT NULL CHECK (step_number > 0),
|
|
title VARCHAR(255) NOT NULL,
|
|
content TEXT NOT NULL,
|
|
image_url TEXT,
|
|
video_url TEXT,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE (manual_id, step_number)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS manual_relations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
manual_id UUID NOT NULL REFERENCES manual_articles(id) ON DELETE CASCADE,
|
|
related_module VARCHAR(80),
|
|
related_tag VARCHAR(120),
|
|
related_sag_type VARCHAR(120),
|
|
related_manual_id UUID REFERENCES manual_articles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_module ON manual_articles(module);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_difficulty ON manual_articles(difficulty);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_deleted_at ON manual_articles(deleted_at);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_use_count ON manual_articles(use_count DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_steps_manual_id_step ON manual_steps(manual_id, step_number);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_manual_id ON manual_relations(manual_id);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_related_module ON manual_relations(related_module);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_related_tag ON manual_relations(related_tag);
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_related_sag_type ON manual_relations(related_sag_type);
|
|
|
|
-- Keep article updated_at fresh on content changes.
|
|
CREATE OR REPLACE FUNCTION bump_manual_article_updated_at()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_manual_articles_updated_at ON manual_articles;
|
|
CREATE TRIGGER trg_manual_articles_updated_at
|
|
BEFORE UPDATE ON manual_articles
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION bump_manual_article_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trg_manual_steps_updated_at ON manual_steps;
|
|
CREATE TRIGGER trg_manual_steps_updated_at
|
|
BEFORE UPDATE ON manual_steps
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION bump_manual_article_updated_at();
|