This commit is contained in:
2022-05-11 21:38:20 +02:00
commit 809b06baf6
35 changed files with 6458 additions and 0 deletions

View File

@ -0,0 +1,13 @@
{{define "admin_menu"}}
<aside class="asideAdmin mt-2">
<h4>
Administration
</h4>
<ul class="side-menu">
<li><a href="/admin/settings" {{if eq . "config"}}class="is-active"{{end}}>Réglages</a></li>
<li><a href="/admin/users" {{if eq . "users"}}class="is-active"{{end}}>Utilisateurs</a></li>
<li><a href="/admin/apps" {{if eq . "apps"}}class="is-active"{{end}}>Applications</a></li>
<li><a href="/admin/market" {{if eq . "market"}}class="is-active"{{end}}>Place de marché</a></li>
</ul>
</aside>
{{end}}

View File

@ -0,0 +1,53 @@
{{define "app_tile" }}
<div class="tile is-parent is-4">
<article class="app-tile tile is-child" data-controller="app-tile">
<div class="front notification">
<p class="title">{{ .Manifest.Title }}</p>
<p class="subtitle">{{ index .Manifest.Tags 0 }}</p>
<div class="level is-mobile">
<div class="level-left">
<div class="level-item">
<div class="buttons">
{{if .Manifest.Options.HighscoresEnabled}}
<a class="button is-outlined is-link is-medium"
href="highscores/{{ .Manifest.ID }}">
<svg class="icon">
<use xlink:href="#trophy"></use>
</svg>
</a>
{{end}}
{{ if .Manifest.Description }}
<button data-action="click->app-tile#flip"
class="button is-outlined is-info is-medium">
<svg class="icon">
<use xlink:href="#question"></use>
</svg>
</button>
{{ end }}
</div>
</div>
</div>
<div class="level-right">
<div class="level-item">
<a class="button is-primary is-medium has-no-shadow"
href="apps/{{ .Manifest.ID }}">
<span>Ouvrir</span>
<svg class="icon">
<use xlink:href="#chevron-right"></use>
</svg>
</a>
</div>
</div>
</div>
</div>
{{ if .Manifest.Description }}
<div class="back notification" data-action="click->app-tile#flip">
<div class="content">
{{ markdown .Manifest.Description }}
</div>
</div>
{{ end }}
</article>
</div>
{{end}}

View File

@ -0,0 +1,24 @@
{{define "base"}}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{block "title" . -}}{{- end}}</title>
<link rel="stylesheet" href="/css/server.css">
<link rel="stylesheet" href="/css/form.css">
<link rel="stylesheet" href="/css/custom.css">
{{- block "head_style" . -}}{{end}}
{{- block "head_script" . -}}
{{template "js_config" .}}
<script defer src="/server.js"></script>
<script defer src="/server.js"></script>
{{end}}
</head>
<body>
{{- block "body" . -}}{{- end -}}
{{- block "body_script" . -}}{{end}}
</body>
{{template "footer" .}}
</html>
{{end}}

View File

@ -0,0 +1,23 @@
{{define "flash"}}
<div class="flash has-margin-top-small has-margin-bottom-small">
{{- range .Flashes -}}
{{- if eq .Type "error" -}}
{{template "flash_message" map "Title" "Erreur" "MessageClass" "is-danger" "Message" .Message }}
{{- else if eq .Type "warn" -}}
{{template "flash_message" map "Title" "Attention" "MessageClass" "is-warning" "Message" .Message }}
{{- else if eq .Type "success" -}}
{{template "flash_message" map "Title" "Succès" "MessageClass" "is-success" "Message" .Message }}
{{- else -}}
{{template "flash_message" map "Title" "Information" "MessageClass" "is-info" "Message" .Message }}
{{- end -}}
{{- end -}}
</div>
{{end}}
{{define "flash_message" -}}
<div class="message {{.MessageClass}}">
<div class="message-body">
<span class="has-text-weight-bold">{{.Title}}</span> {{.Message}}
</div>
</div>
{{- end}}

View File

