2021-03-21 20:38:37 +00:00
|
|
|
package models
|
|
|
|
|
2021-04-11 21:46:06 +00:00
|
|
|
import (
|
|
|
|
"reflect"
|
2021-11-08 19:16:54 +00:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
2021-04-11 21:46:06 +00:00
|
|
|
"time"
|
|
|
|
)
|
2021-03-31 03:55:19 +00:00
|
|
|
|
2021-05-06 04:04:58 +00:00
|
|
|
const (
|
|
|
|
HMNProjectID = 1
|
|
|
|
HMNProjectSlug = "hmn"
|
|
|
|
)
|
2021-03-21 20:38:37 +00:00
|
|
|
|
2021-03-31 03:55:19 +00:00
|
|
|
var ProjectType = reflect.TypeOf(Project{})
|
|
|
|
|
2021-05-05 20:34:32 +00:00
|
|
|
type ProjectLifecycle int
|
|
|
|
|
|
|
|
const (
|
2021-11-06 20:25:31 +00:00
|
|
|
ProjectLifecycleUnapproved ProjectLifecycle = iota
|
2021-05-05 20:34:32 +00:00
|
|
|
ProjectLifecycleApprovalRequired
|
|
|
|
ProjectLifecycleActive
|
|
|
|
ProjectLifecycleHiatus
|
|
|
|
ProjectLifecycleDead
|
|
|
|
ProjectLifecycleLTSRequired
|
|
|
|
ProjectLifecycleLTS
|
|
|
|
)
|
|
|
|
|
2021-06-06 23:48:43 +00:00
|
|
|
// NOTE(asaf): Just checking the lifecycle is not sufficient. Visible projects also must have flags = 0.
|
|
|
|
var VisibleProjectLifecycles = []ProjectLifecycle{
|
|
|
|
ProjectLifecycleActive,
|
|
|
|
ProjectLifecycleHiatus,
|
|
|
|
ProjectLifecycleLTSRequired, // NOTE(asaf): LTS means complete
|
|
|
|
ProjectLifecycleLTS,
|
|
|
|
}
|
|
|
|
|
|
|
|
const RecentProjectUpdateTimespanSec = 60 * 60 * 24 * 28 // NOTE(asaf): Four weeks
|
|
|
|
|
2021-03-21 20:38:37 +00:00
|
|
|
type Project struct {
|
|
|
|
ID int `db:"id"`
|
|
|
|
|
2021-05-11 22:53:23 +00:00
|
|
|
ForumID *int `db:"forum_id"`
|
|
|
|
|
2021-06-06 23:48:43 +00:00
|
|
|
Slug string `db:"slug"`
|
|
|
|
Name string `db:"name"`
|
2021-11-06 20:25:31 +00:00
|
|
|
Tag string `db:"tag"`
|
2021-06-06 23:48:43 +00:00
|
|
|
Blurb string `db:"blurb"`
|
|
|
|
Description string `db:"description"`
|
|
|
|
ParsedDescription string `db:"descparsed"`
|
2021-03-21 20:38:37 +00:00
|
|
|
|
2021-05-11 22:53:23 +00:00
|
|
|
Lifecycle ProjectLifecycle `db:"lifecycle"` // TODO(asaf): Ensure we only fetch projects in the correct lifecycle phase everywhere.
|
2021-05-05 20:34:32 +00:00
|
|
|
|
2021-03-21 20:38:37 +00:00
|
|
|
Color1 string `db:"color_1"`
|
|
|
|
Color2 string `db:"color_2"`
|
2021-04-11 21:46:06 +00:00
|
|
|
|
2021-05-31 23:23:04 +00:00
|
|
|
LogoLight string `db:"logolight"`
|
|
|
|
LogoDark string `db:"logodark"`
|
|
|
|
|
2021-11-06 20:25:31 +00:00
|
|
|
Personal bool `db:"personal"`
|
|
|
|
Hidden bool `db:"hidden"`
|
2021-09-09 03:44:46 +00:00
|
|
|
Featured bool `db:"featured"`
|
|
|
|
DateApproved time.Time `db:"date_approved"`
|
|
|
|
AllLastUpdated time.Time `db:"all_last_updated"`
|
|
|
|
ForumLastUpdated time.Time `db:"forum_last_updated"`
|
|
|
|
BlogLastUpdated time.Time `db:"blog_last_updated"`
|
|
|
|
AnnotationLastUpdated time.Time `db:"annotation_last_updated"`
|
2021-08-28 13:10:26 +00:00
|
|
|
|
|
|
|
ForumEnabled bool `db:"forum_enabled"`
|
|
|
|
BlogEnabled bool `db:"blog_enabled"`
|
|
|
|
LibraryEnabled bool `db:"library_enabled"`
|
2021-03-21 20:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Project) IsHMN() bool {
|
|
|
|
return p.ID == HMNProjectID
|
|
|
|
}
|
2021-04-22 23:02:50 +00:00
|
|
|
|
|
|
|
func (p *Project) Subdomain() string {
|
|
|
|
if p.IsHMN() {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2021-05-06 04:04:58 +00:00
|
|
|
return p.Slug
|
2021-04-22 23:02:50 +00:00
|
|
|
}
|
2021-11-08 19:16:54 +00:00
|
|
|
|
|
|
|
var slugUnsafeChars = regexp.MustCompile(`[^a-zA-Z0-9-]`)
|
|
|
|
var slugHyphenRun = regexp.MustCompile(`-+`)
|
|
|
|
|
|
|
|
// Generates a URL-safe version of a personal project's name.
|
|
|
|
func GeneratePersonalProjectSlug(name string) string {
|
|
|
|
slug := name
|
|
|
|
slug = slugUnsafeChars.ReplaceAllLiteralString(slug, "-")
|
|
|
|
slug = slugHyphenRun.ReplaceAllLiteralString(slug, "-")
|
|
|
|
slug = strings.Trim(slug, "-")
|
|
|
|
slug = strings.ToLower(slug)
|
|
|
|
|
|
|
|
return slug
|
|
|
|
}
|