mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
upload
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back
|
||||
DROP TABLE IF EXISTS club_info CASCADE;
|
||||
DROP TABLE IF EXISTS setup_info CASCADE;
|
||||
@@ -0,0 +1,33 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied
|
||||
CREATE TABLE IF NOT EXISTS setup_info (
|
||||
id SERIAL PRIMARY KEY,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
skipped_at TIMESTAMP WITH TIME ZONE,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
smtp_configured BOOLEAN NOT NULL DEFAULT false,
|
||||
club_imported BOOLEAN NOT NULL DEFAULT false
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS club_info (
|
||||
id SERIAL PRIMARY KEY,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
setup_info_id INTEGER NOT NULL REFERENCES setup_info(id) ON DELETE CASCADE,
|
||||
facr_club_id VARCHAR(255) UNIQUE NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
short_name VARCHAR(100),
|
||||
logo_url TEXT,
|
||||
primary_color VARCHAR(7),
|
||||
secondary_color VARCHAR(7),
|
||||
text_color VARCHAR(7)
|
||||
);
|
||||
|
||||
-- Create initial setup info record if it doesn't exist
|
||||
INSERT INTO setup_info (id, status, created_at, updated_at)
|
||||
SELECT 1, 'pending', NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM setup_info WHERE id = 1);
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Remove contact/location fields from settings
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS show_map_on_homepage;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS map_style;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS map_zoom_level;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS location_longitude;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS location_latitude;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS contact_email;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS contact_phone;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS contact_country;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS contact_zip;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS contact_city;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS contact_address;
|
||||
|
||||
-- Drop contacts table
|
||||
DROP TABLE IF EXISTS contacts;
|
||||
|
||||
-- Drop contact_categories table
|
||||
DROP TABLE IF EXISTS contact_categories;
|
||||
@@ -0,0 +1,48 @@
|
||||
-- Create contact_categories table
|
||||
CREATE TABLE IF NOT EXISTS contact_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
display_order INT DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_contact_categories_display_order ON contact_categories(display_order);
|
||||
CREATE INDEX idx_contact_categories_is_active ON contact_categories(is_active);
|
||||
|
||||
-- Create contacts table
|
||||
CREATE TABLE IF NOT EXISTS contacts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
category_id INT REFERENCES contact_categories(id) ON DELETE SET NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
position VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
phone VARCHAR(100),
|
||||
image_url VARCHAR(500),
|
||||
description TEXT,
|
||||
display_order INT DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_contacts_category_id ON contacts(category_id);
|
||||
CREATE INDEX idx_contacts_display_order ON contacts(display_order);
|
||||
CREATE INDEX idx_contacts_is_active ON contacts(is_active);
|
||||
|
||||
-- Add contact/location fields to settings table
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS contact_address VARCHAR(500);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS contact_city VARCHAR(255);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS contact_zip VARCHAR(20);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS contact_country VARCHAR(100);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS contact_phone VARCHAR(100);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS contact_email VARCHAR(255);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS location_latitude DECIMAL(10, 8);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS location_longitude DECIMAL(11, 8);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS map_zoom_level INT DEFAULT 15;
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS map_style VARCHAR(255);
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS show_map_on_homepage BOOLEAN DEFAULT FALSE;
|
||||
@@ -0,0 +1,9 @@
|
||||
-- Rollback visitor_events table changes
|
||||
|
||||
DROP INDEX IF EXISTS idx_visitor_events_page_path;
|
||||
DROP INDEX IF EXISTS idx_visitor_events_created_at;
|
||||
DROP INDEX IF EXISTS idx_visitor_events_event_type_created_at;
|
||||
|
||||
ALTER TABLE visitor_events DROP COLUMN IF EXISTS page_path;
|
||||
ALTER TABLE visitor_events DROP COLUMN IF EXISTS page_name;
|
||||
ALTER TABLE visitor_events DROP COLUMN IF EXISTS data;
|
||||
@@ -0,0 +1,13 @@
|
||||
-- Add new fields to visitor_events table for better analytics tracking
|
||||
|
||||
ALTER TABLE visitor_events ADD COLUMN IF NOT EXISTS page_path VARCHAR(512);
|
||||
ALTER TABLE visitor_events ADD COLUMN IF NOT EXISTS page_name VARCHAR(512);
|
||||
ALTER TABLE visitor_events ADD COLUMN IF NOT EXISTS data JSONB;
|
||||
|
||||
-- Create indexes for better query performance
|
||||
CREATE INDEX IF NOT EXISTS idx_visitor_events_page_path ON visitor_events(page_path);
|
||||
CREATE INDEX IF NOT EXISTS idx_visitor_events_created_at ON visitor_events(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_visitor_events_event_type_created_at ON visitor_events(event_type, created_at);
|
||||
|
||||
-- Copy existing 'page' data to 'page_path' if page_path is empty
|
||||
UPDATE visitor_events SET page_path = page WHERE page_path IS NULL OR page_path = '';
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Drop file tracking tables
|
||||
DROP INDEX IF EXISTS idx_file_usages_unique;
|
||||
DROP INDEX IF EXISTS idx_file_usages_entity;
|
||||
DROP INDEX IF EXISTS idx_file_usages_file_id;
|
||||
DROP TABLE IF EXISTS file_usages;
|
||||
|
||||
DROP INDEX IF EXISTS idx_uploaded_files_deleted_at;
|
||||
DROP INDEX IF EXISTS idx_uploaded_files_created_at;
|
||||
DROP INDEX IF EXISTS idx_uploaded_files_uploaded_by;
|
||||
DROP INDEX IF EXISTS idx_uploaded_files_file_path;
|
||||
DROP TABLE IF EXISTS uploaded_files;
|
||||
@@ -0,0 +1,35 @@
|
||||
-- Create uploaded_files table to track all uploaded files
|
||||
CREATE TABLE IF NOT EXISTS uploaded_files (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
filename VARCHAR(255) NOT NULL,
|
||||
file_path VARCHAR(500) NOT NULL UNIQUE,
|
||||
file_url VARCHAR(500) NOT NULL,
|
||||
file_size BIGINT NOT NULL DEFAULT 0,
|
||||
mime_type VARCHAR(100),
|
||||
uploaded_by_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
-- Create index for faster lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_uploaded_files_file_path ON uploaded_files(file_path);
|
||||
CREATE INDEX IF NOT EXISTS idx_uploaded_files_uploaded_by ON uploaded_files(uploaded_by_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_uploaded_files_created_at ON uploaded_files(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_uploaded_files_deleted_at ON uploaded_files(deleted_at);
|
||||
|
||||
-- Create file_usages table to track where files are used
|
||||
CREATE TABLE IF NOT EXISTS file_usages (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
file_id BIGINT NOT NULL REFERENCES uploaded_files(id) ON DELETE CASCADE,
|
||||
entity_type VARCHAR(100) NOT NULL, -- e.g., 'article', 'player', 'sponsor', 'event', 'contact', 'settings'
|
||||
entity_id BIGINT NOT NULL,
|
||||
field_name VARCHAR(100), -- e.g., 'image_url', 'logo_url', 'attachments'
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create indexes for file usage tracking
|
||||
CREATE INDEX IF NOT EXISTS idx_file_usages_file_id ON file_usages(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_file_usages_entity ON file_usages(entity_type, entity_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_file_usages_unique ON file_usages(file_id, entity_type, entity_id, field_name);
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS page_element_configs;
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Create page_element_configs table for storing visual element variant preferences
|
||||
CREATE TABLE IF NOT EXISTS page_element_configs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
page_type VARCHAR(50) NOT NULL,
|
||||
element_name VARCHAR(100) NOT NULL,
|
||||
variant VARCHAR(50) NOT NULL,
|
||||
visible BOOLEAN DEFAULT true,
|
||||
display_order INTEGER DEFAULT 0,
|
||||
settings JSONB,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
UNIQUE(page_type, element_name)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_page_element_configs_page_type ON page_element_configs(page_type);
|
||||
CREATE INDEX idx_page_element_configs_element_name ON page_element_configs(element_name);
|
||||
@@ -0,0 +1,25 @@
|
||||
-- Drop triggers
|
||||
DROP TRIGGER IF EXISTS trigger_polls_updated_at ON polls;
|
||||
DROP TRIGGER IF EXISTS trigger_poll_options_updated_at ON poll_options;
|
||||
DROP FUNCTION IF EXISTS update_polls_updated_at();
|
||||
|
||||
-- Drop indexes
|
||||
DROP INDEX IF EXISTS idx_polls_status;
|
||||
DROP INDEX IF EXISTS idx_polls_featured;
|
||||
DROP INDEX IF EXISTS idx_polls_start_date;
|
||||
DROP INDEX IF EXISTS idx_polls_end_date;
|
||||
DROP INDEX IF EXISTS idx_polls_deleted_at;
|
||||
|
||||
DROP INDEX IF EXISTS idx_poll_options_poll_id;
|
||||
DROP INDEX IF EXISTS idx_poll_options_display_order;
|
||||
|
||||
DROP INDEX IF EXISTS idx_poll_votes_poll_id;
|
||||
DROP INDEX IF EXISTS idx_poll_votes_option_id;
|
||||
DROP INDEX IF EXISTS idx_poll_votes_user_id;
|
||||
DROP INDEX IF EXISTS idx_poll_votes_ip_hash;
|
||||
DROP INDEX IF EXISTS idx_poll_votes_session_token;
|
||||
|
||||
-- Drop tables (in reverse order of dependencies)
|
||||
DROP TABLE IF EXISTS poll_votes;
|
||||
DROP TABLE IF EXISTS poll_options;
|
||||
DROP TABLE IF EXISTS polls;
|
||||
@@ -0,0 +1,85 @@
|
||||
-- Create polls table
|
||||
CREATE TABLE IF NOT EXISTS polls (
|
||||
id SERIAL PRIMARY KEY,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
type VARCHAR(50) NOT NULL DEFAULT 'single',
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'draft',
|
||||
start_date TIMESTAMP,
|
||||
end_date TIMESTAMP,
|
||||
allow_multiple BOOLEAN DEFAULT FALSE,
|
||||
max_choices INTEGER DEFAULT 1,
|
||||
show_results VARCHAR(20) DEFAULT 'after_vote',
|
||||
require_auth BOOLEAN DEFAULT FALSE,
|
||||
allow_guest_vote BOOLEAN DEFAULT TRUE,
|
||||
featured BOOLEAN DEFAULT FALSE,
|
||||
category_id INTEGER REFERENCES categories(id) ON DELETE SET NULL,
|
||||
related_match_id INTEGER,
|
||||
image_url VARCHAR(500),
|
||||
total_votes INTEGER DEFAULT 0,
|
||||
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create poll_options table
|
||||
CREATE TABLE IF NOT EXISTS poll_options (
|
||||
id SERIAL PRIMARY KEY,
|
||||
poll_id INTEGER NOT NULL REFERENCES polls(id) ON DELETE CASCADE,
|
||||
text VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
image_url VARCHAR(500),
|
||||
display_order INTEGER DEFAULT 0,
|
||||
vote_count INTEGER DEFAULT 0,
|
||||
player_id INTEGER REFERENCES players(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create poll_votes table
|
||||
CREATE TABLE IF NOT EXISTS poll_votes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
poll_id INTEGER NOT NULL REFERENCES polls(id) ON DELETE CASCADE,
|
||||
option_id INTEGER NOT NULL REFERENCES poll_options(id) ON DELETE CASCADE,
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
ip_hash VARCHAR(64),
|
||||
user_agent VARCHAR(500),
|
||||
session_token VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_status ON polls(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_featured ON polls(featured);
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_start_date ON polls(start_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_end_date ON polls(end_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_deleted_at ON polls(deleted_at);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_options_poll_id ON poll_options(poll_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_options_display_order ON poll_options(display_order);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_poll_id ON poll_votes(poll_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_option_id ON poll_votes(option_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_user_id ON poll_votes(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_ip_hash ON poll_votes(ip_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_session_token ON poll_votes(session_token);
|
||||
|
||||
-- Add trigger for updated_at
|
||||
CREATE OR REPLACE FUNCTION update_polls_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trigger_polls_updated_at
|
||||
BEFORE UPDATE ON polls
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_polls_updated_at();
|
||||
|
||||
CREATE TRIGGER trigger_poll_options_updated_at
|
||||
BEFORE UPDATE ON poll_options
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_polls_updated_at();
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Remove visibility and display order columns
|
||||
DROP INDEX IF EXISTS idx_page_element_configs_display_order;
|
||||
ALTER TABLE page_element_configs DROP COLUMN IF EXISTS visible;
|
||||
ALTER TABLE page_element_configs DROP COLUMN IF EXISTS display_order;
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Add visibility and display order columns to page_element_configs
|
||||
ALTER TABLE page_element_configs ADD COLUMN IF NOT EXISTS visible BOOLEAN DEFAULT true;
|
||||
ALTER TABLE page_element_configs ADD COLUMN IF NOT EXISTS display_order INTEGER DEFAULT 0;
|
||||
|
||||
-- Create index on display_order for faster sorting
|
||||
CREATE INDEX IF NOT EXISTS idx_page_element_configs_display_order ON page_element_configs(display_order);
|
||||
@@ -0,0 +1,9 @@
|
||||
-- Drop indexes
|
||||
DROP INDEX IF EXISTS idx_polls_related_article_id;
|
||||
DROP INDEX IF EXISTS idx_polls_related_event_id;
|
||||
DROP INDEX IF EXISTS idx_polls_related_video_url;
|
||||
|
||||
-- Remove relationship columns
|
||||
ALTER TABLE polls DROP COLUMN IF EXISTS related_article_id;
|
||||
ALTER TABLE polls DROP COLUMN IF EXISTS related_event_id;
|
||||
ALTER TABLE polls DROP COLUMN IF EXISTS related_video_url;
|
||||
@@ -0,0 +1,14 @@
|
||||
-- Add relationship fields to polls table
|
||||
ALTER TABLE polls ADD COLUMN IF NOT EXISTS related_article_id INTEGER REFERENCES articles(id) ON DELETE SET NULL;
|
||||
ALTER TABLE polls ADD COLUMN IF NOT EXISTS related_event_id INTEGER REFERENCES events(id) ON DELETE SET NULL;
|
||||
ALTER TABLE polls ADD COLUMN IF NOT EXISTS related_video_url VARCHAR(500);
|
||||
|
||||
-- Create indexes for better query performance
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_related_article_id ON polls(related_article_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_related_event_id ON polls(related_event_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_related_video_url ON polls(related_video_url);
|
||||
|
||||
-- Add comments for documentation
|
||||
COMMENT ON COLUMN polls.related_article_id IS 'Link poll to a blog article';
|
||||
COMMENT ON COLUMN polls.related_event_id IS 'Link poll to an event/activity';
|
||||
COMMENT ON COLUMN polls.related_video_url IS 'Link poll to a YouTube video URL or ID';
|
||||
@@ -0,0 +1,4 @@
|
||||
-- +goose Down
|
||||
-- Remove font configuration fields from settings table
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS font_heading;
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS font_body;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- +goose Up
|
||||
-- Add font configuration fields to settings table
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS font_heading VARCHAR(255) DEFAULT '';
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS font_body VARCHAR(255) DEFAULT '';
|
||||
|
||||
-- Set default values for existing records
|
||||
UPDATE settings SET font_heading = 'Inter' WHERE font_heading IS NULL OR font_heading = '';
|
||||
UPDATE settings SET font_body = 'Inter' WHERE font_body IS NULL OR font_body = '';
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Remove finished_match_display_days column from settings table
|
||||
ALTER TABLE settings DROP COLUMN IF EXISTS finished_match_display_days;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add finished_match_display_days column to settings table
|
||||
ALTER TABLE settings ADD COLUMN IF NOT EXISTS finished_match_display_days INTEGER DEFAULT 2;
|
||||
@@ -0,0 +1,58 @@
|
||||
-- Rollback performance indexes
|
||||
|
||||
-- Articles indexes
|
||||
DROP INDEX IF EXISTS idx_articles_published_date;
|
||||
DROP INDEX IF EXISTS idx_articles_slug;
|
||||
DROP INDEX IF EXISTS idx_articles_category;
|
||||
DROP INDEX IF EXISTS idx_articles_author;
|
||||
DROP INDEX IF EXISTS idx_articles_featured;
|
||||
DROP INDEX IF EXISTS idx_articles_search;
|
||||
DROP INDEX IF EXISTS idx_articles_category_published;
|
||||
DROP INDEX IF EXISTS idx_articles_author_published;
|
||||
DROP INDEX IF EXISTS idx_articles_published_only;
|
||||
DROP INDEX IF EXISTS idx_articles_unpublished_only;
|
||||
|
||||
-- Players indexes
|
||||
DROP INDEX IF EXISTS idx_players_team;
|
||||
DROP INDEX IF EXISTS idx_players_position;
|
||||
DROP INDEX IF EXISTS idx_players_active;
|
||||
DROP INDEX IF EXISTS idx_players_name;
|
||||
|
||||
-- Users indexes
|
||||
DROP INDEX IF EXISTS idx_users_email;
|
||||
DROP INDEX IF EXISTS idx_users_role;
|
||||
DROP INDEX IF EXISTS idx_users_created;
|
||||
|
||||
-- Categories indexes
|
||||
DROP INDEX IF EXISTS idx_categories_name;
|
||||
|
||||
-- Newsletter indexes
|
||||
DROP INDEX IF EXISTS idx_newsletter_email;
|
||||
DROP INDEX IF EXISTS idx_newsletter_active;
|
||||
|
||||
-- Contact messages indexes
|
||||
DROP INDEX IF EXISTS idx_contact_messages_created;
|
||||
DROP INDEX IF EXISTS idx_contact_messages_read;
|
||||
|
||||
-- Polls indexes
|
||||
DROP INDEX IF EXISTS idx_polls_active;
|
||||
DROP INDEX IF EXISTS idx_poll_votes_poll;
|
||||
DROP INDEX IF EXISTS idx_poll_votes_user;
|
||||
|
||||
-- Match overrides indexes
|
||||
DROP INDEX IF EXISTS idx_match_overrides_external;
|
||||
|
||||
-- Team logo overrides indexes
|
||||
DROP INDEX IF EXISTS idx_team_logo_external;
|
||||
|
||||
-- Uploaded files indexes
|
||||
DROP INDEX IF EXISTS idx_uploaded_files_user;
|
||||
DROP INDEX IF EXISTS idx_uploaded_files_created;
|
||||
|
||||
-- Competition aliases indexes
|
||||
DROP INDEX IF EXISTS idx_competition_aliases_code;
|
||||
DROP INDEX IF EXISTS idx_competition_aliases_order;
|
||||
|
||||
-- Clothing indexes
|
||||
DROP INDEX IF EXISTS idx_clothing_category;
|
||||
DROP INDEX IF EXISTS idx_clothing_available;
|
||||
@@ -0,0 +1,82 @@
|
||||
-- Performance indexes for optimal query performance
|
||||
-- Run this migration to achieve 10/10 database performance
|
||||
|
||||
-- Articles table indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_published_date ON articles(published, published_at DESC) WHERE published = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_slug ON articles(slug) WHERE slug IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_category ON articles(category_id) WHERE category_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_author ON articles(author_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_featured ON articles(featured, published_at DESC) WHERE featured = true AND published = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_search ON articles USING gin(to_tsvector('english', title || ' ' || COALESCE(content, '')));
|
||||
|
||||
-- Players table indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_players_team ON players(team_id) WHERE team_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_players_position ON players(position) WHERE position IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_players_active ON players(is_active) WHERE is_active = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_players_name ON players(name);
|
||||
|
||||
-- Users table indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_created ON users(created_at DESC);
|
||||
|
||||
-- Categories table indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_name ON categories(name);
|
||||
|
||||
-- Newsletter subscriptions indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_email ON newsletter_subscriptions(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_active ON newsletter_subscriptions(is_active) WHERE is_active = true;
|
||||
|
||||
-- Contact messages indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_contact_messages_created ON contact_messages(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_contact_messages_read ON contact_messages(is_read) WHERE is_read = false;
|
||||
|
||||
-- Polls indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_polls_active ON polls(is_active, end_date) WHERE is_active = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_poll ON poll_votes(poll_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_poll_votes_user ON poll_votes(user_identifier);
|
||||
|
||||
-- Match overrides indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_match_overrides_external ON match_overrides(external_match_id);
|
||||
|
||||
-- Team logo overrides indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_team_logo_external ON team_logo_overrides(external_team_id);
|
||||
|
||||
-- Uploaded files indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_uploaded_files_user ON uploaded_files(uploaded_by_id) WHERE uploaded_by_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_uploaded_files_created ON uploaded_files(created_at DESC);
|
||||
|
||||
-- Settings table (only one row, no index needed)
|
||||
|
||||
-- Competition aliases indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_competition_aliases_code ON competition_aliases(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_competition_aliases_order ON competition_aliases(display_order) WHERE display_order > 0;
|
||||
|
||||
-- Clothing items indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_clothing_category ON clothing(category) WHERE category IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_clothing_available ON clothing(is_available) WHERE is_available = true;
|
||||
|
||||
-- Composite indexes for common queries
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_category_published ON articles(category_id, published, published_at DESC) WHERE published = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_author_published ON articles(author_id, published, published_at DESC) WHERE published = true;
|
||||
|
||||
-- Partial indexes for better performance on filtered queries
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_published_only ON articles(published_at DESC) WHERE published = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_unpublished_only ON articles(created_at DESC) WHERE published = false;
|
||||
|
||||
-- VACUUM ANALYZE to update statistics
|
||||
VACUUM ANALYZE articles;
|
||||
VACUUM ANALYZE players;
|
||||
VACUUM ANALYZE users;
|
||||
VACUUM ANALYZE categories;
|
||||
VACUUM ANALYZE newsletter_subscriptions;
|
||||
VACUUM ANALYZE contact_messages;
|
||||
VACUUM ANALYZE polls;
|
||||
VACUUM ANALYZE poll_options;
|
||||
VACUUM ANALYZE poll_votes;
|
||||
|
||||
-- Add comments for documentation
|
||||
COMMENT ON INDEX idx_articles_published_date IS 'Optimizes published articles listing';
|
||||
COMMENT ON INDEX idx_articles_search IS 'Full-text search on articles';
|
||||
COMMENT ON INDEX idx_players_team IS 'Player queries by team';
|
||||
COMMENT ON INDEX idx_newsletter_active IS 'Active subscriber queries';
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Drop triggers first to avoid dependency issues
|
||||
DROP TRIGGER IF EXISTS update_contact_messages_updated_at ON contact_messages;
|
||||
DROP TRIGGER IF EXISTS update_newsletter_subscriptions_updated_at ON newsletter_subscriptions;
|
||||
|
||||
-- Drop the function
|
||||
DROP FUNCTION IF EXISTS update_updated_at_column();
|
||||
|
||||
-- Drop indexes
|
||||
DROP INDEX IF EXISTS idx_contact_messages_email;
|
||||
DROP INDEX IF EXISTS idx_contact_messages_created_at;
|
||||
DROP INDEX IF EXISTS idx_contact_messages_is_read;
|
||||
DROP INDEX IF EXISTS idx_newsletter_subscriptions_email;
|
||||
DROP INDEX IF EXISTS idx_newsletter_subscriptions_is_active;
|
||||
|
||||
-- Drop tables
|
||||
DROP TABLE IF EXISTS contact_messages CASCADE;
|
||||
DROP TABLE IF EXISTS newsletter_subscriptions CASCADE;
|
||||
@@ -0,0 +1,61 @@
|
||||
-- Create contact_messages table
|
||||
CREATE TABLE IF NOT EXISTS contact_messages (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
subject VARCHAR(255) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
ip_address VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
is_read BOOLEAN DEFAULT FALSE,
|
||||
read_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
-- Create index for faster lookups on email and created_at
|
||||
CREATE INDEX IF NOT EXISTS idx_contact_messages_email ON contact_messages(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_contact_messages_created_at ON contact_messages(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_contact_messages_is_read ON contact_messages(is_read);
|
||||
|
||||
-- Create newsletter_subscriptions table
|
||||
CREATE TABLE IF NOT EXISTS newsletter_subscriptions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
-- Create index for faster lookups on email and is_active
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_subscriptions_email ON newsletter_subscriptions(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_subscriptions_is_active ON newsletter_subscriptions(is_active);
|
||||
|
||||
-- Create a function to update the updated_at column
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Create triggers to update updated_at columns
|
||||
DO $$
|
||||
BEGIN
|
||||
-- For contact_messages
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_contact_messages_updated_at') THEN
|
||||
CREATE TRIGGER update_contact_messages_updated_at
|
||||
BEFORE UPDATE ON contact_messages
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
END IF;
|
||||
|
||||
-- For newsletter_subscriptions
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_newsletter_subscriptions_updated_at') THEN
|
||||
CREATE TRIGGER update_newsletter_subscriptions_updated_at
|
||||
BEFORE UPDATE ON newsletter_subscriptions
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
END IF;
|
||||
END$$;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Remove verification code columns from password_resets table
|
||||
ALTER TABLE password_resets
|
||||
DROP COLUMN IF EXISTS verification_code,
|
||||
DROP COLUMN IF EXISTS verification_code_expires_at,
|
||||
DROP COLUMN IF EXISTS verification_attempts;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Add verification code columns to password_resets table
|
||||
ALTER TABLE password_resets
|
||||
ADD COLUMN verification_code VARCHAR(6) DEFAULT NULL,
|
||||
ADD COLUMN verification_code_expires_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
|
||||
ADD COLUMN verification_attempts INT NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Remove source column and its index
|
||||
DROP INDEX IF EXISTS idx_contact_messages_source;
|
||||
ALTER TABLE contact_messages DROP COLUMN IF EXISTS source;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Add source column to contact_messages to differentiate between contact page and sponsor page
|
||||
ALTER TABLE contact_messages ADD COLUMN IF NOT EXISTS source VARCHAR(50) DEFAULT 'contact';
|
||||
|
||||
-- Create index for faster filtering by source
|
||||
CREATE INDEX IF NOT EXISTS idx_contact_messages_source ON contact_messages(source);
|
||||
|
||||
-- Add comment for clarity
|
||||
COMMENT ON COLUMN contact_messages.source IS 'Source of the message: contact, sponsor, etc.';
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Add preferences JSONB column to newsletter_subscriptions
|
||||
ALTER TABLE newsletter_subscriptions
|
||||
ADD COLUMN IF NOT EXISTS preferences JSONB DEFAULT '{}'::jsonb;
|
||||
|
||||
-- Update trigger exists from previous migration to keep updated_at behavior (no-op here)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Add SMTP configuration columns to settings table
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN IF NOT EXISTS smtp_host VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS smtp_port INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS smtp_user VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS smtp_password TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS smtp_from VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS smtp_from_name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS smtp_encryption VARCHAR(16) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS smtp_auth BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS smtp_skip_verify BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Add optional email and phone columns to players
|
||||
ALTER TABLE players
|
||||
ADD COLUMN IF NOT EXISTS email VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS phone VARCHAR(50);
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Add 'featured' flag to articles
|
||||
ALTER TABLE articles
|
||||
ADD COLUMN IF NOT EXISTS featured BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
|
||||
-- Optional: index to query featured quickly together with published
|
||||
CREATE INDEX IF NOT EXISTS idx_articles_featured_published ON articles (featured, published);
|
||||
@@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS blog_notifications CASCADE;
|
||||
DROP TABLE IF EXISTS match_notifications CASCADE;
|
||||
DROP TABLE IF EXISTS newsletter_sent_log CASCADE;
|
||||
@@ -0,0 +1,40 @@
|
||||
-- Add newsletter sent tracking table
|
||||
CREATE TABLE IF NOT EXISTS newsletter_sent_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
newsletter_type VARCHAR(50) NOT NULL, -- weekly|match_reminder|match_result|blog_release
|
||||
subject VARCHAR(500),
|
||||
content_ids TEXT, -- JSON array of article/match IDs included
|
||||
recipients_count INT DEFAULT 0,
|
||||
sent_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_sent_log_type ON newsletter_sent_log(newsletter_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_sent_log_sent_at ON newsletter_sent_log(sent_at);
|
||||
|
||||
-- Add match notification tracking to prevent duplicate alerts
|
||||
CREATE TABLE IF NOT EXISTS match_notifications (
|
||||
id SERIAL PRIMARY KEY,
|
||||
match_id VARCHAR(255) NOT NULL, -- External FACR match ID
|
||||
notification_type VARCHAR(50) NOT NULL, -- reminder_48h|reminder_day|result
|
||||
sent_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
recipients_count INT DEFAULT 0,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(match_id, notification_type)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_match_notifications_match_id ON match_notifications(match_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_match_notifications_sent_at ON match_notifications(sent_at);
|
||||
|
||||
-- Add blog notification tracking to prevent duplicate alerts
|
||||
CREATE TABLE IF NOT EXISTS blog_notifications (
|
||||
id SERIAL PRIMARY KEY,
|
||||
article_id INT NOT NULL,
|
||||
sent_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
recipients_count INT DEFAULT 0,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(article_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_blog_notifications_article_id ON blog_notifications(article_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_blog_notifications_sent_at ON blog_notifications(sent_at);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Remove display_order column and index
|
||||
DROP INDEX IF EXISTS idx_competition_aliases_display_order;
|
||||
ALTER TABLE competition_aliases DROP COLUMN IF EXISTS display_order;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Add display_order column to competition_aliases table for custom sorting
|
||||
ALTER TABLE competition_aliases ADD COLUMN IF NOT EXISTS display_order INTEGER DEFAULT 0;
|
||||
|
||||
-- Create index for better query performance
|
||||
CREATE INDEX IF NOT EXISTS idx_competition_aliases_display_order ON competition_aliases(display_order);
|
||||
@@ -0,0 +1,14 @@
|
||||
-- Rollback contact and map fields from settings table
|
||||
|
||||
ALTER TABLE settings
|
||||
DROP COLUMN IF EXISTS contact_address,
|
||||
DROP COLUMN IF EXISTS contact_city,
|
||||
DROP COLUMN IF EXISTS contact_zip,
|
||||
DROP COLUMN IF EXISTS contact_country,
|
||||
DROP COLUMN IF EXISTS contact_phone,
|
||||
DROP COLUMN IF EXISTS contact_email,
|
||||
DROP COLUMN IF EXISTS location_latitude,
|
||||
DROP COLUMN IF EXISTS location_longitude,
|
||||
DROP COLUMN IF EXISTS map_zoom_level,
|
||||
DROP COLUMN IF EXISTS map_style,
|
||||
DROP COLUMN IF EXISTS show_map_on_homepage;
|
||||
@@ -0,0 +1,28 @@
|
||||
-- Add contact and map fields to settings table
|
||||
-- These fields enable location display and contact information on the website
|
||||
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN IF NOT EXISTS contact_address VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS contact_city VARCHAR(100),
|
||||
ADD COLUMN IF NOT EXISTS contact_zip VARCHAR(20),
|
||||
ADD COLUMN IF NOT EXISTS contact_country VARCHAR(100),
|
||||
ADD COLUMN IF NOT EXISTS contact_phone VARCHAR(50),
|
||||
ADD COLUMN IF NOT EXISTS contact_email VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS location_latitude DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS location_longitude DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS map_zoom_level INT DEFAULT 15,
|
||||
ADD COLUMN IF NOT EXISTS map_style VARCHAR(50),
|
||||
ADD COLUMN IF NOT EXISTS show_map_on_homepage BOOLEAN DEFAULT FALSE;
|
||||
|
||||
-- Add comments for documentation
|
||||
COMMENT ON COLUMN settings.contact_address IS 'Street address of the club/stadium';
|
||||
COMMENT ON COLUMN settings.contact_city IS 'City name';
|
||||
COMMENT ON COLUMN settings.contact_zip IS 'Postal/ZIP code';
|
||||
COMMENT ON COLUMN settings.contact_country IS 'Country name';
|
||||
COMMENT ON COLUMN settings.contact_phone IS 'Contact phone number';
|
||||
COMMENT ON COLUMN settings.contact_email IS 'Contact email address';
|
||||
COMMENT ON COLUMN settings.location_latitude IS 'Geographic latitude for map display';
|
||||
COMMENT ON COLUMN settings.location_longitude IS 'Geographic longitude for map display';
|
||||
COMMENT ON COLUMN settings.map_zoom_level IS 'Default zoom level for map (1-20)';
|
||||
COMMENT ON COLUMN settings.map_style IS 'Map style: default, dark, or satellite';
|
||||
COMMENT ON COLUMN settings.show_map_on_homepage IS 'Whether to display map on homepage';
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE articles
|
||||
DROP COLUMN IF EXISTS youtube_video_thumbnail,
|
||||
DROP COLUMN IF EXISTS youtube_video_url,
|
||||
DROP COLUMN IF EXISTS youtube_video_title,
|
||||
DROP COLUMN IF EXISTS youtube_video_id;
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE articles
|
||||
ADD COLUMN youtube_video_id VARCHAR(64),
|
||||
ADD COLUMN youtube_video_title TEXT,
|
||||
ADD COLUMN youtube_video_url TEXT,
|
||||
ADD COLUMN youtube_video_thumbnail TEXT;
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE articles
|
||||
DROP COLUMN IF EXISTS gallery_photo_ids,
|
||||
DROP COLUMN IF EXISTS gallery_album_url,
|
||||
DROP COLUMN IF EXISTS gallery_album_id,
|
||||
DROP COLUMN IF EXISTS og_image_url;
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE articles
|
||||
ADD COLUMN IF NOT EXISTS og_image_url TEXT,
|
||||
ADD COLUMN IF NOT EXISTS gallery_album_id TEXT,
|
||||
ADD COLUMN IF NOT EXISTS gallery_album_url TEXT,
|
||||
ADD COLUMN IF NOT EXISTS gallery_photo_ids TEXT;
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Remove custom page and navigation fields from settings
|
||||
|
||||
ALTER TABLE settings
|
||||
DROP COLUMN IF EXISTS custom_nav_json,
|
||||
DROP COLUMN IF EXISTS show_about_in_nav,
|
||||
DROP COLUMN IF EXISTS about_html;
|
||||
@@ -0,0 +1,10 @@
|
||||
-- Add custom page and navigation fields to settings
|
||||
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN IF NOT EXISTS about_html TEXT,
|
||||
ADD COLUMN IF NOT EXISTS show_about_in_nav BOOLEAN DEFAULT TRUE,
|
||||
ADD COLUMN IF NOT EXISTS custom_nav_json TEXT;
|
||||
|
||||
COMMENT ON COLUMN settings.about_html IS 'Rich HTML content for the unified custom club page';
|
||||
COMMENT ON COLUMN settings.show_about_in_nav IS 'Controls whether the custom club page appears in main navigation';
|
||||
COMMENT ON COLUMN settings.custom_nav_json IS 'Serialized custom navigation links managed via admin settings';
|
||||
@@ -0,0 +1,22 @@
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back
|
||||
|
||||
-- Drop tables
|
||||
DROP TABLE IF EXISTS social_links;
|
||||
DROP TABLE IF EXISTS navigation_items;
|
||||
|
||||
-- Remove settings columns
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'settings') THEN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'settings' AND column_name = 'custom_navigation_enabled') THEN
|
||||
ALTER TABLE settings DROP COLUMN custom_navigation_enabled;
|
||||
END IF;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'settings' AND column_name = 'show_social_in_nav') THEN
|
||||
ALTER TABLE settings DROP COLUMN show_social_in_nav;
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
@@ -0,0 +1,100 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied
|
||||
|
||||
-- Create navigation_items table for managing navigation
|
||||
CREATE TABLE IF NOT EXISTS navigation_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
-- Basic info
|
||||
label VARCHAR(255) NOT NULL,
|
||||
url TEXT,
|
||||
icon VARCHAR(100),
|
||||
|
||||
-- Type: internal, external, dropdown, page
|
||||
type VARCHAR(50) NOT NULL DEFAULT 'internal',
|
||||
|
||||
-- Page reference (for type=page): links to existing pages
|
||||
page_type VARCHAR(100), -- e.g., 'blog', 'about', 'calendar', 'players', etc.
|
||||
page_id INTEGER, -- optional reference to specific content ID
|
||||
|
||||
-- Visibility and display
|
||||
visible BOOLEAN NOT NULL DEFAULT true,
|
||||
display_order INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
-- Parent for dropdown menus
|
||||
parent_id INTEGER REFERENCES navigation_items(id) ON DELETE CASCADE,
|
||||
|
||||
-- Target
|
||||
target VARCHAR(20) DEFAULT '_self', -- _self, _blank
|
||||
|
||||
-- Styling
|
||||
css_class VARCHAR(255),
|
||||
|
||||
-- Permissions
|
||||
requires_auth BOOLEAN DEFAULT false,
|
||||
requires_admin BOOLEAN DEFAULT false
|
||||
);
|
||||
|
||||
-- Create index for ordering and parent relationships
|
||||
CREATE INDEX idx_navigation_items_order ON navigation_items(display_order);
|
||||
CREATE INDEX idx_navigation_items_parent ON navigation_items(parent_id);
|
||||
CREATE INDEX idx_navigation_items_visible ON navigation_items(visible);
|
||||
|
||||
-- Create social_links table for managing social media
|
||||
CREATE TABLE IF NOT EXISTS social_links (
|
||||
id SERIAL PRIMARY KEY,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
platform VARCHAR(50) NOT NULL, -- facebook, instagram, youtube, twitter, tiktok, etc.
|
||||
url TEXT NOT NULL,
|
||||
display_order INTEGER NOT NULL DEFAULT 0,
|
||||
visible BOOLEAN NOT NULL DEFAULT true,
|
||||
icon VARCHAR(100) -- optional custom icon
|
||||
);
|
||||
|
||||
CREATE INDEX idx_social_links_order ON social_links(display_order);
|
||||
CREATE INDEX idx_social_links_visible ON social_links(visible);
|
||||
|
||||
-- Insert default navigation items if table is empty
|
||||
INSERT INTO navigation_items (label, type, page_type, display_order, visible)
|
||||
SELECT * FROM (VALUES
|
||||
('Domů', 'page', 'home', 0, true),
|
||||
('O klubu', 'page', 'about', 1, true),
|
||||
('Kalendář', 'page', 'calendar', 2, true),
|
||||
('Zápasy', 'page', 'matches', 3, true),
|
||||
('Aktivity', 'page', 'activities', 4, true),
|
||||
('Hráči', 'page', 'players', 5, true),
|
||||
('Tabulky', 'page', 'tables', 6, true),
|
||||
('Články', 'page', 'blog', 7, true),
|
||||
('Videa', 'page', 'videos', 8, true),
|
||||
('Fotogalerie', 'page', 'gallery', 9, true),
|
||||
('Sponzoři', 'page', 'sponsors', 10, true),
|
||||
('Kontakt', 'page', 'contact', 11, true)
|
||||
) AS default_nav(label, type, page_type, display_order, visible)
|
||||
WHERE NOT EXISTS (SELECT 1 FROM navigation_items);
|
||||
|
||||
-- Migrate existing social links from settings if they exist
|
||||
-- This will be handled in application code as we don't want to directly access settings table
|
||||
|
||||
-- Add navigation settings to settings table if not exists
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'settings') THEN
|
||||
-- Add column for navigation customization enabled
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'settings' AND column_name = 'custom_navigation_enabled') THEN
|
||||
ALTER TABLE settings ADD COLUMN custom_navigation_enabled BOOLEAN DEFAULT false;
|
||||
END IF;
|
||||
|
||||
-- Add column for showing social links in nav
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'settings' AND column_name = 'show_social_in_nav') THEN
|
||||
ALTER TABLE settings ADD COLUMN show_social_in_nav BOOLEAN DEFAULT true;
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Drop clothing table
|
||||
DROP INDEX IF EXISTS idx_clothing_created_at;
|
||||
DROP INDEX IF EXISTS idx_clothing_display_order;
|
||||
DROP INDEX IF EXISTS idx_clothing_active;
|
||||
DROP TABLE IF EXISTS clothing;
|
||||
@@ -0,0 +1,20 @@
|
||||
-- Create clothing table for merchandising items
|
||||
CREATE TABLE IF NOT EXISTS clothing (
|
||||
id SERIAL PRIMARY KEY,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
price DECIMAL(10, 2),
|
||||
currency VARCHAR(10) DEFAULT 'Kč',
|
||||
image_url VARCHAR(500),
|
||||
url VARCHAR(500),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
display_order INT DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create index for active items and ordering
|
||||
CREATE INDEX idx_clothing_active ON clothing(is_active);
|
||||
CREATE INDEX idx_clothing_display_order ON clothing(display_order);
|
||||
CREATE INDEX idx_clothing_created_at ON clothing(created_at);
|
||||
Reference in New Issue
Block a user