@ -0,0 +1,15 @@
{{define "footer"}}
<footer>
<p>
<a href="/admin">Accéder au panneau d'administration</a>
</p>
<p>
Propulsé par <a href="https://gitlab.com/arcadbox/arcad">Arcad</a> et publié sous licence <a class="has-text-primary" href="https://gitlab.com/arcadbox/arcad/-/blob/{{ .BuildInfo.GitRef }}/LICENSE">AGPL-3.0</a>.
</p>
<p>
Version: {{ .BuildInfo.ProjectVersion }} -
Réf.: {{ .BuildInfo.GitRef }} -
Date de construction: {{ .BuildInfo.BuildDate }}
</p>
</footer>
{{end}}

View File

@ -0,0 +1,27 @@
{{define "header"}}
<header>
<a id="logo" href="/"><img src="/assets/logo.svg"></a>
<input type="checkbox" id="active">
<label for="active" class="menu-btn"><span></span></label>
<label for="active" class="close"></label>
<div class="wrapper">
<ul>
<li class="flashlight"><a href="/"><img src="/assets/logo.svg"></a></li>
{{if .IsAdmin}}
<li>
<a href="/admin/logout" class="button is-warning is-medium" style="font-size: 0.73em;">
<svg class="icon" width="50" height="50">
<use xlink:href="#sign-out-alt"></use>
</svg>
</a>
</li>
{{end}}
<li>
<a id="flash" href="/profile">Profile</a>
</li>
<li><a class="ligth" href="/admin">Admin</a></li>
<li><a href="#">Feedback</a></li>
</ul>
</div>
</header>
{{end}}

View File

@ -0,0 +1,3 @@
{{define "js_config"}}
<script type="text/javascript">(function() { window.__CONFIG__ = JSON.parse({{toJSON .JSConfig}}) }())</script>
{{end}}

View File

