sync: Add partner's info

This commit is contained in:
nemunaire 2021-09-01 10:15:26 +02:00
parent f2bf07fd28
commit 74d77dce9f
6 changed files with 105 additions and 31 deletions

View File

@ -1405,7 +1405,7 @@ angular.module("FICApp")
}) })
.controller("ThemeController", function($scope, Theme, $routeParams, $location, $rootScope, $http) { .controller("ThemeController", function($scope, Theme, $routeParams, $location, $rootScope, $http) {
$scope.theme = Theme.get({ themeId: $routeParams.themeId }); $scope.theme = Theme.get({ themeId: $routeParams.themeId });
$scope.fields = ["name", "urlid", "authors", "headline", "intro", "image"]; $scope.fields = ["name", "urlid", "authors", "headline", "intro", "image", "partner_txt", "partner_href", "partner_img"];
$scope.saveTheme = function() { $scope.saveTheme = function() {
if (this.theme.id) { if (this.theme.id) {

View File

@ -153,6 +153,22 @@ func BuildTheme(i Importer, tdir string) (th *fic.Theme, errs []string) {
errs = append(errs, fmt.Sprintf("%q: heading.jpg: No such file", tdir)) errs = append(errs, fmt.Sprintf("%q: heading.jpg: No such file", tdir))
} }
if i.exists(path.Join(tdir, "partner.jpg")) {
th.PartnerImage = path.Join(tdir, "partner.jpg")
} else if i.exists(path.Join(tdir, "partner.png")) {
th.PartnerImage = path.Join(tdir, "partner.png")
}
if i.exists(path.Join(tdir, "partner.txt")) {
if txt, err := getFileContent(i, path.Join(tdir, "partner.txt")); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to get partner's text: %s", th.Name, err))
} else {
th.PartnerText, err = ProcessMarkdown(i, txt, tdir)
if err != nil {
errs = append(errs, fmt.Sprintf("%q: partner.txt: an error occurs during markdown formating: %s", tdir, err))
}
}
}
return return
} }
@ -189,6 +205,16 @@ func SyncThemes(i Importer) []string {
} }
} }
if len(btheme.PartnerImage) > 0 {
if _, err := i.importFile(btheme.PartnerImage,
func(filePath string, origin string) (interface{}, error) {
btheme.PartnerImage = strings.TrimPrefix(filePath, fic.FilesDir)
return nil, nil
}); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to import partner image: %s", tdir, err))
}
}
var theme fic.Theme var theme fic.Theme
if theme, err = fic.GetThemeByPath(btheme.Path); err != nil { if theme, err = fic.GetThemeByPath(btheme.Path); err != nil {
if _, err := fic.CreateTheme(*btheme); err != nil { if _, err := fic.CreateTheme(*btheme); err != nil {

View File

@ -12,7 +12,13 @@
import { import {
Alert, Alert,
Badge, Badge,
Button,
Card,
CardBody,
CardTitle,
Col,
Icon, Icon,
Row,
} from 'sveltestrap'; } from 'sveltestrap';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
@ -23,12 +29,37 @@
</script> </script>
{#if theme && theme.exercices} {#if theme && theme.exercices}
<div class="card niceborder text-indent mt-2 mb-4"> <Card class="niceborder text-indent mt-2 mb-4">
<div class="card-body bg-dark text-light"> <CardBody class="bg-dark text-light">
<p class="mt-4 mx-3 card-text lead text-justify">{@html theme.headline}</p> <Row>
<p class="mb-4 mx-3 card-text text-justify">{@html theme.intro}</p> <Col>
</div> <p class="mt-4 mx-3 card-text lead text-justify">{@html theme.headline}</p>
<p class="mb-4 mx-3 card-text text-justify">{@html theme.intro}</p>
</Col>
{#if theme.partner_txt || theme.partner_img || theme.partner_href}
<Col md="2" lg="3" class="d-none d-md-block">
<Card class="pt-3 px-3">
{#if theme.partner_img}
<img src="{theme.partner_img}" class="card-img-top">
{/if}
{#if theme.partner_txt || theme.partner_href}
<CardBody class="p-0 mt-3">
{#if theme.partner_txt}
{@html theme.partner_txt}
{/if}
{#if theme.partner_href}
<Button tag="a" color="primary" href="{theme.partner_href}">
Visiter le site
</Button>
{/if}
</CardBody>
{/if}
</Card>
</Col>
{/if}
</Row>
</CardBody>
<ul class="list-group"> <ul class="list-group">
{#each Object.keys(theme.exercices) as k, index} {#each Object.keys(theme.exercices) as k, index}
@ -88,7 +119,7 @@
{/each} {/each}
</ul> </ul>
</div> </Card>
{:else} {:else}
<Alert color="danger" fade={false}> <Alert color="danger" fade={false}>
<Icon name="dash-circle-fill" /> <Icon name="dash-circle-fill" />

View File

@ -85,7 +85,10 @@ CREATE TABLE IF NOT EXISTS themes(
headline TEXT NOT NULL, headline TEXT NOT NULL,
intro TEXT NOT NULL, intro TEXT NOT NULL,
image VARCHAR(255) NOT NULL, image VARCHAR(255) NOT NULL,
authors TEXT NOT NULL authors TEXT NOT NULL,
partner_img VARCHAR(255) NOT NULL,
partner_href VARCHAR(255) NOT NULL,
partner_text TEXT NOT NULL
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; ) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
`); err != nil { `); err != nil {
return err return err

View File

@ -4,24 +4,27 @@ import ()
// Theme represents a group of challenges, to display to players // Theme represents a group of challenges, to display to players
type Theme struct { type Theme struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
URLId string `json:"urlid"` URLId string `json:"urlid"`
Path string `json:"path"` Path string `json:"path"`
Authors string `json:"authors,omitempty"` Authors string `json:"authors,omitempty"`
Intro string `json:"intro,omitempty"` Intro string `json:"intro,omitempty"`
Headline string `json:"headline,omitempty"` Headline string `json:"headline,omitempty"`
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`
PartnerImage string `json:"partner_img,omitempty"`
PartnerLink string `json:"partner_href,omitempty"`
PartnerText string `json:"partner_txt,omitempty"`
} }
// CmpTheme returns true if given Themes are identicals. // CmpTheme returns true if given Themes are identicals.
func CmpTheme(t1 Theme, t2 Theme) bool { func CmpTheme(t1 Theme, t2 Theme) bool {
return !(t1.Name != t2.Name || t1.URLId != t2.URLId || t1.Path != t2.Path || t1.Authors != t2.Authors || t1.Intro != t2.Intro || t1.Headline != t2.Headline || t1.Image != t2.Image) return !(t1.Name != t2.Name || t1.URLId != t2.URLId || t1.Path != t2.Path || t1.Authors != t2.Authors || t1.Intro != t2.Intro || t1.Headline != t2.Headline || t1.Image != t2.Image || t1.PartnerImage != t2.PartnerImage || t1.PartnerLink != t2.PartnerLink || t1.PartnerText != t2.PartnerText)
} }
// GetThemes returns a list of registered Themes from the database. // GetThemes returns a list of registered Themes from the database.
func GetThemes() ([]Theme, error) { func GetThemes() ([]Theme, error) {
if rows, err := DBQuery("SELECT id_theme, name, url_id, path, authors, intro, headline, image FROM themes"); err != nil { if rows, err := DBQuery("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes"); err != nil {
return nil, err return nil, err
} else { } else {
defer rows.Close() defer rows.Close()
@ -29,7 +32,7 @@ func GetThemes() ([]Theme, error) {
var themes = make([]Theme, 0) var themes = make([]Theme, 0)
for rows.Next() { for rows.Next() {
var t Theme var t Theme
if err := rows.Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image); err != nil { if err := rows.Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText); err != nil {
return nil, err return nil, err
} }
themes = append(themes, t) themes = append(themes, t)
@ -45,7 +48,7 @@ func GetThemes() ([]Theme, error) {
// GetTheme retrieves a Theme from its identifier. // GetTheme retrieves a Theme from its identifier.
func GetTheme(id int64) (Theme, error) { func GetTheme(id int64) (Theme, error) {
var t Theme var t Theme
if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image FROM themes WHERE id_theme=?", id).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image); err != nil { if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes WHERE id_theme=?", id).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText); err != nil {
return t, err return t, err
} }
@ -55,7 +58,7 @@ func GetTheme(id int64) (Theme, error) {
// GetThemeByName retrieves a Theme from its title // GetThemeByName retrieves a Theme from its title
func GetThemeByName(name string) (Theme, error) { func GetThemeByName(name string) (Theme, error) {
var t Theme var t Theme
if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image FROM themes WHERE name=?", name).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image); err != nil { if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_text FROM themes WHERE name=?", name).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerText); err != nil {
return t, err return t, err
} }
@ -65,7 +68,7 @@ func GetThemeByName(name string) (Theme, error) {
// GetThemeByPath retrieves a Theme from its dirname // GetThemeByPath retrieves a Theme from its dirname
func GetThemeByPath(dirname string) (Theme, error) { func GetThemeByPath(dirname string) (Theme, error) {
var t Theme var t Theme
if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image FROM themes WHERE path=?", dirname).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image); err != nil { if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes WHERE path=?", dirname).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText); err != nil {
return t, err return t, err
} }
@ -74,7 +77,7 @@ func GetThemeByPath(dirname string) (Theme, error) {
// CreateTheme creates and fills a new struct Theme and registers it into the database. // CreateTheme creates and fills a new struct Theme and registers it into the database.
func CreateTheme(theme Theme) (Theme, error) { func CreateTheme(theme Theme) (Theme, error) {
if res, err := DBExec("INSERT INTO themes (name, url_id, authors, path, intro, headline, image) VALUES (?, ?, ?, ?, ?, ?, ?)", theme.Name, theme.URLId, theme.Authors, theme.Path, theme.Intro, theme.Headline, theme.Image); err != nil { if res, err := DBExec("INSERT INTO themes (name, url_id, authors, path, intro, headline, image, partner_img, partner_href, partner_text) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", theme.Name, theme.URLId, theme.Authors, theme.Path, theme.Intro, theme.Headline, theme.Image, theme.PartnerImage, theme.PartnerLink, theme.PartnerText); err != nil {
return Theme{}, err return Theme{}, err
} else if theme.Id, err = res.LastInsertId(); err != nil { } else if theme.Id, err = res.LastInsertId(); err != nil {
return Theme{}, err return Theme{}, err
@ -95,7 +98,7 @@ func (t *Theme) FixURLId() bool {
// Update applies modifications back to the database. // Update applies modifications back to the database.
func (t Theme) Update() (int64, error) { func (t Theme) Update() (int64, error) {
if res, err := DBExec("UPDATE themes SET name = ?, url_id = ?, authors = ?, path = ?, intro = ?, headline = ?, image = ? WHERE id_theme = ?", t.Name, t.URLId, t.Authors, t.Path, t.Intro, t.Headline, t.Image, t.Id); err != nil { if res, err := DBExec("UPDATE themes SET name = ?, url_id = ?, authors = ?, path = ?, intro = ?, headline = ?, image = ?, partner_img = ?, partner_href = ?, partner_text = ? WHERE id_theme = ?", t.Name, t.URLId, t.Authors, t.Path, t.Intro, t.Headline, t.Image, t.PartnerImage, t.PartnerLink, t.PartnerText, t.Id); err != nil {
return 0, err return 0, err
} else if nb, err := res.RowsAffected(); err != nil { } else if nb, err := res.RowsAffected(); err != nil {
return 0, err return 0, err

View File

@ -20,13 +20,16 @@ type exportedExercice struct {
// exportedTheme is a structure representing a Theme, as exposed to players. // exportedTheme is a structure representing a Theme, as exposed to players.
type exportedTheme struct { type exportedTheme struct {
Name string `json:"name"` Name string `json:"name"`
URLId string `json:"urlid"` URLId string `json:"urlid"`
Authors string `json:"authors"` Authors string `json:"authors"`
Headline string `json:"headline,omitempty"` Headline string `json:"headline,omitempty"`
Intro string `json:"intro"` Intro string `json:"intro"`
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`
Exercices map[string]exportedExercice `json:"exercices"` PartnerImage string `json:"partner_img,omitempty"`
PartnerLink string `json:"partner_href,omitempty"`
PartnerText string `json:"partner_txt,omitempty"`
Exercices map[string]exportedExercice `json:"exercices"`
} }
// Exportedthemes exports themes from the database, to be displayed to players. // Exportedthemes exports themes from the database, to be displayed to players.
@ -59,6 +62,11 @@ func ExportThemes() (interface{}, error) {
imgpath = path.Join(FilesDir, theme.Image) imgpath = path.Join(FilesDir, theme.Image)
} }
partnerImgpath := ""
if len(theme.PartnerImage) > 0 {
partnerImgpath = path.Join(FilesDir, theme.PartnerImage)
}
ret[fmt.Sprintf("%d", theme.Id)] = exportedTheme{ ret[fmt.Sprintf("%d", theme.Id)] = exportedTheme{
theme.Name, theme.Name,
theme.URLId, theme.URLId,
@ -66,6 +74,9 @@ func ExportThemes() (interface{}, error) {
theme.Headline, theme.Headline,
strings.Replace(theme.Intro, "$FILES$", FilesDir, -1), strings.Replace(theme.Intro, "$FILES$", FilesDir, -1),
imgpath, imgpath,
partnerImgpath,
theme.PartnerLink,
theme.PartnerText,
exos, exos,
} }
} }