feat: add project icon picker component and integrate with project management
- Implemented ProjectIconPicker component for selecting project icons. - Created ProjectIcon component to display selected icons. - Updated calendar page to remove unused PageHeading component. - Modified growth page to enhance UI and improve text clarity. - Refactored index page to include project icons and improve layout. - Added mine page for user profile management with avatar selection. - Introduced projects-sort page for managing project order with drag-and-drop functionality. - Enhanced projects page to allow icon selection when adding or editing projects. - Updated record page to streamline user experience and improve form actions. - Adjusted practice service to support project icon management. - Added tests for project saving functionality to ensure correct handling of icons. - Updated global type definitions to support SVG and PNG imports.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
ALTER TABLE projects ADD COLUMN icon_id text NOT NULL DEFAULT '' CHECK (char_length(icon_id) <= 64);
|
||||
|
||||
-- Existing installations have never offered icon selection. Seed familiar names
|
||||
-- once; subsequent migrations/logins must preserve explicit changes or removal.
|
||||
UPDATE projects SET icon_id = CASE name
|
||||
WHEN '零基础' THEN 'plie'
|
||||
WHEN '基础提升' THEN 'tendu'
|
||||
WHEN '软开素质' THEN 'flexibility'
|
||||
WHEN '足髋训练' THEN 'foot-hip'
|
||||
WHEN '核心臀腿' THEN 'core-glutes'
|
||||
WHEN '小球核心' THEN 'ball-core'
|
||||
WHEN '天鹅臂颈' THEN 'swan-arms'
|
||||
WHEN '呼吸训练' THEN 'breathing'
|
||||
ELSE ''
|
||||
END;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Keep identity allocation for new projects while allowing owned projects to swap positions.
|
||||
ALTER TABLE projects ALTER COLUMN position SET GENERATED BY DEFAULT;
|
||||
@@ -11,6 +11,12 @@ import (
|
||||
//go:embed 001_practice.sql
|
||||
var practiceSQL string
|
||||
|
||||
//go:embed 002_project_icons.sql
|
||||
var projectIconsSQL string
|
||||
|
||||
//go:embed 003_project_order.sql
|
||||
var projectOrderSQL string
|
||||
|
||||
// Migrate applies versioned migrations atomically. A transaction-scoped lock keeps
|
||||
// concurrent service starts from applying the same version twice.
|
||||
func Migrate(ctx context.Context, pool *pgxpool.Pool) error {
|
||||
@@ -25,17 +31,20 @@ func Migrate(ctx context.Context, pool *pgxpool.Pool) error {
|
||||
if _, err = tx.Exec(ctx, "CREATE TABLE IF NOT EXISTS schema_migrations (version integer PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now())"); err != nil {
|
||||
return err
|
||||
}
|
||||
var applied bool
|
||||
if err = tx.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM schema_migrations WHERE version=1)").Scan(&applied); err != nil {
|
||||
return err
|
||||
}
|
||||
if !applied {
|
||||
if _, err = tx.Exec(ctx, practiceSQL); err != nil {
|
||||
return fmt.Errorf("migration 1: %w", err)
|
||||
}
|
||||
if _, err = tx.Exec(ctx, "INSERT INTO schema_migrations(version) VALUES (1)"); err != nil {
|
||||
for i, sql := range []string{practiceSQL, projectIconsSQL, projectOrderSQL} {
|
||||
version := i + 1
|
||||
var applied bool
|
||||
if err = tx.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM schema_migrations WHERE version=$1)", version).Scan(&applied); err != nil {
|
||||
return err
|
||||
}
|
||||
if !applied {
|
||||
if _, err = tx.Exec(ctx, sql); err != nil {
|
||||
return fmt.Errorf("migration %d: %w", version, err)
|
||||
}
|
||||
if _, err = tx.Exec(ctx, "INSERT INTO schema_migrations(version) VALUES ($1)", version); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user