@ -0,0 +1,118 @@
{{define "title"}}Modifier l'app - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" ""}}
</div>
<div class="column is-10">
{{template "flash" .}}
<div class="level">
<div class="level-left">
<a class="button level-item" href="/admin/apps">← Retour</a>
</div>
<div class="level-right"></div>
</div>
<form class="has-margin-top-small" action="/admin/apps/{{ .App.ID }}" method="post">
<div class="columns">
<div class="column is-12">
<div class="level">
<div class="level-left">
<h5 class="is-size-5 level-item">Informations de l'app</h5>
</div>
<div class="level-right">
<div class="field level-item">
<input id="publishedSwitch" type="checkbox" name="published" class="switch" {{if .IsPublished}}checked="checked"{{end}} />
<label for="publishedSwitch">Publiée ?</label>
</div>
</div>
</div>
<div class="field">
<label class="label">Identifiant</label>
<div class="control">
<p class="input">{{ .App.ID }}</p>
<p class="helper">Non modifiable</p>
</div>
</div>
<div class="field">
<label class="label">Titre</label>
<div class="control">
<input class="input" type="text"
name="title"
value="{{if .Form}}{{ .Form.Get "title" }}{{else}}{{ .App.Manifest.Title }}{{end}}">
<label className="checkbox is-right">
<input type="checkbox" name="resetTitle" />
Réinitialiser la valeur par défaut ?
</label>
</div>
</div>
<div class="field">
<label class="label">Description</label>
<div class="control">
<textarea class="textarea"
name="description">{{if .Form}}{{ .Form.Get "description" }}{{else}}{{ .App.Manifest.Description }}{{end}}</textarea>
<label className="checkbox is-right">
<input type="checkbox" name="resetDescription" />
Réinitialiser la valeur par défaut ?
</label>
</div>
</div>
<div class="field">
<label class="label">Ordre d'affichage</label>
<div class="control">
<input class="input" type="number"
step="1"
min="0"
name="order"
value="{{if .Form}}{{ .Form.Get "order" }}{{else}}{{ .App.Order }}{{end}}">
<label className="checkbox is-right">
<input type="checkbox" name="resetOrder" />
Réinitialiser la valeur par défaut ?
</label>
</div>
</div>
<div class="field" data-controller="tags-editor">
<label class="label">Tags</label>
<div class="control">
<div class="field has-addons">
<div class="control">
<input class="input is-small" type="text" placeholder="Nouveau tag" data-target="tags-editor.newTag">
</div>
<div class="control">
<a class="button is-small is-info has-text-bold" data-action="click->tags-editor#onAddTag">
+
</a>
</div>
</div>
<div class="tags" data-target="tags-editor.tagsContainer"></div>
<input class="input is-hidden" type="text"
data-target="tags-editor.tagsSource"
name="tags"
value="{{if .Form}}{{ .Form.Get "tags" }}{{else}}{{range .App.Manifest.Tags}}{{.}},{{end}}{{end}}" />
<label className="checkbox is-right">
<input type="checkbox" name="resetOrder" />
Réinitialiser la valeur par défaut ?
</label>
</div>
</div>
{{ .csrfField }}
<div class="buttons" style="justify-content:flex-end">
<button type="submit" class="button is-primary is-normal">Modifier</button>
</div>
</div>
</div>
</form>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,69 @@
{{define "title"}}Applications - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" "apps"}}
</div>
<div class="column is-10">
{{template "flash" .}}
<h4 class="is-size-4">Liste des applications installées</h4>
<div class="has-text-right">
<b>Total</b> {{ .AppsCount }}
</div>
<div class="table-container">
<table class="table is-fullwidth is-striped">
<thead>
<tr>
<th>ID</th>
<th>Titre</th>
<th>Version</th>
<th>Ordre d'affichage</th>
<th>Publiée ?</th>
<th>Tags</th>
<th class="has-text-right">Actions</th>
</tr>
</thead>
<tbody>
{{range .Apps}}
<tr>
<td><code>{{ .ID }}</code></td>
<td>{{ .Manifest.Title }}</td>
<td>{{ if eq .Manifest.Version "" }}--{{else}}{{ .Manifest.Version }}{{end}}</td>
<td>{{ .Order }}</td>
<td>{{ if .Published }}oui{{else}}non{{end}}</td>
<td>
{{range .Manifest.Tags}}
<span class="tag is-info">{{ . }}</span>
{{end}}
</td>
<td>
<div class="buttons are-small is-right">
<a class="button is-link" href="/admin/apps/{{ .ID }}">Modifier</a>
</div>
</td>
</tr>
{{else}}
<tr class="has-text-centered is-italic">
<td colspan="7">
Aucune application installée.
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,22 @@
{{define "title"}}Login - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="login is-fullheight section">
<div class="container">
{{template "flash" .}}
<div class="loginForm">
<h4>Administration</h4>
<form method="POST">
<input
name="password" type="password"
autocomplete="current-password"
placeholder="Mot de passe">
{{ .csrfField }}
<button>S'identifier</button>
</form>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,46 @@
{{define "title"}}Installer une application - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section" data-controller="app-install">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" "market"}}
</div>
<div class="column is-10">
{{template "flash" .}}
{{if .App}}
<article class="message is-info">
<div class="message-header">
<p>Installation d'une application</p>
</div>
<div class="message-body">
<p data-target="app-install.message">Êtes vous sûr de vouloir installer l'application <code>{{ .App.Name }}</code> en version <code>{{ .App.LatestRelease.Version }}</code> développée par <b>{{ .App.Owner.Username }}</b> ?</p>
<div class="buttons is-right">
<a data-target="app-install.cancelButton" href="/admin/market" class="button is-outlined is-link">Annuler</a>
<button data-target="app-install.installButton" data-action="click->app-install#onInstallClick" class="button is-primary">Confirmer</a>
</div>
</div>
</article>
{{else}}
<article class="message is-danger">
<div class="message-body">
Impossible de trouver l'application correspondant à la demande d'installation.
<div class="buttons is-right">
<a href="/admin/market" class="button is-outlined is-danger">Retour</a>
</div>
</div>
</article>
{{end}}
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,74 @@
{{define "title"}}Place de marché - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" "market"}}
</div>
<div class="column is-10">
{{template "flash" .}}
<form action="/admin/market" methode="GET">
<div class="field has-addons mt-5 mb-5">
<div class="control is-expanded">
<input class="input is-medium" type="text" name="search" placeholder="Rechercher une application..." value="{{ .Search }}">
</div>
<div class="control">
<button type="submit" class="button is-medium">
Rechercher
</button>
</div>
</div>
</form>
<div class="has-text-right">
<b>Total</b> {{ .ResultsCount }}
</div>
<div class="table-container">
<table class="table is-fullwidth is-striped">
<thead>
<tr>
<th>ID</th>
<th>Description</th>
<th>Développeur</th>
<th>Dernière version</th>
<th>Dernière mise à jour</th>
<th class="has-text-right">Actions</th>
</tr>
</thead>
<tbody>
{{range .Results}}
<tr>
<td><code>{{ .Name }}</code></td>
<td>{{ .LatestRelease.Description }}</td>
<td>{{ .Owner.Username }}</td>
<td>{{ .LatestRelease.Version }}</td>
<td>{{ localeTimeFormat .LatestRelease.CreatedAt.Time "02/01/2006 15:04" "fr_FR" }}</td>
<td>
<div class="buttons are-small is-right">
<a class="button is-link" href="/admin/market/{{ .ID }}/install">Installer</a>
</div>
</td>
</tr>
{{else}}
<tr class="has-text-centered is-italic">
<td colspan="6">
Aucun résultat.
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,40 @@
{{define "title"}}Création du mot de passe - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="login is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-offset-4 is-4">
{{template "flash" .}}
<div class="box">
<h4 class="title is-size-4">Création du mot de passe de l'administrateur</h4>
<form method="POST">
<div class="field">
<div class="control">
<input class="input is-normal"
name="adminPassword" type="password"
autocomplete="new-password"
placeholder="Mot de passe">
</div>
</div>
<div class="field">
<div class="control">
<input class="input is-normal"
name="adminPassword-confirm" type="password"
autocomplete="new-password"
placeholder="Confirmation du mot de passe">
</div>
</div>
{{ .csrfField }}
<input type="submit"
value="Enregister"
class="button is-block is-primary is-normal is-fullwidth">
</form>
</div>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,72 @@
{{define "title"}}Configuration - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section" data-controller="clock-sync">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" "config"}}
</div>
<div class="mt-2">
{{template "flash" .}}
<h4 class="is-size-4">Réglages</h4>
<form id="adminSettings" method="post">
{{ .csrfField }}
{{ $settings := .Settings }}
{{range $id, $meta := .Metadatas}}
{{ $se := $settings.Get $id }}
{{ $data := createMap "ID" $id "Setting" $se "Meta" $meta }}
{{if eq $meta.ValueType "password"}}
{{template "password_setting" $data}}
{{else if eq $meta.ValueType "markdown"}}
{{template "markdown_setting" $data}}
{{end}}
{{end}}
<div class="field is-grouped is-grouped-right">
<p class="control">
<input type="submit" class="button is-success" value="Enregistrer">
</p>
</div>
</form>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}
{{define "password_setting"}}
<div class="field">
<label class="label">{{ .Meta.Label }}</label>
<div class="control">
<input class="input" name="{{ .ID }}"
autocomplete="new-password"
type="password">
</div>
</div>
<div class="field">
<label class="label">{{ .Meta.Label }} (confirmation)</label>
<div class="control">
<input class="input" name="{{ .ID }}-confirm"
autocomplete="new-password"
type="password">
</div>
</div>
{{end}}
{{define "markdown_setting"}}
<div class="field">
<label class="label">{{ .Meta.Label }}</label>
<div class="field">
<div class="control">
<textarea class="textarea" placeholder="{{ .Meta.DefaultValue }}" name="{{ .ID }}">{{- if .Setting}}{{ .Setting.Value }}{{end -}}</textarea>
</div>
</div>
</div>
{{end}}

View File

@ -0,0 +1,41 @@
{{define "title"}}Informations de l'utilisateur - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" ""}}
</div>
<div class="column is-10">
{{template "flash" .}}
<form class="has-margin-top-small" action="/admin/users/{{ .User.ID }}/delete" method="post">
{{ .csrfField }}
<div class="message is-warning">
<div class="message-body">
Êtes vous sûr de vouloir supprimer le compte de l'utilisateur "{{ .User.Nickname }}" ({{ .User.ID }}) ?
</div>
</div>
<div class="field is-grouped is-grouped-right">
<p class="control">
<a href="/admin/users/{{.User.ID}}" class="button is-light">
Annuler
</a>
</p>
<p class="control">
<input type="submit" class="button is-danger" value="Supprimer">
</p>
</div>
</form>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,102 @@
{{define "title"}}Informations de l'utilisateur - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" ""}}
</div>
<div class="column is-10">
{{template "flash" .}}
<div class="level">
<div class="level-left">
<a class="button level-item" href="/admin/users">← Retour</a>
</div>
<div class="level-right">
<a class="button level-item is-danger" href="/admin/users/{{ .User.ID }}/delete">Supprimer</a>
</div>
</div>
<form class="has-margin-top-small" action="/admin/users/{{ .User.ID }}" method="post">
<div class="columns">
<div class="column is-6">
<h5 class="is-size-5">Informations de l'utilisateur</h5>
<div class="field">
<label class="label">Pseudonyme</label>
<div class="control">
<input class="input" type="text"
name="nickname"
value="{{if .Form}}{{ .Form.Get "nickname" }}{{else}}{{ .User.Nickname }}{{end}}">
</div>
</div>
{{ .csrfField }}
<div class="buttons" style="justify-content:flex-end">
<button type="submit" class="button is-primary is-normal">Modifier</button>
</div>
<div class="field">
<label class="label">Date de création</label>
<div class="control">
<p class="input" readonly>
{{ localeTimeFormat .User.CreationTime "02/01/2006 15:04" "fr_FR" }}
</p>
</div>
</div>
<div class="field">
<label class="label">Date de dernière connexion</label>
<div class="control">
<p class="input" readonly>
{{ localeTimeFormat .User.LastSeenTime "02/01/2006 15:04" "fr_FR" }}
</p>
</div>
</div>
{{with .User.LastUserAgent}}
<div class="field">
<label class="label">Dernier système d'exploitation utilisé</label>
<div class="control">
<p class="input" readonly>
{{ .OS.Name.StringTrimPrefix }} {{ .OS.Version.Major }}.{{ .OS.Version.Minor }}.{{ .OS.Version.Patch }}
</p>
</div>
</div>
<div class="field">
<label class="label">Dernier navigateur utilisé</label>
<div class="control">
<p class="input" readonly>
{{ .Browser.Name.StringTrimPrefix }} {{ .Browser.Version.Major }}.{{ .Browser.Version.Minor }}.{{ .Browser.Version.Patch }}
</p>
</div>
</div>
<div class="field">
<label class="label">Dernier type de terminal utilisé</label>
<div class="control">
<p class="input" readonly>
{{ .DeviceType.StringTrimPrefix }}
</p>
</div>
</div>
{{end}}
</div>
<div class="column is-6">
<h5 class="is-size-5">Carte de membre</h5>
<div class="box has-margin-top-small">
<figure class="image is-3by2">
<a href="/admin/users/{{ .User.ID }}/card" rel="Member card" download="ArcadBox-Member-{{ .User.Nickname }}">
<img src="/admin/users/{{ .User.ID }}/card" />
</a>
</figure>
</div>
</div>
</div>
</form>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,58 @@
{{define "title"}}Utilisateurs - Administration - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div class="container">
<div class="columns">
<div class="column is-2">
{{template "admin_menu" "users"}}
</div>
<div class="column is-10">
{{template "flash" .}}
<h4 class="is-size-4">Liste des utilisateurs</h4>
<div class="has-text-right">
<b>Total</b> {{ .UsersCount }}
</div>
<div class="table-container">
<table class="table is-hovered is-fullwidth is-striped">
<thead>
<tr>
<th>Pseudonyme</th>
<th>Date d'enregistrement</th>
<th>Dernière connexion</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{{range .Users}}
<tr>
<td>{{ .Nickname }}</td>
<td>{{ localeTimeFormat .CreationTime "02/01/2006 15:04" "fr_FR" }}</td>
<td>{{ localeTimeFormat .LastSeenTime "02/01/2006 15:04" "fr_FR" }}</td>
<td>
<div class="field is-grouped">
<div class="control">
<a class="button is-danger is-small" href="/admin/users/{{ .ID }}/delete">Supprimer</a>
</div>
<div class="control">
<a class="button is-info is-small" href="/admin/users/{{ .ID }}">Voir</a>
</div>
</div>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "body_script"}}
<script defer src="/admin.js"></script>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,31 @@
{{define "title"}}{{ .App.Manifest.Title }} - Arcad{{end}}
{{define "body"}}
<div class="app-wrapper" data-controller="app" data-app-frame-src="./{{ .App.Manifest.ID }}/">
<div class="app-header">
<div class="level is-marginless is-mobile">
<div class="level-left">
<a href="../" class="level-item button is-link is-small">
<svg class="icon">
<use xlink:href="#home"></use>
</svg>
</a>
</div>
<div class="level-right">
{{if .App.Manifest.Options.HighscoresEnabled}}
<a href="../highscores/{{ .App.Manifest.ID }}" class="level-item button is-link is-small">
<span>Classement</span>
<svg class="icon">
<use xlink:href="#trophy"></use>
</svg>
</a>
{{end}}
</div>
</div>
</div>
<iframe class="app-frame" data-target="app.frame"
scrolling="no" seamless="seamless"
data-action="beforeunload->app#onFrameBeforeUnload load->app#onFrameLoad">
</iframe>
</div>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,15 @@
{{define "title"}}Borne non disponible - Arcad{{end}}
{{define "body"}}
<section class="is-fullheight section">
<div class="is-flex is-justify-content-center is-align-content-center is-fullheight">
<div class="message is-warning is-align-self-center">
<div class="message-body">
<h1 class="is-size-4">Arcad</h1>
<p>Désolé mais aucune borne correspondant à ce domaine n'est actuellement en ligne.</p>
<p>Veuillez réessayer plus tard et/ou vous assurer que la borne est correctement connectée à internet.</p>
</div>
</div>
</div>
</section>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,29 @@
{{define "title"}}Chargement en cours - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
{{ $redirectUrl := "/captive?escape=1" }}
{{ if .IsAndroid }}
{{ $redirectUrl := "intent://arcadbox.local/captive?escape=1#Intent;scheme=http;end" }}
{{ end }}
<section class="home is-fullheight section">
<div class="container">
<div class="message is-info">
<div class="message-body">
<div class="content">
<p>Un instant s'il vous plaît, nous préparons votre espace...</p>
<p>Si la page ne se recharge pas automatiquement, <a id="homepage-link" href="{{ $redirectUrl }}" target="_blank">cliquez ici.</a></p>
</div>
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{define "head_style"}}
{{ $redirectUrl := "/captive?escape=1" }}
{{ if .IsAndroid }}
{{ $redirectUrl := "intent://arcadbox.local/captive?escape=1#Intent;scheme=http;end" }}
{{ end }}
<meta http-equiv="refresh" content="1;URL={{ $redirectUrl }}">
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,121 @@
{{define "title"}}{{.App.Manifest.Title}} - Tableau des scores - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div class="container">
<div class="level">
<div class="level-left">
<h1 class="title level-item">{{.App.Manifest.Title}}</h1>
<h2 class="subtitle level-item">Tableau des scores</h2>
</div>
<div class="level-right">
<a class="level-item button is-primary is-large" href="/apps/{{ .App.ID }}">
<span>Ouvrir</span>
<svg class="icon">
<use xlink:href="#chevron-right"></use>
</svg>
</a>
</div>
</div>
<div class="columns">
<div class="column">
{{template "podium" .}}
</div>
<div class="column">
{{template "highscores" .}}
</div>
</div>
{{template "footer" .}}
</div>
</section>
{{end}}
{{template "base" .}}
{{define "podium"}}
<div class="podium-container">
<div class="podium">
<div class="pod second">
{{ if gt (len .Highscores) 1 }}
{{ $secondPlayerHighscore := index .Highscores 1 }}
{{if $secondPlayerHighscore}}
<div class="pod-player">
{{ $secondPlayer := (index .Users $secondPlayerHighscore.UserID) }}
<span class="player-nickname">{{with $secondPlayer}}{{ .Nickname }}{{else}}???{{end}}</span>
<span class="player-score">{{ $secondPlayerHighscore.Score }}</span>
</div>
{{end}}
{{end}}
<div class="pod-stair">
<span class="pod-position">2</span>
</div>
</div>
<div class="pod first">
{{ if gt (len .Highscores) 0 }}
{{ $firstPlayerHighscore := index .Highscores 0 }}
{{if $firstPlayerHighscore}}
<div class="pod-player">
{{ $firstPlayer := (index .Users $firstPlayerHighscore.UserID) }}
<svg class="icon player-crown">
<use xlink:href="#crown"></use>
</svg>
<span class="player-nickname">{{with $firstPlayer}}{{ .Nickname }}{{else}}???{{end}}</span>
<span class="player-score">{{ $firstPlayerHighscore.Score }}</span>
</div>
{{end}}
{{end}}
<div class="pod-stair">
<span class="pod-position">1</span>
</div>
</div>
<div class="pod third">
{{ if gt (len .Highscores) 2 }}
{{ $thirdPlayerHighscore := index .Highscores 2 }}
{{if $thirdPlayerHighscore}}
<div class="pod-player">
{{ $thirdPlayer := (index .Users $thirdPlayerHighscore.UserID) }}
<span class="player-nickname">{{with $thirdPlayer}}{{ .Nickname }}{{else}}???{{end}}</span>
<span class="player-score">{{ $thirdPlayerHighscore.Score }}</span>
</div>
{{end}}
{{end}}
<div class="pod-stair">
<div class="pod-position">3</div>
</div>
</div>
</div>
</div>
{{end}}
{{define "highscores"}}
{{ $users := .Users }}
<div class="table-container">
<table class="table is-fullwidth is-hoverable is-striped">
<thead>
<th>Position</th>
<th>Pseudonyme</th>
<th>Score</th>
<th>Date</th>
</thead>
<tbody>
{{range $i, $h := .Highscores}}
{{ $user := (index $users $h.UserID) }}
<tr>
{{ $position := addInt $i 1 }}
<td>{{ $position }}</td>
<td>{{with $user}}{{ .Nickname }}{{else}}???{{end}}</td>
<td>{{ $h.Score }}</td>
<td>{{ localeTimeFormat $h.CreationTime "02/01/2006 15:04" "fr_FR" }}</td>
</tr>
{{else}}
<tr>
<td colspan="4" class="has-text-centered is-italic">Aucun score pour l'instant.</td>
</tr>
{{end}}
</tbody>
</table>
</div>
{{end}}

View File

@ -0,0 +1,24 @@
{{define "title"}}Accueil - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section class="home is-fullheight section">
<div id="main" class="container">
<img src="/assets/arcad.svg">
{{if and .WelcomeMessage .WelcomeMessage.Value}}
<div class="message is-info is-small">
<div class="message-body">
<div class="content">
{{markdown .WelcomeMessage.Value}}
</div>
</div>
</div>
{{end}}
<div class="tile is-ancestor is-wrap tile-container">
{{range .Apps}}
{{- template "app_tile" . -}}
{{end}}
</div>
</div>
</section>
{{end}}
{{template "base" .}}

View File

@ -0,0 +1,85 @@
{{define "title"}}Profil - Arcad{{end}}
{{define "body"}}
{{template "header" .}}
<section>
<div>
{{template "flash" .}}
<form action="/login" method="POST" enctype="multipart/form-data">
<div class="field" style="margin-bottom:0">
<div class="file is-medium is-success" id="memberCard">
<label class="file-label">
<input class="file-input" type="file" name="memberCard">
<span class="file-cta">
<span class="file-icon">
<svg class="icon" width="50" height="50">
<use xlink:href="#address-card"></use>
</svg>
</span>
<span class="file-label">
Se connecter
</span>
</span>
</label>
</div>
</div>
{{ .csrfField }}
</form>
</div>
<div class="level-item">
<a href="/logout" class="button is-warning is-medium">
<svg class="icon" width="50" height="50">
<use xlink:href="#sign-out-alt"></use>
</svg>
</a>
</div>
</div>
</div>
<div class="columns">
<div class="column is-6">
<h5 class="is-size-5">Vos informations</h5>
<form class="has-margin-top-small" action="/profile" method="post">
<div class="field">
<label class="label">Pseudonyme</label>
<div class="control">
<input class="input is-medium" type="text"
name="nickname"
value="{{if .Form}}{{ .Form.Get "nickname" }}{{else}}{{ .User.Nickname }}{{end}}">
</div>
</div>
{{ .csrfField }}
<div class="buttons" style="justify-content:flex-end">
<button type="submit" class="button is-primary is-medium">
<span>Modifier</span>
<span class="icon">
<svg class="icon" width="50" height="50">
<use xlink:href="#edit"></use>
</svg>
</span>
</button>
</div>
</form>
</div>
<div class="column is-6">
<h5 class="is-size-5">Carte de membre</h5>
<article class="message is-info">
<div class="message-body">
Téléchargez et utilisez votre carte de membre afin de pouvoir vous authentifier la prochaine fois avec le même pseudonyme !
</div>
</article>
<figure class="image is-3by2 has-margin-top-small">
<a href="/profile/card" rel="Member card" download="ArcadBox-Member-{{ .User.Nickname }}">
<img src="/profile/card" />
</a>
</figure>
</div>
</section>
{{end}}
{{define "body_script"}}
<script>
const fileInput = document.querySelector('#memberCard input[type=file]');
fileInput.onchange = () => {
fileInput.form.submit();
}
</script>
{{end}}
{{template "base" .}}