Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51b9631708 |
No files matched your search
+6
-12
@@ -1,12 +1,6 @@
|
||||
# Nix build result
|
||||
result
|
||||
|
||||
# .NET
|
||||
bin/
|
||||
obj/
|
||||
*.user
|
||||
*.suo
|
||||
*.db
|
||||
publish/
|
||||
|
||||
.direnv/
|
||||
node_modules/*
|
||||
lib/*
|
||||
css/*
|
||||
/api/resultats.json
|
||||
/index.html
|
||||
/main-built.js
|
||||
@@ -0,0 +1,21 @@
|
||||
image: node
|
||||
|
||||
before_script:
|
||||
# install ssh-agent
|
||||
- 'which npm || ( apt-get update -y && apt-get install node -y )'
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- npm install
|
||||
- node_modules/.bin/gulp prod
|
||||
- node_modules/.bin/r.js -o build.js
|
||||
- rm -rf node_modules .public public
|
||||
- mkdir .public
|
||||
- cp -r * .public
|
||||
- mv .public public
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- private
|
||||
@@ -1,74 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Phenix.Models;
|
||||
using Phenix.Services;
|
||||
|
||||
namespace Phenix.Controllers;
|
||||
|
||||
public record CreateGameRequest(
|
||||
string Date, string Time, string Home, string Away,
|
||||
int? HomeScore = null, int? AwayScore = null,
|
||||
bool Practice = false, bool Rain = false
|
||||
);
|
||||
|
||||
[Route("/api")]
|
||||
public class ApiController : Controller
|
||||
{
|
||||
private readonly IGameService _games;
|
||||
|
||||
public ApiController(IGameService games)
|
||||
{
|
||||
_games = games;
|
||||
}
|
||||
|
||||
[HttpGet("results/{year}.json")]
|
||||
public async Task<IActionResult> ResultsJson(int year)
|
||||
{
|
||||
var games = await _games.GetAllGames();
|
||||
var results = games
|
||||
.Where(g => g.Year == year)
|
||||
.Select(g => new Dictionary<string, object?>
|
||||
{
|
||||
["id"] = g.Id,
|
||||
["date"] = g.Date,
|
||||
["time"] = g.Time,
|
||||
["home"] = g.Home,
|
||||
["away"] = g.Away,
|
||||
["year"] = g.Year,
|
||||
[g.Home] = g.HomeScore,
|
||||
[g.Away] = g.AwayScore,
|
||||
["practice"] = g.Practice,
|
||||
["rain"] = g.Rain,
|
||||
});
|
||||
return Json(results);
|
||||
}
|
||||
|
||||
[HttpGet("available-years.json")]
|
||||
public async Task<IActionResult> AvailableYearsJson()
|
||||
{
|
||||
var games = await _games.GetAllGames();
|
||||
var years = games.Select(g => g.Year).Distinct().OrderByDescending(y => y);
|
||||
return Json(years);
|
||||
}
|
||||
|
||||
[HttpPost("games")]
|
||||
public async Task<IActionResult> CreateGame([FromBody] CreateGameRequest req)
|
||||
{
|
||||
var (game, error) = await _games.CreateNewGame(req.Date, req.Time, req.Home, req.Away);
|
||||
if (game is null)
|
||||
return error switch
|
||||
{
|
||||
"game already exists at this date/time" => Conflict(new { error }),
|
||||
_ => BadRequest(new { error }),
|
||||
};
|
||||
|
||||
await _games.UpdateGame(game.Id, req.HomeScore, req.AwayScore, req.Rain, req.Practice);
|
||||
return Created($"/api/games/{game.Id}", game);
|
||||
}
|
||||
|
||||
[HttpDelete("games")]
|
||||
public async Task<IActionResult> ClearGames()
|
||||
{
|
||||
await _games.ClearAllGames();
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Phenix.Services;
|
||||
|
||||
namespace Phenix.Controllers;
|
||||
|
||||
public class HomeController : Controller
|
||||
{
|
||||
[HttpGet("/")]
|
||||
public IActionResult Index() => View();
|
||||
|
||||
[HttpGet("/calendrier")]
|
||||
public IActionResult Calendrier() => View();
|
||||
|
||||
[HttpGet("/nouvelles")]
|
||||
public IActionResult Nouvelles() => View();
|
||||
|
||||
[HttpGet("/contact")]
|
||||
public IActionResult Contact() => View();
|
||||
|
||||
[HttpGet("/reglement")]
|
||||
public IActionResult Reglement() => View();
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Phenix.Services;
|
||||
|
||||
namespace Phenix.Controllers;
|
||||
|
||||
[Route("/membre")]
|
||||
public class MembreController : Controller
|
||||
{
|
||||
private readonly IGameService _games;
|
||||
private readonly LoginService _login;
|
||||
private const string SessionCookie = "phenix-session";
|
||||
private const string SessionSignCookie = "phenix-session-sign";
|
||||
|
||||
public MembreController(IGameService games, LoginService login)
|
||||
{
|
||||
_games = games;
|
||||
_login = login;
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
ViewBag.IsLoggedIn = IsLoggedIn();
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet("/login")]
|
||||
public IActionResult Login(string? username, string? password)
|
||||
{
|
||||
if (username is null || password is null || !_login.ValidateCredentials(username, password))
|
||||
return StatusCode(403);
|
||||
|
||||
var expiresAt = DateTimeOffset.UtcNow.AddDays(90).ToUnixTimeSeconds();
|
||||
Response.Cookies.Append(SessionCookie, expiresAt.ToString(), new CookieOptions
|
||||
{
|
||||
MaxAge = TimeSpan.FromDays(90),
|
||||
});
|
||||
Response.Cookies.Append(SessionSignCookie, _login.SignSession(expiresAt), new CookieOptions
|
||||
{
|
||||
MaxAge = TimeSpan.FromDays(90),
|
||||
});
|
||||
|
||||
return Redirect("/membre/games-editor/today");
|
||||
}
|
||||
|
||||
[HttpGet("games-editor/today")]
|
||||
public async Task<IActionResult> GamesEditorToday()
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
var games = await _games.GetAllGames();
|
||||
var today = DateOnly.FromDateTime(TimeZoneInfo.ConvertTime(
|
||||
DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("America/New_York")));
|
||||
|
||||
var lastGameDay = games
|
||||
.Where(g => DateOnly.Parse(g.Date) <= today)
|
||||
.Select(g => g.Date)
|
||||
.OrderByDescending(d => d)
|
||||
.FirstOrDefault();
|
||||
|
||||
ViewBag.SelectedYear = (int?)null;
|
||||
ViewBag.IsToday = true;
|
||||
ViewBag.Years = games.Select(g => g.Year).Distinct().OrderByDescending(y => y).ToList();
|
||||
ViewBag.Games = games.Where(g => g.Date == lastGameDay).ToList();
|
||||
return PartialView("GamesEditor");
|
||||
}
|
||||
|
||||
[HttpGet("games-editor/{year:int}")]
|
||||
public async Task<IActionResult> GamesEditorByYear(int year)
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
var games = await _games.GetAllGames();
|
||||
ViewBag.SelectedYear = year;
|
||||
ViewBag.IsToday = false;
|
||||
ViewBag.Years = games.Select(g => g.Year).Distinct().OrderByDescending(y => y).ToList();
|
||||
ViewBag.Games = games.Where(g => g.Year == year).ToList();
|
||||
return PartialView("GamesEditor");
|
||||
}
|
||||
|
||||
[HttpGet("new-game-editor")]
|
||||
public IActionResult NewGameEditor()
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
return PartialView();
|
||||
}
|
||||
|
||||
[HttpPost("new-game")]
|
||||
public async Task<IActionResult> NewGame(string gameDate, string gameTime, string homeTeam, string awayTeam)
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
|
||||
var (game, error) = await _games.CreateNewGame(gameDate, gameTime, homeTeam, awayTeam);
|
||||
|
||||
if (error != "")
|
||||
{
|
||||
ViewBag.Error = error;
|
||||
return StatusCode(500, PartialView("NewGameError"));
|
||||
}
|
||||
|
||||
Response.Headers["game-id"] = game!.Id;
|
||||
return PartialView("SingleGameEditor", game);
|
||||
}
|
||||
|
||||
[HttpDelete("games/{gameId}")]
|
||||
public async Task<IActionResult> DeleteGame(string gameId)
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
var ok = await _games.DeleteGameById(gameId);
|
||||
return Content(ok ? "true" : "false");
|
||||
}
|
||||
|
||||
[HttpPost("games/{gameId}")]
|
||||
public async Task<IActionResult> UpdateGame(string gameId, int? awayScore, int? homeScore, string? gameType)
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
var success = await _games.UpdateGame(gameId, homeScore, awayScore,
|
||||
rain: gameType == "rain", practice: gameType == "practice");
|
||||
return Content(success
|
||||
? "<i class=\"fa fa-floppy-o\" aria-hidden=\"true\"></i>"
|
||||
: "<i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>");
|
||||
}
|
||||
|
||||
[HttpPost("games/{gameId}/switch")]
|
||||
public async Task<IActionResult> SwitchVisitors(string gameId)
|
||||
{
|
||||
if (!IsLoggedIn()) return Redirect("/membre");
|
||||
var success = await _games.SwitchVisitors(gameId);
|
||||
if (!success)
|
||||
return Content("<i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>");
|
||||
|
||||
var game = await _games.GetGameById(gameId);
|
||||
Response.Headers["game-id"] = gameId;
|
||||
return PartialView("SingleGameEditor", game);
|
||||
}
|
||||
|
||||
private bool IsLoggedIn()
|
||||
{
|
||||
Request.Cookies.TryGetValue(SessionCookie, out var expires);
|
||||
Request.Cookies.TryGetValue(SessionSignCookie, out var sig);
|
||||
return _login.VerifySession(expires, sig);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Phenix.Models;
|
||||
|
||||
public class Game
|
||||
{
|
||||
public string Id { get; set; } = "";
|
||||
public string Date { get; set; } = "";
|
||||
public string Time { get; set; } = "";
|
||||
public string Home { get; set; } = "";
|
||||
public string Away { get; set; } = "";
|
||||
public int Year { get; set; }
|
||||
public int? HomeScore { get; set; }
|
||||
public int? AwayScore { get; set; }
|
||||
public bool Practice { get; set; }
|
||||
public bool Rain { get; set; }
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Phenix.Models;
|
||||
|
||||
public class TeamSelectorModel
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
public string SelectedTeam { get; set; } = "";
|
||||
public bool IsDisabled { get; set; }
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RootNamespace>Phenix</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
<PackageReference Include="Npgsql" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
using Phenix.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
WebRootPath = "static",
|
||||
});
|
||||
|
||||
builder.Services
|
||||
.AddControllersWithViews()
|
||||
.AddRazorOptions(o =>
|
||||
{
|
||||
o.ViewLocationFormats.Clear();
|
||||
o.ViewLocationFormats.Add("/Views/{1}/{0}.cshtml");
|
||||
o.ViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
|
||||
o.ViewLocationFormats.Add("/Views/{0}.cshtml");
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton<IGameService>(sp =>
|
||||
{
|
||||
var config = sp.GetRequiredService<IConfiguration>();
|
||||
var connStr = config.GetConnectionString("Default")
|
||||
?? "Data Source=phenix.db";
|
||||
var provider = config["DatabaseProvider"] ?? "Sqlite";
|
||||
|
||||
IGameService svc = provider.ToLowerInvariant() switch
|
||||
{
|
||||
"postgres" or "postgresql" => new PostgresGameService(connStr),
|
||||
_ => new SqliteGameService(connStr),
|
||||
};
|
||||
svc.Init().GetAwaiter().GetResult();
|
||||
return svc;
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton(sp =>
|
||||
{
|
||||
var key = sp.GetRequiredService<IConfiguration>()["SessionKey"] ?? "dev-only";
|
||||
return new LoginService(key);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
@@ -1,39 +1,41 @@
|
||||
# Site Web de [Balle Phénix](http://ballephenix.com)
|
||||
# Site Web de Balle Phénix
|
||||

|
||||
|
||||
## Stack
|
||||
|
||||
- **ASP.NET Core 9** — Razor Views (`Views/*.cshtml`), contrôleurs dans `Controllers/`
|
||||
- **SQLite** par défaut (`phenix.db`), Postgres au choix via `DatabaseProvider`
|
||||
- **Nix** — build et déploiement via `flake.nix` (service NixOS, domaine `ballephenix.com`)
|
||||
- Les assets statiques vivent dans `static/` et sont servis par `app.config.WebRootPath = "static"`
|
||||
## introduction
|
||||
|
||||
## Développement
|
||||
Vous trouverez le code source du site web pour les Phénix ici. Le site web
|
||||
en lui-même est accessible au https://didiercrunch.gitlab.io/phenix-website/.
|
||||
|
||||
```shell
|
||||
dotnet run
|
||||
```
|
||||
### Structure du site web.
|
||||
|
||||
Base de données SQLite par défaut (`phenix.db`). La config se règle dans `appsettings.json`
|
||||
(ou par variables d'environnement en prod, voir le module NixOS dans `flake.nix`).
|
||||
Premièrement, mille excuses pour mes choix hétéroclites. J'ai décidé d'explorer
|
||||
de nouvels technologies avec ce projet. En conséquence, le code est un peu
|
||||
difficile à comprendre à première vue mais il est __tellement__ plus cool!
|
||||
|
||||
Pour peupler une instance locale depuis la prod:
|
||||
|
||||
```shell
|
||||
python dev/populate-db/populate.py --source https://ballephenix.com --target http://localhost:5000 --force
|
||||
```
|
||||
#### Choix
|
||||
|
||||
## Déploiement
|
||||
* mithril.js comme framework dans le fureteur
|
||||
* require.js pour les dépendances
|
||||
* uikit avec sass comme framework css
|
||||
* gulp pour la compilation
|
||||
* gitlab pour le deployment
|
||||
|
||||
Le build et le service NixOS sont décrits dans `flake.nix` (`packages.website` et
|
||||
`nixosModules.x86_64-linux`). Le module déploie le binaire `Phenix` avec `static/`
|
||||
et une base de données dans `/var/lib/phenix`.
|
||||
---
|
||||
|
||||
## Outils d'administration
|
||||
# English Version
|
||||
|
||||
- `debut_saison.ts` — script Deno qui crée le calendrier de la saison: se connecte
|
||||
via `GET /login` puis POST chaque partie à `/membre/new-game`. Mettre à jour les
|
||||
identifiants en haut du fichier et les dates avant de le lancer.
|
||||
All the source code is in english. The source code is for a static web
|
||||
side for The softball league 'Balle Phénix'.
|
||||
|
||||
```shell
|
||||
deno run -A debut_saison.ts
|
||||
```
|
||||
## How to build
|
||||
|
||||
$ npm install
|
||||
$ node_modules/.bin/gulp help
|
||||
|
||||
# How it is made
|
||||
|
||||
* mithril.js as client side framework
|
||||
* uikit as css framework
|
||||
* coffee and love
|
||||
@@ -1,15 +0,0 @@
|
||||
using Phenix.Models;
|
||||
|
||||
namespace Phenix.Services;
|
||||
|
||||
public interface IGameService
|
||||
{
|
||||
Task Init();
|
||||
Task<List<Game>> GetAllGames();
|
||||
Task<Game?> GetGameById(string id);
|
||||
Task<(Game? Game, string Error)> CreateNewGame(string date, string time, string home, string away);
|
||||
Task<bool> UpdateGame(string id, int? homeScore, int? awayScore, bool? rain, bool? practice);
|
||||
Task<bool> DeleteGameById(string id);
|
||||
Task<bool> SwitchVisitors(string id);
|
||||
Task ClearAllGames();
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Phenix.Services;
|
||||
|
||||
public class LoginService
|
||||
{
|
||||
private readonly Dictionary<string, string> _users;
|
||||
private readonly string _sessionKey;
|
||||
|
||||
private static readonly (string User, string Hash)[] OfficialUsers =
|
||||
[
|
||||
("marqueur", "34373780cc542a1eddb6a08488ec149323b94d66025421acd98ffc20eb5055a0:6f2fa05777d45a2da9db79b7fd11e3bc69eb1807642ccb53d41a0b9eb71a3311"),
|
||||
("comite", "8649feff48a50f53448e59ce480db97b5549eef1d92c886c49b5a14ee22648e5:a0017b879c8834d2f34938e7a4fa3f4c7be8f70545b9bb22a28cf56ab2eb26d9"),
|
||||
];
|
||||
|
||||
public LoginService(string sessionKey)
|
||||
{
|
||||
_users = OfficialUsers.ToDictionary(x => x.User, x => x.Hash);
|
||||
_sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public bool ValidateCredentials(string username, string password)
|
||||
{
|
||||
if (!_users.TryGetValue(username, out var hashWithSalt))
|
||||
return false;
|
||||
return VerifyPassword(password, hashWithSalt);
|
||||
}
|
||||
|
||||
public string SignSession(long expiresAt)
|
||||
{
|
||||
return ShittyHmac(expiresAt.ToString(), _sessionKey);
|
||||
}
|
||||
|
||||
public bool VerifySession(string? expiresAt, string? signature)
|
||||
{
|
||||
if (expiresAt is null || signature is null)
|
||||
return false;
|
||||
if (!long.TryParse(expiresAt, out var ts))
|
||||
return false;
|
||||
if (signature != ShittyHmac(ts.ToString(), _sessionKey))
|
||||
return false;
|
||||
return DateTimeOffset.UtcNow.ToUnixTimeSeconds() < ts;
|
||||
}
|
||||
|
||||
private static bool VerifyPassword(string password, string hashWithSalt)
|
||||
{
|
||||
var parts = hashWithSalt.Split(':');
|
||||
if (parts.Length != 2) return false;
|
||||
var salt = parts[0];
|
||||
var expected = parts[1];
|
||||
return ShittyHmac(password, salt) == expected;
|
||||
}
|
||||
|
||||
private static string HashMessage(string message)
|
||||
{
|
||||
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(message));
|
||||
return Convert.ToHexStringLower(bytes);
|
||||
}
|
||||
|
||||
private static string ShittyHmac(string message, string salt)
|
||||
{
|
||||
var h1 = HashMessage(message + salt);
|
||||
var h2 = HashMessage(salt + message);
|
||||
return HashMessage(h1 + h2);
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
using System.Data.Common;
|
||||
using Npgsql;
|
||||
using Phenix.Models;
|
||||
|
||||
namespace Phenix.Services;
|
||||
|
||||
public class PostgresGameService : IGameService
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
public PostgresGameService(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
public async Task Init()
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
CREATE TABLE IF NOT EXISTS games (
|
||||
id TEXT PRIMARY KEY,
|
||||
date TEXT NOT NULL,
|
||||
time TEXT NOT NULL,
|
||||
home TEXT NOT NULL,
|
||||
away TEXT NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
home_score INTEGER,
|
||||
away_score INTEGER,
|
||||
practice BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
rain BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
UNIQUE(date, time)
|
||||
)
|
||||
""";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Game>> GetAllGames()
|
||||
{
|
||||
var games = new List<Game>();
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT * FROM games ORDER BY date, time";
|
||||
await using var reader = await cmd.ExecuteReaderAsync();
|
||||
while (await reader.ReadAsync())
|
||||
games.Add(ReadGame(reader));
|
||||
return games;
|
||||
}
|
||||
|
||||
public async Task<Game?> GetGameById(string id)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT * FROM games WHERE id = @id";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
await using var reader = await cmd.ExecuteReaderAsync();
|
||||
if (await reader.ReadAsync())
|
||||
return ReadGame(reader);
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<(Game? Game, string Error)> CreateNewGame(string date, string time, string home, string away)
|
||||
{
|
||||
date = CleanDate(date);
|
||||
time = CleanTime(time);
|
||||
|
||||
if (!DateOnly.TryParse(date, out _))
|
||||
return (null, $"Invalide date format {date}");
|
||||
if (!TimeOnly.TryParse(time, out _))
|
||||
return (null, $"Invalide time format {time}");
|
||||
if (!ValidTeams.Contains(away))
|
||||
return (null, $"Invalide away format {away}");
|
||||
if (!ValidTeams.Contains(home))
|
||||
return (null, $"Invalide home format {home}");
|
||||
if (home == away)
|
||||
return (null, $"Home and away teams must be different (received {home} for both)");
|
||||
|
||||
var year = DateOnly.Parse(date).Year;
|
||||
var game = new Game
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
Date = date,
|
||||
Time = time,
|
||||
Home = home,
|
||||
Away = away,
|
||||
Year = year,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
INSERT INTO games (id, date, time, home, away, year)
|
||||
VALUES (@id, @date, @time, @home, @away, @year)
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@id", game.Id);
|
||||
cmd.Parameters.AddWithValue("@date", game.Date);
|
||||
cmd.Parameters.AddWithValue("@time", game.Time);
|
||||
cmd.Parameters.AddWithValue("@home", game.Home);
|
||||
cmd.Parameters.AddWithValue("@away", game.Away);
|
||||
cmd.Parameters.AddWithValue("@year", game.Year);
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
catch (PostgresException ex) when (ex.SqlState == "23505")
|
||||
{
|
||||
return (null, "game already exists at this date/time");
|
||||
}
|
||||
|
||||
return (game, "");
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateGame(string id, int? homeScore, int? awayScore, bool? rain, bool? practice)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
UPDATE games SET
|
||||
home_score = COALESCE(@homeScore, home_score),
|
||||
away_score = COALESCE(@awayScore, away_score),
|
||||
rain = COALESCE(@rain, rain),
|
||||
practice = COALESCE(@practice, practice)
|
||||
WHERE id = @id
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
cmd.Parameters.AddWithValue("@homeScore", (object?)homeScore ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@awayScore", (object?)awayScore ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@rain", rain ?? (object?)DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@practice", practice ?? (object?)DBNull.Value);
|
||||
return await cmd.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteGameById(string id)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "DELETE FROM games WHERE id = @id";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
return await cmd.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task ClearAllGames()
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "DELETE FROM games";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> SwitchVisitors(string id)
|
||||
{
|
||||
var game = await GetGameById(id);
|
||||
if (game is null) return false;
|
||||
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
UPDATE games SET home = @home, away = @away,
|
||||
home_score = @homeScore, away_score = @awayScore
|
||||
WHERE id = @id
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
cmd.Parameters.AddWithValue("@home", game.Away);
|
||||
cmd.Parameters.AddWithValue("@away", game.Home);
|
||||
cmd.Parameters.AddWithValue("@homeScore", (object?)game.AwayScore ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@awayScore", (object?)game.HomeScore ?? DBNull.Value);
|
||||
return await cmd.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
private static Game ReadGame(DbDataReader r) => new()
|
||||
{
|
||||
Id = r.GetString(r.GetOrdinal("id")),
|
||||
Date = r.GetString(r.GetOrdinal("date")),
|
||||
Time = r.GetString(r.GetOrdinal("time")),
|
||||
Home = r.GetString(r.GetOrdinal("home")),
|
||||
Away = r.GetString(r.GetOrdinal("away")),
|
||||
Year = r.GetInt32(r.GetOrdinal("year")),
|
||||
HomeScore = r.IsDBNull(r.GetOrdinal("home_score")) ? null : r.GetInt32(r.GetOrdinal("home_score")),
|
||||
AwayScore = r.IsDBNull(r.GetOrdinal("away_score")) ? null : r.GetInt32(r.GetOrdinal("away_score")),
|
||||
Practice = r.GetBoolean(r.GetOrdinal("practice")),
|
||||
Rain = r.GetBoolean(r.GetOrdinal("rain")),
|
||||
};
|
||||
|
||||
private static readonly string[] ValidTeams =
|
||||
["jaune", "rouge", "bleu", "gris", "vert", "noir", "orange", "mauve"];
|
||||
|
||||
private static string CleanDate(string raw)
|
||||
{
|
||||
var parts = raw.Split('-');
|
||||
if (parts.Length != 3) return raw;
|
||||
return $"{parts[0]}-{parts[1].PadLeft(2, '0')}-{parts[2].PadLeft(2, '0')}";
|
||||
}
|
||||
|
||||
private static string CleanTime(string raw)
|
||||
{
|
||||
var sep = raw.Contains('h') ? 'h' : ':';
|
||||
var parts = raw.Split(sep);
|
||||
if (parts.Length != 2) return raw;
|
||||
return $"{parts[0].PadLeft(2, '0')}:{parts[1].PadLeft(2, '0')}";
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Phenix.Models;
|
||||
|
||||
namespace Phenix.Services;
|
||||
|
||||
public class SqliteGameService : IGameService
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
public SqliteGameService(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
public async Task Init()
|
||||
{
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
CREATE TABLE IF NOT EXISTS games (
|
||||
id TEXT PRIMARY KEY,
|
||||
date TEXT NOT NULL,
|
||||
time TEXT NOT NULL,
|
||||
home TEXT NOT NULL,
|
||||
away TEXT NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
home_score INTEGER,
|
||||
away_score INTEGER,
|
||||
practice INTEGER NOT NULL DEFAULT 0,
|
||||
rain INTEGER NOT NULL DEFAULT 0,
|
||||
UNIQUE(date, time)
|
||||
)
|
||||
""";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Game>> GetAllGames()
|
||||
{
|
||||
var games = new List<Game>();
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT * FROM games ORDER BY date, time";
|
||||
await using var reader = await cmd.ExecuteReaderAsync();
|
||||
while (await reader.ReadAsync())
|
||||
games.Add(ReadGame(reader));
|
||||
return games;
|
||||
}
|
||||
|
||||
public async Task<Game?> GetGameById(string id)
|
||||
{
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT * FROM games WHERE id = @id";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
await using var reader = await cmd.ExecuteReaderAsync();
|
||||
if (await reader.ReadAsync())
|
||||
return ReadGame(reader);
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<(Game? Game, string Error)> CreateNewGame(string date, string time, string home, string away)
|
||||
{
|
||||
date = CleanDate(date);
|
||||
time = CleanTime(time);
|
||||
|
||||
if (!DateOnly.TryParse(date, out _))
|
||||
return (null, $"Invalide date format {date}");
|
||||
if (!TimeOnly.TryParse(time, out _))
|
||||
return (null, $"Invalide time format {time}");
|
||||
if (!ValidTeams.Contains(away))
|
||||
return (null, $"Invalide away format {away}");
|
||||
if (!ValidTeams.Contains(home))
|
||||
return (null, $"Invalide home format {home}");
|
||||
if (home == away)
|
||||
return (null, $"Home and away teams must be different (received {home} for both)");
|
||||
|
||||
var year = DateOnly.Parse(date).Year;
|
||||
var game = new Game
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
Date = date,
|
||||
Time = time,
|
||||
Home = home,
|
||||
Away = away,
|
||||
Year = year,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
INSERT INTO games (id, date, time, home, away, year)
|
||||
VALUES (@id, @date, @time, @home, @away, @year)
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@id", game.Id);
|
||||
cmd.Parameters.AddWithValue("@date", game.Date);
|
||||
cmd.Parameters.AddWithValue("@time", game.Time);
|
||||
cmd.Parameters.AddWithValue("@home", game.Home);
|
||||
cmd.Parameters.AddWithValue("@away", game.Away);
|
||||
cmd.Parameters.AddWithValue("@year", game.Year);
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
catch (SqliteException ex) when (ex.SqliteErrorCode == 19)
|
||||
{
|
||||
return (null, "game already exists at this date/time");
|
||||
}
|
||||
|
||||
return (game, "");
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateGame(string id, int? homeScore, int? awayScore, bool? rain, bool? practice)
|
||||
{
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
UPDATE games SET
|
||||
home_score = COALESCE(@homeScore, home_score),
|
||||
away_score = COALESCE(@awayScore, away_score),
|
||||
rain = COALESCE(@rain, rain),
|
||||
practice = COALESCE(@practice, practice)
|
||||
WHERE id = @id
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
cmd.Parameters.AddWithValue("@homeScore", (object?)homeScore ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@awayScore", (object?)awayScore ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@rain", rain ?? (object?)DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@practice", practice ?? (object?)DBNull.Value);
|
||||
return await cmd.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteGameById(string id)
|
||||
{
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "DELETE FROM games WHERE id = @id";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
return await cmd.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task ClearAllGames()
|
||||
{
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "DELETE FROM games";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> SwitchVisitors(string id)
|
||||
{
|
||||
var game = await GetGameById(id);
|
||||
if (game is null) return false;
|
||||
|
||||
await using var conn = new SqliteConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
UPDATE games SET home = @home, away = @away,
|
||||
home_score = @homeScore, away_score = @awayScore
|
||||
WHERE id = @id
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@id", id);
|
||||
cmd.Parameters.AddWithValue("@home", game.Away);
|
||||
cmd.Parameters.AddWithValue("@away", game.Home);
|
||||
cmd.Parameters.AddWithValue("@homeScore", (object?)game.AwayScore ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@awayScore", (object?)game.HomeScore ?? DBNull.Value);
|
||||
return await cmd.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
private static Game ReadGame(DbDataReader r) => new()
|
||||
{
|
||||
Id = r.GetString(r.GetOrdinal("id")),
|
||||
Date = r.GetString(r.GetOrdinal("date")),
|
||||
Time = r.GetString(r.GetOrdinal("time")),
|
||||
Home = r.GetString(r.GetOrdinal("home")),
|
||||
Away = r.GetString(r.GetOrdinal("away")),
|
||||
Year = r.GetInt32(r.GetOrdinal("year")),
|
||||
HomeScore = r.IsDBNull(r.GetOrdinal("home_score")) ? null : r.GetInt32(r.GetOrdinal("home_score")),
|
||||
AwayScore = r.IsDBNull(r.GetOrdinal("away_score")) ? null : r.GetInt32(r.GetOrdinal("away_score")),
|
||||
Practice = r.GetBoolean(r.GetOrdinal("practice")),
|
||||
Rain = r.GetBoolean(r.GetOrdinal("rain")),
|
||||
};
|
||||
|
||||
private static readonly string[] ValidTeams =
|
||||
["jaune", "rouge", "bleu", "gris", "vert", "noir", "orange", "mauve"];
|
||||
|
||||
private static string CleanDate(string raw)
|
||||
{
|
||||
var parts = raw.Split('-');
|
||||
if (parts.Length != 3) return raw;
|
||||
return $"{parts[0]}-{parts[1].PadLeft(2, '0')}-{parts[2].PadLeft(2, '0')}";
|
||||
}
|
||||
|
||||
private static string CleanTime(string raw)
|
||||
{
|
||||
var sep = raw.Contains('h') ? 'h' : ':';
|
||||
var parts = raw.Split(sep);
|
||||
if (parts.Length != 2) return raw;
|
||||
return $"{parts[0].PadLeft(2, '0')}:{parts[1].PadLeft(2, '0')}";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Tab"] = "calendrier";
|
||||
}
|
||||
|
||||
<div id="mithril-content"></div>
|
||||
<script type=module src="scripts/calendar.js"></script>
|
||||
@@ -1,36 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Tab"] = "contact";
|
||||
}
|
||||
|
||||
<div class="uk-width-large-2-5 uk-width-medium-4-5 uk-width-small-1-1 uk-container-center">
|
||||
<div class="uk-grid uk-margin">
|
||||
<div class="uk-width-1-1">
|
||||
<div style="height: 300px; width: 300px; background-size: 300px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div uk-panel uk-panel-box uk-panel-box-secondary uk-container-center uk-margin">
|
||||
<table class="uk-table">
|
||||
<tr>
|
||||
<td class="uk-text-right"><i class="fa fa-desktop"></i></td>
|
||||
<td><a href="mailto:sportsphenixmtl@gmail.com">sportsphenixmtl@gmail.com</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="uk-text-right"><i class="fa fa-phone"></i></td>
|
||||
<td> (514) 838-8950</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="uk-text-right"><i class="fa fa-envelope"></i></td>
|
||||
<td>
|
||||
<p> 10454 Sylvain-Garneau<br>Montréal, Québec H1C 0A2</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="uk-text-right"><i class="fa fa-gitlab"></i></td>
|
||||
<td>
|
||||
<p> Le site web est ouvert et accessible sur <a href="https://gitlab.com/ballephenix/website">gitlab.</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,103 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Tab"] = "home";
|
||||
}
|
||||
|
||||
<script type="module" src="scripts/little-calendar.js"></script>
|
||||
|
||||
<div class="uk-grid">
|
||||
<div class="uk-large-1-3 uk-medium-2-3 uk-container-center">
|
||||
<div style="height:300px; width: 300px; background-size: 300px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center uk-margin-left uk-margin-top"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-margin-top uk-margin-bottom uk-grid">
|
||||
<div class="uk-width-large-3-5 uk-width-medium-4-5 uk-width-small-1-1 uk-container-center">
|
||||
<div class="uk-grid uk-visible-large uk-grid-match">
|
||||
<div class="uk-width-large-1-3 uk-width-medium-1-3">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge">
|
||||
<i class="fa fa-newspaper-o" style="font-size: 1.7em;"></i>
|
||||
</div>
|
||||
<div>
|
||||
<partial name="HomeNews" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-large-1-3 uk-width-medium-1-3">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-calendar" style="font-size: 1.7em;"></i></div>
|
||||
<h3 class="uk-panel-title"><a href="#/calendrier" class="uk-link-muted">Calendrier</a></h3>
|
||||
<div id="large-mithril-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-large-1-3 uk-width-medium-1-3">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-map-o" style="font-size: 1.7em;"></i></div>
|
||||
<h3 class="uk-panel-title">Parc Walter-Stewart</h3>
|
||||
<partial name="WalterStewartMap" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-visible-medium">
|
||||
<div class="uk-grid uk-grid-match">
|
||||
<div class="uk-width-medium-1-2">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-newspaper-o" style="font-size: 1.7em;"></i></div>
|
||||
<div>
|
||||
<partial name="HomeNews" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-medium-1-2">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-calendar" style="font-size: 1.7em;"></i></div>
|
||||
<h3 class="uk-panel-title"><a href="#/calendrier" class="uk-link-muted">Calendrier</a></h3>
|
||||
<div id="medium-mithril-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-medium-1-1">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-map-o" style="font-size: 1.7em;"></i></div>
|
||||
<h3 class="uk-panel-title">Parc Walter-Stewart</h3>
|
||||
<partial name="WalterStewartMap" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-visible-small">
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-small-1-1">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-newspaper-o" style="font-size: 1.7em;"></i></div>
|
||||
<div>
|
||||
<partial name="HomeNews" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-small-1-1">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-calendar" style="font-size: 1.7em;"></i></div>
|
||||
<h3 class="uk-panel-title"><a href="#/calendrier" class="uk-link-muted">Calendrier</a></h3>
|
||||
<div id="small-mithril-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-small-1-1">
|
||||
<div class="uk-panel uk-panel-box">
|
||||
<div class="uk-panel-badge uk-badge"><i class="fa fa-map-o" style="font-size: 1.7em;"></i></div>
|
||||
<h3 class="uk-panel-title">Parc Walter-Stewart</h3>
|
||||
<partial name="WalterStewartMap" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,64 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Tab"] = "nouvelles";
|
||||
}
|
||||
|
||||
<div class="uk-width-large-2-5 uk-width-medium-3-5 uk-width-small-1-1 uk-container-center">
|
||||
<div>
|
||||
<article class="uk-article uk-margin-">
|
||||
<h1 class="uk-article-title">
|
||||
<h2 id="pre-inscription">Pré-inscription</h2>
|
||||
</h1>
|
||||
<p class="uk-article-meta">
|
||||
<p>Samedi 8 Août 2026</p>
|
||||
</p>
|
||||
<p>
|
||||
La pré-inscription pour la balle-molle Phénix est maintenant ouverte. Ça ne coûte rien et c'est sans prix!
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://forms.gle/Mv2wCVdbP83uiMdC7">https://forms.gle/Mv2wCVdbP83uiMdC7</a>
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-width-large-2-5 uk-width-medium-3-5 uk-width-small-1-1 uk-container-center">
|
||||
<div>
|
||||
<article class="uk-article uk-margin-">
|
||||
<h1 class="uk-article-title">
|
||||
<h2 id="saison-2025">Saison 2026</h2>
|
||||
</h1>
|
||||
<p class="uk-article-meta">
|
||||
<p>Lundi 9 Mars 2026</p>
|
||||
</p>
|
||||
<p>
|
||||
La saison de la balle annonce à grand pas et les inscriptions débuteront lundi prochain (16 mars 2026). Le coût de la saison sera le même que l'an passé: 155$ pour la saison + 20$ de dépôt remboursable pour le prêt du chandail.
|
||||
</p>
|
||||
<p>
|
||||
Comme à l'habitude, nous jouerons au parc walter-stewart les jeudis soir. La ligue comptera quatre équipes pour un grand total de 44 joueurs.
|
||||
</p>
|
||||
<p>
|
||||
Les inscriptions en présentiel auront lieu le vendredi 20 mars au bar fullum entre 18h00 et 21h00. Pour ceux qui veulle venir prendre une petite bière avec nous ou payer en argent compten.
|
||||
</p>
|
||||
<p>
|
||||
On vous tiens au courrant!
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-width-large-2-5 uk-width-medium-3-5 uk-width-small-1-1 uk-container-center">
|
||||
<div>
|
||||
<article class="uk-article uk-margin-">
|
||||
<h1 class="uk-article-title">
|
||||
<h2 id="saison-2025">Saison 2025</h2>
|
||||
</h1>
|
||||
<p class="uk-article-meta">
|
||||
<p>Vendredi 25 Avril 2025</p>
|
||||
</p>
|
||||
<p>Bonne saison à tous et toutes!</p>
|
||||
<p>N'oubliez pas de consulter la page facebook: <a href="https://www.facebook.com/SportsPhenixMtl/">https://www.facebook.com/SportsPhenixMtl/</a> pour toutes mises à jour, y compris les annulations due à la météo.</p>
|
||||
<p>Votre Comité 2023</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,43 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Tab"] = "reglement";
|
||||
}
|
||||
|
||||
<div class="uk-margin-top uk-margin-bottom uk-grid">
|
||||
<div class="uk-width-large-3-5 uk-width-medium-4-5 uk-width-large-1-1 uk-container-center">
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-large-1-3 uk-width-small-1-1">
|
||||
<div style="height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center"></div>
|
||||
</div>
|
||||
<div class="uk-width-large-2-3 uk-width-small-1-1">
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary">
|
||||
<h2>Règlements 2021</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<h3><a href="files/regle_de_jeux_2021.pdf">Règles de jeu</a></h3>
|
||||
</li>
|
||||
<li>
|
||||
<h3><a href="files/regles_et_procedures_2021.pdf">Règles et procédures</a></h3>
|
||||
</li>
|
||||
<li>
|
||||
<h3><a href="files/charte_organisationnelle_2021.pdf">Charte Organisationnelle</a></h3>
|
||||
</li>
|
||||
<li>
|
||||
<h3><a href="files/formulaire_inscription_2021.pdf">Formulaire d'inscription</a></h3>
|
||||
</li>
|
||||
<li>
|
||||
<h3><a href="files/code_ethique_2021.pdf">Code d'éthique</a></h3>
|
||||
</li>
|
||||
<li>
|
||||
<h3><a href="http://www.asbm.ca/">Association des Sports de Balle à Montréal (ASBN)</a></h3>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary">
|
||||
<h2>Mission</h2>
|
||||
<p>La ligue de balle Les Phénix a été fondée en 2004 afin d'offrir aux membres de la communauté gaie et lesbienne et à leurs amis hétéros l'opportunité de s'amuser et de pratiquer un sport dans une ambiance amicale et décontractée. L'ouverture d'esprit, la camaraderie et le plaisir de pratiquer un sport à l'extérieur caractérisent cette ligue.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,36 +0,0 @@
|
||||
@{
|
||||
var isToday = ViewBag.IsToday == true;
|
||||
var years = (List<int>)ViewBag.Years;
|
||||
var games = (List<Phenix.Models.Game>)ViewBag.Games;
|
||||
var selectedYear = (int?)ViewBag.SelectedYear;
|
||||
}
|
||||
|
||||
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||
<div class="uk-margin" style="margin-top: 1em">
|
||||
<ul class="uk-tab">
|
||||
<li class="@(isToday ? "uk-active" : "")">
|
||||
<a hx-get="/membre/games-editor/today" hx-target="#content">Aujourd'hui</a>
|
||||
</li>
|
||||
@foreach (var year in years)
|
||||
{
|
||||
<li class="@(year == selectedYear ? "uk-active" : "")">
|
||||
<a hx-get="/membre/games-editor/@year" hx-target="#content">Saison @year</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@foreach (var game in games)
|
||||
{
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||
<partial name="GameEditor" model="game" />
|
||||
</div>
|
||||
}
|
||||
|
||||
<hr>
|
||||
<button class="uk-button"
|
||||
hx-get="/membre/new-game-editor"
|
||||
hx-target="#content">
|
||||
Nouvelle Partie
|
||||
</button>
|
||||
</div>
|
||||
@@ -1,28 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Tab"] = "membre";
|
||||
}
|
||||
|
||||
<div id="content"
|
||||
@if (ViewBag.IsLoggedIn == true)
|
||||
{
|
||||
@:hx-get="/membre/games-editor/today"
|
||||
@:hx-trigger="load"
|
||||
@:hx-target="#content"
|
||||
}>
|
||||
<div class="uk-grid uk-margin">
|
||||
<div class="uk-width-1-1">
|
||||
<div style="height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-width-large-1-3 uk-container-center uk-margin">
|
||||
<form action=""
|
||||
class="uk-text-center"
|
||||
hx-get="/login"
|
||||
hx-target="#content">
|
||||
<div class="uk-form-row"><label>Nom d'utilisateur <input type="text" name="username" class="uk-form-width-small"></label></div>
|
||||
<div class="uk-form-row"><label>Mot de passe <input type="password" name="password" class="uk-form-width-small"></label></div>
|
||||
<div class="uk-form-row"><button class="uk-button"><i class="fa fa-mars-double"></i> Pénétrez</button></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,35 +0,0 @@
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||
<div class="uk-margin"></div>
|
||||
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||
<form hx-post="/membre/new-game"
|
||||
hx-target="#created-game"
|
||||
hx-swap="afterbegin">
|
||||
<div class="uk-form-row" style="text-align: center; font-size: 2em;">
|
||||
<partial name="TeamSelector" model='new Phenix.Models.TeamSelectorModel { Name = "awayTeam" }' />
|
||||
<label>Vs.</label>
|
||||
<partial name="TeamSelector" model='new Phenix.Models.TeamSelectorModel { Name = "homeTeam" }' />
|
||||
</div>
|
||||
|
||||
<div class="uk-form-row">
|
||||
<label>Date: <input type=date name="gameDate" required></label>
|
||||
</div>
|
||||
|
||||
<div class="uk-form-row">
|
||||
<label>Heure: <input type="time" name="gameTime"></label>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div style="text-align: right;">
|
||||
<button class="uk-button">Creer</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="created-game"></div>
|
||||
</div>
|
||||
@@ -1,9 +0,0 @@
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||
<pre>@ViewBag.Error</pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +0,0 @@
|
||||
@model Phenix.Models.Game
|
||||
|
||||
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||
<partial name="GameEditor" model="Model" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,53 +0,0 @@
|
||||
@model Phenix.Models.Game
|
||||
@{
|
||||
var prettyDate = DateOnly.Parse(Model.Date).ToString("d MMMM yyyy", new System.Globalization.CultureInfo("fr-CA"));
|
||||
}
|
||||
|
||||
<div id="game-@Model.Id">
|
||||
<h3>@Model.Away vs @Model.Home | @prettyDate | @Model.Time</h3>
|
||||
<form style="font-size: 1.1em;"
|
||||
hx-trigger="input delay:250ms"
|
||||
hx-post="/membre/games/@Model.Id"
|
||||
hx-target="#saving-result">
|
||||
<div class="uk-form-row">
|
||||
<label>
|
||||
Points @Model.Away : <input type=number min=0 name="awayScore"
|
||||
value="@(Model.AwayScore ?? 0)"
|
||||
disabled="@(Model.Rain || Model.Practice ? true : null)">
|
||||
</label>
|
||||
</div>
|
||||
<div class="uk-form-row">
|
||||
<label>
|
||||
Points @Model.Home : <input type=number min=0 name="homeScore"
|
||||
value="@(Model.HomeScore ?? 0)"
|
||||
disabled="@(Model.Rain || Model.Practice ? true : null)">
|
||||
</label>
|
||||
</div>
|
||||
<div class="uk-form-row">
|
||||
<label>
|
||||
Partie reguliere <input type=radio name="gameType" value="regular-game"
|
||||
checked="@(!Model.Practice && !Model.Rain ? true : null)">
|
||||
</label>
|
||||
<label>
|
||||
Pluie <input type=radio name="gameType" value="rain"
|
||||
checked="@(Model.Rain ? true : null)">
|
||||
</label>
|
||||
<label>
|
||||
Pratique <input type=radio name="gameType" value="practice"
|
||||
checked="@(Model.Practice && !Model.Rain ? true : null)">
|
||||
</label>
|
||||
</div>
|
||||
<div id="saving-result"></div>
|
||||
</form>
|
||||
|
||||
<div style="text-align: right">
|
||||
<button class="uk-button"
|
||||
hx-post="/membre/games/@Model.Id/switch"
|
||||
hx-target="#game-@Model.Id">Inverser visiteur/receveur</button>
|
||||
<button class="uk-button-danger"
|
||||
hx-delete="/membre/games/@Model.Id"
|
||||
hx-confirm="Certain de voulez supprimer la partie?"
|
||||
hx-target="#game-@Model.Id"
|
||||
hx-swap="delete">Supprimer</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,9 +0,0 @@
|
||||
<h3 class="uk-panel-title">
|
||||
<a href="/nouvelles" class="uk-link-muted">
|
||||
<h2 id="pre-inscription">Pré-inscription</h2>
|
||||
</a>
|
||||
</h3>
|
||||
<p>
|
||||
Pré-inscription pour la balle-molle Phénix, ça ne coûte rien et c'est sans prix! <a href="https://forms.gle/Mv2wCVdbP83uiMdC7">https://forms.gle/Mv2wCVdbP83uiMdC7</a>
|
||||
</p>
|
||||
<p><strong><a href="/nouvelles">lire la suite ...</a></strong></p>
|
||||
@@ -1,11 +0,0 @@
|
||||
@model Phenix.Models.TeamSelectorModel
|
||||
@{
|
||||
var teams = new[] { "jaune", "rouge", "bleu", "gris", "vert", "noir", "orange", "mauve" };
|
||||
}
|
||||
|
||||
<select name="@Model.Name" class="uk-select" disabled="@(Model.IsDisabled)">
|
||||
@foreach (var team in teams)
|
||||
{
|
||||
<option value="@team" selected="@(Model.SelectedTeam == team)">@team</option>
|
||||
}
|
||||
</select>
|
||||
@@ -1,14 +0,0 @@
|
||||
<div>
|
||||
<iframe
|
||||
style="border: 1px solid black; min-height: 300px;"
|
||||
width="100%"
|
||||
frameborder="0"
|
||||
scrolling="no"
|
||||
marginheight="0"
|
||||
src="//www.openstreetmap.org/export/embed.html?bbox=-73.55936229228975%2C45.53102667048665%2C-73.55230271816255%2C45.53444249585723&layer=mapnik">
|
||||
</iframe>
|
||||
<br>
|
||||
<small>
|
||||
<a href="http://www.openstreetmap.org/#map=17/45.53216/-73.55692">Voir la carte</a>
|
||||
</small>
|
||||
</div>
|
||||
@@ -1,86 +0,0 @@
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Balle Phenix</title>
|
||||
<link rel="shortcut icon" href="/images/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="/scripts/jquery-3.7.1.min.js"></script>
|
||||
<script src="/scripts/uikit.min.js"></script>
|
||||
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="uk-navbar uk-navbar-attached">
|
||||
<ul class="uk-navbar-nav uk-visible-large uk-navbar-content uk-navbar-center">
|
||||
<li class="uk-parent">
|
||||
<div class="uk-navbar-brand"><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></div>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "home" ? "uk-active" : "")">
|
||||
<a href="/"><div><i class="fa fa-home"></i> Accueil</div></a>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "nouvelles" ? "uk-active" : "")">
|
||||
<a href="/nouvelles"><div><i class="fa fa-newspaper-o"></i> Nouvelles</div></a>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "calendrier" ? "uk-active" : "")">
|
||||
<a href="/calendrier"><div><i class="fa fa-calendar"></i> Calendrier</div></a>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "reglement" ? "uk-active" : "")">
|
||||
<a href="/reglement"><div><i class="fa fa-legal"></i> Règlement</div></a>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "membre" ? "uk-active" : "")">
|
||||
<a href="/membre"><div><i class="fa fa-lock"></i> Membre</div></a>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "contact" ? "uk-active" : "")">
|
||||
<a href="/contact"><div><i class="fa fa-phone"></i> Nous Joindre</div></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="uk-navbar-nav uk-visible-medium">
|
||||
<li class="uk-parent">
|
||||
<div class="uk-navbar-brand"><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></div>
|
||||
</li>
|
||||
<li class="@((ViewData["Tab"] as string) == "home" ? "uk-active" : "")"><a href="/"><i class="fa fa-home"></i> Accueil </a></li>
|
||||
<li class="@((ViewData["Tab"] as string) == "nouvelles" ? "uk-active" : "")"><a href="/nouvelles"><i class="fa fa-newspaper-o"></i> Nouvelles</a></li>
|
||||
<li class="@((ViewData["Tab"] as string) == "calendrier" ? "uk-active" : "")"><a href="/calendrier"><i class="fa fa-calendar"></i> Calendrier</a></li>
|
||||
<li class="@((ViewData["Tab"] as string) == "reglement" ? "uk-active" : "")"><a href="/reglement"><i class="fa fa-legal"></i> Règlement</a></li>
|
||||
<li class="@((ViewData["Tab"] as string) == "membre" ? "uk-active" : "")"><a href="/membre"><i class="fa fa-lock"></i> Membre</a></li>
|
||||
<li class="@((ViewData["Tab"] as string) == "contact" ? "uk-active" : "")"><a href="/contact"><i class="fa fa-phone"></i> Nous Joindre</a></li>
|
||||
</ul>
|
||||
<ul class="uk-navbar-nav uk-visible-small">
|
||||
<li class="uk-parent">
|
||||
<div class="uk-navbar-brand"><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></div>
|
||||
</li>
|
||||
<li data-uk-dropdown="" aria-expanded="" class="uk-parent"><a><i class="fa fa-bars"></i> Menu</a>
|
||||
<div class="uk-dropdown">
|
||||
<ul class="uk-nav uk-nav-navbar uk-dropdown-navbar">
|
||||
<li class="uk-active"><a href="/"><i class="fa fa-home"></i> Accueil</a></li>
|
||||
<li class=""><a href="/nouvelles"><i class="fa fa-newspaper-o"></i> Nouvelles</a></li>
|
||||
<li class=""><a href="/calendrier"><i class="fa fa-calendar"></i> Calendrier</a></li>
|
||||
<li class=""><a href="/reglement"><i class="fa fa-legal"></i> Règlement</a></li>
|
||||
<li class=""><a href="/membre"><i class="fa fa-lock"></i> Membre</a></li>
|
||||
<li class=""><a href="/contact"><i class="fa fa-phone"></i> Nous Joindre</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@RenderBody()
|
||||
|
||||
<footer class="uk-grid ph-footer" style="padding: 40px;">
|
||||
<div class="uk-container uk-container-center uk-text-center">
|
||||
<div class="uk-panel"><span class="uk-hidden-small">Ligue de balle les Phénix... pour le plaisir de jouer!</span>
|
||||
<h4 class="uk-visible-small">Ligue de balle les Phénix</h4>
|
||||
</div>
|
||||
<ul class="uk-subnav uk-subnav-line uk-flex-center">
|
||||
<li><a href="mailto:sportsphenixmtl@gmail.com">sportsphenixmtl@gmail.com</a></li>
|
||||
</ul>
|
||||
<h1><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></h1>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@@ -1,3 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"DatabaseProvider": "Sqlite",
|
||||
"ConnectionStrings": {
|
||||
"Default": "Data Source=phenix.db"
|
||||
},
|
||||
"SessionKey": "dev-only"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "phenix-website",
|
||||
"description": "Main web site of Balle Phénix.",
|
||||
"main": "index.html",
|
||||
"authors": [
|
||||
"didier amyot <didier.amyot@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"moduleType": [],
|
||||
"homepage": "",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"lib",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"uikit": "~2.24.3",
|
||||
"mithril": "~0.2.1",
|
||||
"lodash": "~4.2.1",
|
||||
"almond": "~0.3.1",
|
||||
"requirejs": "~2.1.22"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
({
|
||||
baseUrl: "script",
|
||||
paths: {
|
||||
m: '../lib/mithril/mithril.min',
|
||||
_: '../lib/lodash/dist/lodash.min',
|
||||
requireLib: '../lib/requirejs/require'
|
||||
},
|
||||
include: 'main',
|
||||
name: "../lib/almond/almond",
|
||||
out: "main-built.js"
|
||||
})
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Balle Phenix</title>
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
|
||||
<script src="lib/mithril/mithril.min.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="uk-navbar">
|
||||
<div class="uk-navbar-content uk-navbar-center">
|
||||
<ul class="uk-navbar-nav">
|
||||
<li class="uk-parent">
|
||||
<a href="https://www.facebook.com/LigueDeBalleLesPhenix">
|
||||
<i class="fa fa-facebook-square"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="uk-parent"><a href="/">Acceuil</a></li>
|
||||
<li class="uk-active"><a href="">Calendrier</a></li>
|
||||
<li class="uk-parent"><a>Règlements</a></li>
|
||||
<li class="uk-parent"><a>Photos</a></li>
|
||||
<li class="uk-parent"><a>Membre</a></li>
|
||||
<li class="uk-parent"><a>Nous Joindre</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-1-5"></div>
|
||||
<div class="uk-width-3-5">
|
||||
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-5-5">
|
||||
<h2>Classement 2015</h2>
|
||||
<table class="uk-table uk-table-hover uk-table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Équipes</th>
|
||||
<th>PJ</th>
|
||||
<th>V</th>
|
||||
<th>D</th>
|
||||
<th>N</th>
|
||||
<th>PP</th>
|
||||
<th>PC</th>
|
||||
<th>DIF</th>
|
||||
<th>PTS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Verts</td>
|
||||
<td>14</td>
|
||||
<td>11</td>
|
||||
<td>3</td>
|
||||
<td>0</td>
|
||||
<td>161</td>
|
||||
<td>108</td>
|
||||
<td>+53</td>
|
||||
<td>22</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Verts</td>
|
||||
<td>14</td>
|
||||
<td>11</td>
|
||||
<td>3</td>
|
||||
<td>0</td>
|
||||
<td>161</td>
|
||||
<td>108</td>
|
||||
<td>+53</td>
|
||||
<td>22</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Verts</td>
|
||||
<td>14</td>
|
||||
<td>11</td>
|
||||
<td>3</td>
|
||||
<td>0</td>
|
||||
<td>161</td>
|
||||
<td>108</td>
|
||||
<td>+53</td>
|
||||
<td>22</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Verts</td>
|
||||
<td>14</td>
|
||||
<td>11</td>
|
||||
<td>3</td>
|
||||
<td>0</td>
|
||||
<td>161</td>
|
||||
<td>108</td>
|
||||
<td>+53</td>
|
||||
<td>22</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="uk-subnav uk-subnav-line uk-flex-center">
|
||||
<li>PJ : Parties joués </li><li> V : Victoire </li><li> D : Défaite </li><li> N : Nul </li><li> PP : Points pour </li><li> PC : Points contre </li><li> DIF : Diférenciel </li><li> PTS : Points </li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-grid">
|
||||
<div class="uk-width-3-5">
|
||||
<h2>Calendrier 2015</h2>
|
||||
<h3 style="text-align: left;">5 mai 2016</h3>
|
||||
<table class="uk-table uk-table-hover uk-table-condensed uk-table-striped">
|
||||
<tr>
|
||||
<td>18h30</td>
|
||||
<td><i class="fa fa-flag" style="color: purple;"></i> Mauve</td>
|
||||
<td>8</td>
|
||||
<td>vs</td>
|
||||
<td><i class="fa fa-flag" style="color: red;"></i> Rouge</td>
|
||||
<td>7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>18h30</td>
|
||||
<td><i class="fa fa-flag" style="color: yellow;"></i> Jaune</td>
|
||||
<td>00</td>
|
||||
<td>vs</td>
|
||||
<td><i class="fa fa-flag" style="color: gray;"></i> Gris</td>
|
||||
<td>00</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="uk-width-1-5"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<footer class="uk-grid ph-footer" style="padding: 80px;">
|
||||
<div class="uk-container uk-container-center uk-text-center">
|
||||
<div class="uk-panel">
|
||||
Ligue de balle les Phénix … pour le plaisir de jouer!
|
||||
</div>
|
||||
<ul class="uk-subnav uk-subnav-line uk-flex-center">
|
||||
<li><a href="mailto:info@ballephenix.com">info@ballephenix.com</a></li>
|
||||
</ul>
|
||||
<h1>
|
||||
<a href="https://www.facebook.com/LigueDeBalleLesPhenix">
|
||||
<i class="fa fa-facebook-square"></i>
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,59 @@
|
||||
[title]
|
||||
innerMarkdown = """
|
||||
## Inscription 2016!
|
||||
"""
|
||||
|
||||
[meta]
|
||||
innerMarkdown = """
|
||||
Lundi 14 mars 2016
|
||||
"""
|
||||
|
||||
[body]
|
||||
innerMarkdown = """
|
||||
|
||||
Bonjour à tous les phénixiens phénixiennes.
|
||||
|
||||
Eh bien oui l'hiver tire à ça fin et il sera bientôt temps de sortir gants et
|
||||
batons (en bon français mites et battes) pour jouer à notre sport préféré:
|
||||
la balle-molle.
|
||||
|
||||
|
||||
**L'inscription aura lieu le vendredi 18 mars 2016 de 19h30 à 21h30 à la [taverne
|
||||
le normandie](http://bit.ly/1pmNWu8)**; situé au [1295 rue amherst,
|
||||
Montréal](http://bit.ly/1QUC6Ou). Il s'agit de l'endroit ou nous avons fêté la
|
||||
fin de la dernière saison.
|
||||
|
||||
|
||||
Le prix de l'inscription est de 110$ incluant la location du chandail au coût de
|
||||
10$. La valeur de la location du chandail vous sera rendu en fin de saison
|
||||
lorsque vous le rendrez.
|
||||
|
||||
Pour ceux et celles qui ne pourront être présent à l'inscription, vous pouvez
|
||||
vous inscrire par courrier. Imprimez, remplissez et envoyez le formulaire
|
||||
avec le chèque.
|
||||
|
||||
|
||||
Nous avons très hâte de vous y voir et de fêter avec vous!!!
|
||||
|
||||
|
||||
Votre comité de balle les phénix.
|
||||
|
||||
"""
|
||||
|
||||
[smallBody]
|
||||
innerMarkdown = """
|
||||
Bonjour à tous les phénixiens phénixiennes.
|
||||
|
||||
Eh bien oui l'hiver tire à ça fin et il sera bientôt temps de sortir gants et
|
||||
batons (en bon français mites et battes) pour jouer à notre sport préféré:
|
||||
la balle-molle.
|
||||
|
||||
|
||||
**L'inscription aura lieu le vendredi 18 mars 2016 de 19h30 à 21h30 à la [taverne
|
||||
le normandie](http://bit.ly/1pmNWu8)**; situé au [1295 rue amherst,
|
||||
Montréal](http://bit.ly/1QUC6Ou). Il s'agit de l'endroit ou nous avons fêté la
|
||||
fin de la dernière saison.
|
||||
|
||||
**[lire la suite ...](#/nouvelles)**
|
||||
|
||||
"""
|
||||
@@ -0,0 +1,289 @@
|
||||
---
|
||||
-
|
||||
email: fleet80@hickle.org
|
||||
name: "Delle Emmerich"
|
||||
score: 2
|
||||
team: rouge
|
||||
tel: 613-805-2793x858
|
||||
-
|
||||
email: qschamberger@yahoo.com
|
||||
name: "Susie Quitzon MD"
|
||||
score: 3
|
||||
team: rouge
|
||||
tel: 1-332-714-0777x97469
|
||||
-
|
||||
email: kianna90@yahoo.com
|
||||
name: "Johnathan Leuschke"
|
||||
score: 5
|
||||
team: jaune
|
||||
tel: 974-275-2040
|
||||
-
|
||||
email: susannah.grant@hotmail.com
|
||||
name: "Dr. Wendell Sporer"
|
||||
score: 3
|
||||
team: rouge
|
||||
tel: 04691879363
|
||||
-
|
||||
email: millicent46@adams.info
|
||||
name: "Emile Powlowski II"
|
||||
score: 1
|
||||
team: bleu
|
||||
tel: 1-449-950-7363x2633
|
||||
-
|
||||
email: cormier.codi@hotmail.com
|
||||
name: "Gardner Willms"
|
||||
score: 2
|
||||
team: bleu
|
||||
tel: 625-516-1325
|
||||
-
|
||||
email: kamryn.kovacek@gmail.com
|
||||
name: "Aliya Vandervort"
|
||||
score: 4
|
||||
team: rouge
|
||||
tel: "250.915.3706"
|
||||
-
|
||||
email: marian97@beahan.org
|
||||
name: "Gaige Kautzer"
|
||||
score: 2
|
||||
team: gris
|
||||
tel: "298.694.0319"
|
||||
-
|
||||
email: patsy.kerluke@satterfieldberge.com
|
||||
name: "Orilla Brakus"
|
||||
score: 5
|
||||
team: rouge
|
||||
tel: (506)015-3098x8355
|
||||
-
|
||||
email: alpha30@connelly.com
|
||||
name: "Dr. Thurman O'Hara"
|
||||
score: 5
|
||||
team: bleu
|
||||
tel: 07469452414
|
||||
-
|
||||
email: thompson.willene@gmail.com
|
||||
name: "Rachael Medhurst DDS"
|
||||
score: 2
|
||||
team: rouge
|
||||
tel: 1-602-031-0376
|
||||
-
|
||||
email: inader@kunze.info
|
||||
name: "Mr. Ingram Thompson"
|
||||
score: 2
|
||||
team: rouge
|
||||
tel: (109)873-9483x211
|
||||
-
|
||||
email: desiree.harris@gmail.com
|
||||
name: "Dr. Saul Streich Jr."
|
||||
score: 5
|
||||
team: gris
|
||||
tel: 1-249-486-6759x84328
|
||||
-
|
||||
email: samir83@hills.com
|
||||
name: "Kimberley Kihn"
|
||||
score: 5
|
||||
team: jaune
|
||||
tel: 304.586.6687x3262
|
||||
-
|
||||
email: egrady@emmerichpadberg.com
|
||||
name: "Arra Boyer"
|
||||
score: 3
|
||||
team: gris
|
||||
tel: "485.730.8331"
|
||||
-
|
||||
email: bgoodwin@gmail.com
|
||||
name: "Miss Kaylan Robel DVM"
|
||||
score: 4
|
||||
team: gris
|
||||
tel: "321.945.7155"
|
||||
-
|
||||
email: angelic86@homenick.com
|
||||
name: "Kyson Ruecker"
|
||||
score: 4
|
||||
team: bleu
|
||||
tel: 1-017-690-5278
|
||||
-
|
||||
email: val.sawayn@gmail.com
|
||||
name: "Shaun Goodwin"
|
||||
score: 3
|
||||
team: jaune
|
||||
tel: (271)085-2639x251
|
||||
-
|
||||
email: kya.wunsch@gmail.com
|
||||
name: "Mr. Denzell Casper"
|
||||
score: 2
|
||||
team: bleu
|
||||
tel: 948-754-1786x17035
|
||||
-
|
||||
email: delmus18@stoltenberg.org
|
||||
name: "Bluford Marvin Jr."
|
||||
score: 2
|
||||
team: jaune
|
||||
tel: (268)984-3065x3634
|
||||
-
|
||||
email: kihn.zackery@gmail.com
|
||||
name: "Lucio Kub"
|
||||
score: 2
|
||||
team: jaune
|
||||
tel: 185-942-2355x8756
|
||||
-
|
||||
email: jade24@aufderharkuhic.com
|
||||
name: "Mr. Justice Pollich DVM"
|
||||
score: 1
|
||||
team: bleu
|
||||
tel: 1-918-319-1713
|
||||
-
|
||||
email: vgoyette@hotmail.com
|
||||
name: "Bose Ankunding"
|
||||
score: 4
|
||||
team: gris
|
||||
tel: "265.582.6145"
|
||||
-
|
||||
email: raltenwerth@lueilwitz.com
|
||||
name: "Harlen Harber"
|
||||
score: 1
|
||||
team: jaune
|
||||
tel: (081)424-2803
|
||||
-
|
||||
email: thiel.bode@reynolds.info
|
||||
name: "Linnie Abshire"
|
||||
score: 1
|
||||
team: rouge
|
||||
tel: 1-809-325-8148x5271
|
||||
-
|
||||
email: istracke@lueilwitz.com
|
||||
name: "Mr. Juwan Zemlak"
|
||||
score: 5
|
||||
team: jaune
|
||||
tel: 982.535.6849x5299
|
||||
-
|
||||
email: boysie44@hartmanngraham.com
|
||||
name: "Mr. Tahj Bernhard"
|
||||
score: 1
|
||||
team: rouge
|
||||
tel: +57(9)5038029147
|
||||
-
|
||||
email: harm91@dare.net
|
||||
name: "Dr. Lyle Lakin PhD"
|
||||
score: 4
|
||||
team: bleu
|
||||
tel: 079-078-9724
|
||||
-
|
||||
email: prosacco.dolphus@dickens.com
|
||||
name: "Bertram Schuster"
|
||||
score: 4
|
||||
team: gris
|
||||
tel: (917)409-8168x00826
|
||||
-
|
||||
email: elian04@stroman.com
|
||||
name: "Viviana Howell"
|
||||
score: 5
|
||||
team: rouge
|
||||
tel: 1-414-103-3954x02444
|
||||
-
|
||||
email: hakim08@hotmail.com
|
||||
name: "Marques Goodwin"
|
||||
score: 1
|
||||
team: rouge
|
||||
tel: (649)195-3556x81548
|
||||
-
|
||||
email: nigel.kilback@gmail.com
|
||||
name: "Rayfield Lubowitz"
|
||||
score: 2
|
||||
team: bleu
|
||||
tel: (231)457-7181
|
||||
-
|
||||
email: rogahn.tollie@lehnerwillms.com
|
||||
name: "Miss Luz Altenwerth"
|
||||
score: 3
|
||||
team: gris
|
||||
tel: 00248382520
|
||||
-
|
||||
email: reilly.velia@hansenhegmann.com
|
||||
name: "Lilly Brekke"
|
||||
score: 1
|
||||
team: rouge
|
||||
tel: 006.284.1261x54374
|
||||
-
|
||||
email: batz.dessa@rippin.org
|
||||
name: "Jay Aufderhar"
|
||||
score: 3
|
||||
team: rouge
|
||||
tel: 960-144-7624x406
|
||||
-
|
||||
email: garth.barton@kerluke.com
|
||||
name: "Ms. Contina Pfeffer DDS"
|
||||
score: 5
|
||||
team: jaune
|
||||
tel: (352)043-9218x9064
|
||||
-
|
||||
email: mmcglynn@gusikowski.com
|
||||
name: "Robyn Lakin"
|
||||
score: 1
|
||||
team: bleu
|
||||
tel: 667-492-9674x3911
|
||||
-
|
||||
email: breinger@yahoo.com
|
||||
name: "Latonia Kuhlman"
|
||||
score: 2
|
||||
team: bleu
|
||||
tel: 404.860.5529x107
|
||||
-
|
||||
email: jamarion.sipes@gmail.com
|
||||
name: "Dr. Camryn Goyette"
|
||||
score: 4
|
||||
team: bleu
|
||||
tel: 648-481-0991x380
|
||||
-
|
||||
email: consuelo37@gmail.com
|
||||
name: "Khloe Altenwerth"
|
||||
score: 4
|
||||
team: gris
|
||||
tel: 1-480-994-8256x873
|
||||
-
|
||||
email: icie.kohler@murphyrohan.com
|
||||
name: "Pearl Dicki"
|
||||
score: 1
|
||||
team: rouge
|
||||
tel: +04(3)0376370559
|
||||
-
|
||||
email: miya43@yahoo.com
|
||||
name: "Christoper Botsford"
|
||||
score: 2
|
||||
team: gris
|
||||
tel: (731)031-5128x77337
|
||||
-
|
||||
email: xschmidt@yahoo.com
|
||||
name: "Lauren Bins"
|
||||
score: 1
|
||||
team: gris
|
||||
tel: (503)215-2332x77244
|
||||
-
|
||||
email: rempel.earley@waelchi.net
|
||||
name: "Sigmund Stroman"
|
||||
score: 4
|
||||
team: rouge
|
||||
tel: (719)103-8927x0887
|
||||
-
|
||||
email: gustav.graham@kihn.com
|
||||
name: "Brook Nolan"
|
||||
score: 2
|
||||
team: gris
|
||||
tel: "642.931.3403"
|
||||
-
|
||||
email: hettinger.emit@cartwright.com
|
||||
name: "Mr. Gaston Bartell"
|
||||
score: 5
|
||||
team: jaune
|
||||
tel: "00536147705"
|
||||
-
|
||||
email: tlittle@marquardtfunk.info
|
||||
name: "Ansel Schimmel"
|
||||
score: 3
|
||||
team: bleu
|
||||
tel: (432)161-1237
|
||||
-
|
||||
email: blangosh@hotmail.com
|
||||
name: "Kiefer Funk"
|
||||
score: 3
|
||||
team: rouge
|
||||
tel: 224-921-0391x3813
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
-
|
||||
date: ~
|
||||
time: ~
|
||||
home: gris
|
||||
away: jaune
|
||||
home_points: ~
|
||||
away_points: !
|
||||
|
||||
-
|
||||
date: ~
|
||||
time: ~
|
||||
home: bleu
|
||||
away: rouge
|
||||
home_points: ~
|
||||
away_points: ~
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
const URL = "https://ballephenix.com";
|
||||
const USERNAME = "XXXXXX";
|
||||
const PASSWORD = "XXXXXX";
|
||||
|
||||
type PreGame = {
|
||||
date: string;
|
||||
time: string;
|
||||
home: string;
|
||||
away: string;
|
||||
};
|
||||
|
||||
class WeekDay {
|
||||
readonly year: number;
|
||||
readonly month: number;
|
||||
readonly day: number;
|
||||
|
||||
constructor(iso: string) {
|
||||
const [y, m, d] = iso.split("-").map(Number);
|
||||
this.year = y;
|
||||
this.month = m;
|
||||
this.day = d;
|
||||
}
|
||||
|
||||
next(): WeekDay {
|
||||
const d = new Date(this.year, this.month - 1, this.day + 7);
|
||||
return new WeekDay(
|
||||
`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`,
|
||||
);
|
||||
}
|
||||
|
||||
saturday(): WeekDay {
|
||||
const d = new Date(this.year, this.month - 1, this.day + 2);
|
||||
return new WeekDay(
|
||||
`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`,
|
||||
);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `${this.year}-${String(this.month).padStart(2, "0")}-${String(this.day).padStart(2, "0")}`;
|
||||
}
|
||||
}
|
||||
|
||||
const w1 = new WeekDay("2026-05-14");
|
||||
const w2 = w1.next();
|
||||
const w3 = w2.next();
|
||||
const w4 = w3.next();
|
||||
// skip Saint-Jean
|
||||
const w5 = w4.next().next();
|
||||
const w6 = w5.next();
|
||||
const w7 = w6.next();
|
||||
const w8 = w7.next();
|
||||
const w9 = w8.next();
|
||||
const w10 = w9.next();
|
||||
const w11 = w10.next();
|
||||
const w12 = w11.next();
|
||||
// const tournament = w12.saturday();
|
||||
const w13 = w12.next();
|
||||
const w14 = w13.next();
|
||||
|
||||
const games: PreGame[] = [
|
||||
{ date: `${w1}`, time: "18:45", home: "gris", away: "bleu" },
|
||||
{ date: `${w1}`, time: "20:15", home: "mauve", away: "jaune" },
|
||||
|
||||
{ date: `${w2}`, time: "18:45", home: "jaune", away: "gris" },
|
||||
{ date: `${w2}`, time: "20:15", home: "bleu", away: "mauve" },
|
||||
|
||||
{ date: `${w3}`, time: "18:45", home: "gris", away: "mauve" },
|
||||
{ date: `${w3}`, time: "20:15", home: "jaune", away: "bleu" },
|
||||
|
||||
{ date: `${w4}`, time: "18:45", home: "mauve", away: "bleu" },
|
||||
{ date: `${w4}`, time: "20:15", home: "gris", away: "jaune" },
|
||||
|
||||
{ date: `${w5}`, time: "18:45", home: "bleu", away: "jaune" },
|
||||
{ date: `${w5}`, time: "20:15", home: "mauve", away: "gris" },
|
||||
|
||||
{ date: `${w6}`, time: "18:45", home: "jaune", away: "mauve" },
|
||||
{ date: `${w6}`, time: "20:15", home: "bleu", away: "gris" },
|
||||
|
||||
{ date: `${w7}`, time: "18:45", home: "gris", away: "bleu" },
|
||||
{ date: `${w7}`, time: "20:15", home: "mauve", away: "jaune" },
|
||||
|
||||
{ date: `${w8}`, time: "18:45", home: "jaune", away: "gris" },
|
||||
{ date: `${w8}`, time: "20:15", home: "bleu", away: "mauve" },
|
||||
|
||||
{ date: `${w9}`, time: "18:45", home: "gris", away: "mauve" },
|
||||
{ date: `${w9}`, time: "20:15", home: "jaune", away: "bleu" },
|
||||
|
||||
{ date: `${w10}`, time: "18:45", home: "mauve", away: "bleu" },
|
||||
{ date: `${w10}`, time: "20:15", home: "gris", away: "jaune" },
|
||||
{ date: `${w10}`, time: "21:35", home: "jaune", away: "gris" },
|
||||
|
||||
{ date: `${w11}`, time: "18:45", home: "bleu", away: "jaune" },
|
||||
{ date: `${w11}`, time: "20:15", home: "mauve", away: "gris" },
|
||||
|
||||
{ date: `${w12}`, time: "18:45", home: "jaune", away: "mauve" },
|
||||
{ date: `${w12}`, time: "20:15", home: "bleu", away: "gris" },
|
||||
|
||||
// { date: `${tournament}`, time: "09:00", home: "gris", away: "bleu" },
|
||||
// { date: `${tournament}`, time: "10:30", home: "mauve", away: "jaune" },
|
||||
// { date: `${tournament}`, time: "15:30", home: "bleu", away: "mauve" },
|
||||
|
||||
{ date: `${w13}`, time: "18:45", home: "gris", away: "mauve" },
|
||||
{ date: `${w13}`, time: "20:15", home: "jaune", away: "bleu" },
|
||||
|
||||
{ date: `${w14}`, time: "18:45", home: "gris", away: "bleu" },
|
||||
{ date: `${w14}`, time: "20:15", home: "mauve", away: "jaune" },
|
||||
];
|
||||
|
||||
function extractCookies(headers: Headers): string {
|
||||
const cookies: string[] = [];
|
||||
for (const value of headers.getSetCookie()) {
|
||||
cookies.push(value.split(";")[0]);
|
||||
}
|
||||
return cookies.join("; ");
|
||||
}
|
||||
|
||||
async function login(): Promise<string> {
|
||||
const res = await fetch(
|
||||
`${URL}/login?username=${encodeURIComponent(USERNAME)}&password=${encodeURIComponent(PASSWORD)}`,
|
||||
{ redirect: "manual" },
|
||||
);
|
||||
if (res.status !== 302) {
|
||||
throw new Error(`Login failed with status ${res.status}`);
|
||||
}
|
||||
return extractCookies(res.headers);
|
||||
}
|
||||
|
||||
async function createGame(cookie: string, game: PreGame): Promise<void> {
|
||||
const body = new URLSearchParams({
|
||||
"game-date": game.date,
|
||||
"game-time": game.time,
|
||||
"home-team": game.home,
|
||||
"away-team": game.away,
|
||||
});
|
||||
|
||||
const res = await fetch(`${URL}/membre/new-game`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
Cookie: cookie,
|
||||
},
|
||||
body: body.toString(),
|
||||
redirect: "manual",
|
||||
});
|
||||
|
||||
if (res.status >= 400) {
|
||||
const text = await res.text();
|
||||
throw new Error(
|
||||
`Failed to create ${game.date} ${game.time} ${game.home} vs ${game.away}: ${text}`,
|
||||
);
|
||||
}
|
||||
|
||||
await res.body?.cancel();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log("Logging in...");
|
||||
const cookie = await login();
|
||||
console.log("Logged in.\n");
|
||||
|
||||
for (const game of games) {
|
||||
console.log(
|
||||
`Creating: ${game.date} ${game.time} ${game.home} vs ${game.away}`,
|
||||
);
|
||||
await createGame(cookie, game);
|
||||
}
|
||||
|
||||
console.log(`\nDone. ${games.length} games created.`);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,12 +0,0 @@
|
||||
{ fetchNuGet }: [
|
||||
(fetchNuGet { pname = "Microsoft.Data.Sqlite"; version = "9.0.0"; sha256 = "0m58j9cdrkk8m0yl24z8jy3iafxfbwmf3v01cwhwnqs0cbq1ara8"; })
|
||||
(fetchNuGet { pname = "Microsoft.Data.Sqlite.Core"; version = "9.0.0"; sha256 = "11s3pf12x4ghi1xn2dv6dsj3ckxq062m82dcinn2l42z590ny5fg"; })
|
||||
(fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "8.0.0"; sha256 = "1zw0bpp5742jzx03wvqc8csnvsbgdqi0ls9jfc5i2vd3cl8b74pg"; })
|
||||
(fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "8.0.0"; sha256 = "1klcqhg3hk55hb6vmjiq2wgqidsl81aldw0li2z98lrwx26msrr6"; })
|
||||
(fetchNuGet { pname = "Npgsql"; version = "8.0.0"; sha256 = "1x3jlin44frkhd7d50q0vmy0gapxqhmd4jv1nvsnkndp3xjsaynd"; })
|
||||
(fetchNuGet { pname = "SQLitePCLRaw.bundle_e_sqlite3"; version = "2.1.10"; sha256 = "1irrg46sv2w12nh6jc810clbi06fgclnbky14b8kamfkgy61d4li"; })
|
||||
(fetchNuGet { pname = "SQLitePCLRaw.core"; version = "2.1.10"; sha256 = "03q02p1cajqzcbk9112mgw3qq733l4gd2vi21dq2am4911imr5l2"; })
|
||||
(fetchNuGet { pname = "SQLitePCLRaw.lib.e_sqlite3"; version = "2.1.10"; sha256 = "0xqa3l4p68vm3p5n4h3d2gs97vrpnvhwfv366i6fv5x80m2zcswv"; })
|
||||
(fetchNuGet { pname = "SQLitePCLRaw.provider.e_sqlite3"; version = "2.1.10"; sha256 = "0n7cdwix5h9k578a07g00sw9c03sv4liy91qzpj9wb8k4673gfrh"; })
|
||||
(fetchNuGet { pname = "System.Memory"; version = "4.5.3"; sha256 = "0naqahm3wljxb5a911d37mwjqjdxv9l0b49p5dmfyijvni2ppy8a"; })
|
||||
]
|
||||
@@ -1,90 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
def fetch_json(api_root, path):
|
||||
url = f"{api_root}{path}"
|
||||
resp = requests.get(url, timeout=30)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Populate a local instance from production data via REST"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--source",
|
||||
default=os.environ.get("PHENIX_SOURCE_URL", "https://ballephenix.com"),
|
||||
help="Source API root (default: https://ballephenix.com)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--target",
|
||||
default=os.environ.get("PHENIX_TARGET_URL", "http://localhost:5000"),
|
||||
help="Target API root (default: http://localhost:5000)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--force",
|
||||
action="store_true",
|
||||
help="Clear existing games before inserting",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
source_root = args.source.rstrip("/")
|
||||
target_root = args.target.rstrip("/")
|
||||
|
||||
years = fetch_json(source_root, "/api/available-years.json")
|
||||
print(f"Years on source: {len(years)} ({min(years)}–{max(years)})")
|
||||
|
||||
all_games = []
|
||||
for year in years:
|
||||
games = fetch_json(source_root, f"/api/results/{year}.json")
|
||||
all_games.extend(games)
|
||||
print(f"Total games fetched: {len(all_games)}")
|
||||
|
||||
if args.force:
|
||||
resp = requests.delete(f"{target_root}/api/games", timeout=30)
|
||||
if resp.status_code not in (204, 200):
|
||||
print(f"Failed to clear games: {resp.status_code} {resp.text}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
print("Cleared existing games")
|
||||
|
||||
inserted = 0
|
||||
skipped = 0
|
||||
errors = 0
|
||||
|
||||
for g in all_games:
|
||||
payload = {
|
||||
"date": g.get("date", ""),
|
||||
"time": g.get("time", ""),
|
||||
"home": g.get("home", ""),
|
||||
"away": g.get("away", ""),
|
||||
"homeScore": g.get("homeScore"),
|
||||
"awayScore": g.get("awayScore"),
|
||||
"practice": bool(g.get("practice")),
|
||||
"rain": bool(g.get("rain")),
|
||||
}
|
||||
|
||||
try:
|
||||
resp = requests.post(f"{target_root}/api/games", json=payload, timeout=30)
|
||||
if resp.status_code == 201:
|
||||
inserted += 1
|
||||
elif resp.status_code == 409:
|
||||
skipped += 1
|
||||
else:
|
||||
print(f"Error on {g.get('date')} {g.get('time')}: {resp.status_code} {resp.text}", file=sys.stderr)
|
||||
errors += 1
|
||||
except requests.RequestException as e:
|
||||
print(f"Request error on {g.get('date')} {g.get('time')}: {e}", file=sys.stderr)
|
||||
errors += 1
|
||||
|
||||
print(f"Inserted: {inserted}, skipped: {skipped}, errors: {errors}")
|
||||
print(f"Target: {target_root}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Generated
-60
@@ -1,60 +0,0 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1719848872,
|
||||
"narHash": "sha256-H3+EC5cYuq+gQW8y0lSrrDZfH71LB4DAf+TDFyvwCNA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "00d80d13810dbfea8ab4ed1009b09100cca86ba8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
{
|
||||
description = "Balle Phenix website — ASP.NET + SQLite";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils, ... }:
|
||||
let
|
||||
nixosModule = { config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.all-dressed-programming.phenix-website;
|
||||
phenix = self.packages.${pkgs.system}.website;
|
||||
in {
|
||||
options.services.all-dressed-programming.phenix-website = {
|
||||
enable = lib.mkEnableOption "Balle Phenix website";
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ballephenix.com";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8000;
|
||||
};
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/phenix";
|
||||
};
|
||||
databaseUrl = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
};
|
||||
sessionKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.phenix-website = {
|
||||
description = "Balle Phenix website";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${phenix}/lib/Phenix";
|
||||
WorkingDirectory = "${phenix}/lib/";
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
User = "phenix";
|
||||
Group = "phenix";
|
||||
};
|
||||
|
||||
environment =
|
||||
{
|
||||
ASPNETCORE_URLS = "http://0.0.0.0:${toString cfg.port}";
|
||||
ASPNETCORE_ENVIRONMENT = "Production";
|
||||
}
|
||||
// lib.optionalAttrs (cfg.databaseUrl == "") {
|
||||
ConnectionStrings__Default = "Data Source=${cfg.dataDir}/phenix.db";
|
||||
}
|
||||
// lib.optionalAttrs (cfg.databaseUrl != "") {
|
||||
DatabaseProvider = "Postgres";
|
||||
ConnectionStrings__Default = cfg.databaseUrl;
|
||||
}
|
||||
// lib.optionalAttrs (cfg.sessionKey != "") {
|
||||
SessionKey = cfg.sessionKey;
|
||||
};
|
||||
|
||||
postStart = ''
|
||||
mkdir -p ${cfg.dataDir}
|
||||
'';
|
||||
};
|
||||
|
||||
users.users.phenix = {
|
||||
isSystemUser = true;
|
||||
group = "phenix";
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
};
|
||||
|
||||
users.groups.phenix = {};
|
||||
};
|
||||
};
|
||||
in
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
dotnet = pkgs.dotnetCorePackages.sdk_9_0;
|
||||
pythonEnv = pkgs.python3.withPackages (ps: [ ps.requests ]);
|
||||
|
||||
phenix-website = pkgs.buildDotnetModule {
|
||||
name = "phenix-website";
|
||||
src = ./.;
|
||||
projectFile = "Phenix.csproj";
|
||||
selfContainedBuild = true;
|
||||
dotnet-sdk = dotnet;
|
||||
dotnet-runtime = pkgs.dotnetCorePackages.runtime_9_0;
|
||||
runtimeIdentifiers = "linux-x64";
|
||||
nugetDeps = ./deps.nix;
|
||||
|
||||
postInstall = ''
|
||||
cp -r static $out/lib/static/
|
||||
cp appsettings.json $out/lib/
|
||||
'';
|
||||
meta.mainProgram = "Phenix";
|
||||
};
|
||||
in {
|
||||
packages = {
|
||||
default = phenix-website;
|
||||
website = phenix-website;
|
||||
};
|
||||
|
||||
devShell = pkgs.mkShell {
|
||||
name = "Phenix-Website";
|
||||
buildInputs = [ dotnet pkgs.nuget-to-nix pythonEnv ];
|
||||
|
||||
shellHook = ''
|
||||
export PATH="$PWD/dev/populate-db:$PATH"
|
||||
'';
|
||||
};
|
||||
}) // {
|
||||
nixosModules.x86_64-linux = nixosModule;
|
||||
};
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
var gulp = require('gulp');
|
||||
var bower = require('gulp-bower');
|
||||
var help = require('gulp-task-listing');
|
||||
var clean = require('gulp-clean');
|
||||
var toml = require('gulp-toml');
|
||||
var sass = require('gulp-sass');
|
||||
var rename = require("gulp-rename");
|
||||
var yaml = require('gulp-yaml');
|
||||
var template = require('gulp-template');
|
||||
var wrapper = require('gulp-wrapper');
|
||||
var rename = require("gulp-rename");
|
||||
var webserver = require('gulp-webserver');
|
||||
var marked = require('marked');
|
||||
var _ = require('lodash');
|
||||
|
||||
gulp.task('help', help);
|
||||
|
||||
gulp.task('bower', function(){
|
||||
return bower()
|
||||
.pipe(gulp.dest('lib/'))
|
||||
.on('error', console.log);
|
||||
});
|
||||
|
||||
gulp.task('sass', ['bower'], function(){
|
||||
var extraSassPath = ['./lib/'];
|
||||
return gulp.src('./scss/*.scss')
|
||||
.pipe(sass({includePaths: extraSassPath}).on('error', console.log))
|
||||
.pipe(gulp.dest('./css'));
|
||||
});
|
||||
|
||||
gulp.task('clean', function(){
|
||||
return gulp.src(["lib/", "css/"], {read: false})
|
||||
.pipe(clean());
|
||||
});
|
||||
|
||||
gulp.task('compile-results', function(){
|
||||
return gulp.src('data/*.yaml')
|
||||
.pipe(yaml({safe: true}))
|
||||
.pipe(gulp.dest('./api'));
|
||||
});
|
||||
|
||||
gulp.task('template-prod', function () {
|
||||
return gulp.src('index.tmpl.html')
|
||||
.pipe(rename("index.html"))
|
||||
.pipe(template({production: true}))
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('template-dev', function () {
|
||||
return gulp.src('index.tmpl.html')
|
||||
.pipe(rename("index.html"))
|
||||
.pipe(template({production: false}))
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('compile-articles', function(){
|
||||
|
||||
var transformArticle = function(article){
|
||||
var isMarkdownKey = /markdown/i;
|
||||
_.each(article, function(section, sectionName){
|
||||
_.each(section, function(value, key){
|
||||
if(isMarkdownKey.test(key) && _.isString(value)){
|
||||
section[key] = marked(value);
|
||||
}
|
||||
});
|
||||
});
|
||||
return JSON.stringify(article, null, 4);
|
||||
};
|
||||
|
||||
gulp.src('data/articles/**/*.toml.md')
|
||||
.pipe(toml({to: transformArticle}))
|
||||
.pipe(wrapper({
|
||||
header: "define(['m', '_'], function (m, _ ) {\nreturn ",
|
||||
footer: ';\n});\n'
|
||||
}))
|
||||
.pipe(rename(function(path){
|
||||
path.basename = path.basename.replace(/\.toml$/i, '');
|
||||
path.extname = '.js';
|
||||
return path;
|
||||
}))
|
||||
.pipe(gulp.dest('./script/articles/'));
|
||||
|
||||
});
|
||||
|
||||
gulp.task('default', ['bower', 'sass', 'compile-results', 'compile-articles']);
|
||||
|
||||
gulp.task('prod', ['default', 'template-prod']);
|
||||
|
||||
gulp.task('webserver', function(){
|
||||
return gulp.src('.')
|
||||
.pipe(webserver({
|
||||
host: '0.0.0.0',
|
||||
port: 2222,
|
||||
livereload: false,
|
||||
directoryListing: false,
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('dev', ['default', 'webserver', 'template-dev', 'bower'], function(){
|
||||
gulp.watch('./scss/*.scss', ['sass']);
|
||||
gulp.watch('*.tmpl.html', ['template-dev']);
|
||||
gulp.watch('./data/articles/**/*', ['compile-articles']);
|
||||
return gulp.watch('./data/*.yaml', ['compile-results']);
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" >
|
||||
<title>Balle Phenix</title>
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<%if(production){ %>
|
||||
<script src="main-built.js"></script>
|
||||
<% }else{ %>
|
||||
<script data-main="script/main" src="lib/requirejs/require.js"></script>
|
||||
<% } %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
0 info it worked if it ends with ok
|
||||
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'install' ]
|
||||
2 info using npm@1.4.28
|
||||
3 info using node@v0.10.37
|
||||
4 verbose node symlink /usr/bin/node
|
||||
5 error install Couldn't read dependencies
|
||||
6 error package.json ENOENT, open '/home/didier/dev/go/src/gitlab.com/didiercrunch/phenix-website/static/package.json'
|
||||
6 error package.json This is most likely not a problem with npm itself.
|
||||
6 error package.json npm can't find a package.json file in your current directory.
|
||||
7 error System Linux 4.2.0-23-generic
|
||||
8 error command "/usr/bin/node" "/usr/bin/npm" "install"
|
||||
9 error cwd /home/didier/dev/go/src/gitlab.com/didiercrunch/phenix-website/static
|
||||
10 error node -v v0.10.37
|
||||
11 error npm -v 1.4.28
|
||||
12 error path /home/didier/dev/go/src/gitlab.com/didiercrunch/phenix-website/static/package.json
|
||||
13 error code ENOPACKAGEJSON
|
||||
14 error errno 34
|
||||
15 verbose exit [ 34, true ]
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "phenix-website",
|
||||
"version": "1.0.0",
|
||||
"description": "Main web site of Balle Phénix.",
|
||||
"main": "index.html",
|
||||
"dependencies": {
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-bower": "0.0.13",
|
||||
"gulp-clean": "^0.3.1",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sass": "^2.1.1",
|
||||
"gulp-task-listing": "^1.0.1",
|
||||
"gulp-template": "^3.1.0",
|
||||
"gulp-toml": "^0.1.1",
|
||||
"gulp-wrap": "^0.11.0",
|
||||
"gulp-wrapper": "^1.0.0",
|
||||
"lodash": "^4.6.1",
|
||||
"marked": "^0.3.5",
|
||||
"requirejs": "^2.1.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp-webserver": "^0.9.1",
|
||||
"gulp-yaml": "^1.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitlab.com/didiercrunch/phenix-website"
|
||||
},
|
||||
"author": "didier amyot <didier.amyot@gmail.com>",
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
define(['m', 'articles/inscription'], function (m, inscription) {
|
||||
|
||||
var simplifyArticleStructure = function(article){
|
||||
var ret = {};
|
||||
_.each(article, function(section, sectionName){
|
||||
ret[sectionName] = m.trust(section.innerMarkdown);
|
||||
});
|
||||
return ret;
|
||||
};
|
||||
|
||||
var articles = [];
|
||||
articles.push(inscription);
|
||||
|
||||
|
||||
return _.map(articles, simplifyArticleStructure);
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
import m from "https://esm.sh/mithril@2.2.2"
|
||||
|
||||
export function rainSvg (size){
|
||||
define(['m'], function(m) {
|
||||
return function(size){
|
||||
return m("svg[viewBox='0 0 107.95 87.723']",{width: size, height: size}, [
|
||||
m("defs[id='defs16']"),
|
||||
m("g[id='layer1'][transform='translate(-310.1 -167.39)']", [
|
||||
@@ -16,4 +15,5 @@ export function rainSvg (size){
|
||||
])
|
||||
])
|
||||
]);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
requirejs.config({
|
||||
paths: {
|
||||
'_': '../lib/lodash/dist/lodash.min',
|
||||
'm': '../lib/mithril/mithril.min'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
requirejs(['m', 'views/mainPage', 'views/newsPage', 'views/calendarPage', 'views/rulesPage', 'views/photosPage', 'views/confidentialPage', 'views/contactPage', 'views/loginPage',], function(m, mainPage, newsPage, calendarPage, rulesPage, photosPage, confidentialPage, contactPage, loginPage){
|
||||
m.route.mode = "hash";
|
||||
m.route(document.body, "/", {
|
||||
"/": mainPage,
|
||||
"/nouvelles": newsPage,
|
||||
"/calendrier": calendarPage,
|
||||
"/reglement": rulesPage,
|
||||
"/photos": photosPage,
|
||||
"/membre": confidentialPage,
|
||||
"/contact": contactPage
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
define(['_'], function(_) {
|
||||
var resultParser = {};
|
||||
|
||||
resultParser._addJSDateToResult = function(res){
|
||||
var date = res.date.split('/');
|
||||
var time = _.isString(res.time) ? res.time.split(':'): [0, 0];
|
||||
res.jsDate = new Date(
|
||||
Number(date[0]),
|
||||
Number(date[1]) - 1,
|
||||
Number(date[2]),
|
||||
Number(time[0]),
|
||||
Number(time[1])
|
||||
);
|
||||
return res;
|
||||
};
|
||||
|
||||
resultParser.parseResults = function(rawResults){
|
||||
rawResults = _.map(rawResults, resultParser._addJSDateToResult);
|
||||
rawResults = _.map(rawResults, resultParser._addCustomStyle);
|
||||
return rawResults;
|
||||
};
|
||||
|
||||
resultParser.getNightGames = function(rawResults){
|
||||
var ret = {};
|
||||
_.each(resultParser.parseResults(rawResults), function(res){
|
||||
if(_.has(ret, res.date)){
|
||||
ret[res.date].push(res);
|
||||
}else{
|
||||
ret[res.date] = [res];
|
||||
}
|
||||
});
|
||||
return _.map(ret, function(games, date){
|
||||
return resultParser._addJSDateToResult({date: date, games: games});
|
||||
});
|
||||
};
|
||||
|
||||
resultParser._getAllTeams = function(rawResults){
|
||||
var homeTeams = _.map(rawResults, 'home');
|
||||
var awayTeams = _.map(rawResults, 'away');
|
||||
return _.uniq(_.concat(homeTeams, awayTeams));
|
||||
};
|
||||
|
||||
resultParser._getWinner = function(res){
|
||||
if(res.home_points > res.away_points){
|
||||
return res.home;
|
||||
}
|
||||
if(res.home_points < res.away_points){
|
||||
return res.away;
|
||||
}
|
||||
};
|
||||
|
||||
resultParser._hasWon = function(res, team){
|
||||
return resultParser._getWinner(res) == team;
|
||||
};
|
||||
|
||||
resultParser._hasLost = function(res, team){
|
||||
return !resultParser._isDraw(res) && resultParser._getWinner(res) != team;
|
||||
};
|
||||
|
||||
resultParser._isDraw = function(res){
|
||||
return res.home_points == res.away_points;
|
||||
};
|
||||
|
||||
resultParser._getPointsFor = function(res, team){
|
||||
if(res.home == team){
|
||||
return res.home_points;
|
||||
}
|
||||
return res.away_points;
|
||||
};
|
||||
|
||||
resultParser._getPointsForOpponent = function(res, team){
|
||||
if(res.home == team){
|
||||
return res.away_points;
|
||||
}
|
||||
return res.home_points;
|
||||
};
|
||||
|
||||
resultParser._getPointsForGame = function(res, team){
|
||||
if(resultParser._hasWon(res, team)){
|
||||
return 2;
|
||||
}
|
||||
return resultParser._isDraw(res) ? 1: 0;
|
||||
};
|
||||
|
||||
resultParser._getTeamStats = function(rawResults, team){
|
||||
var ret = {
|
||||
team: team, gamePlayed: 0, victories: 0, points: 0,
|
||||
defeats: 0, draws: 0, pointsFor: 0, pointsAgaint: 0};
|
||||
_.each(rawResults, function(res){
|
||||
if((team != res.home && team != res.away) || !_.isNumber(res.home_points)){
|
||||
return;
|
||||
}
|
||||
ret.gamePlayed += 1;
|
||||
ret.victories += resultParser._hasWon(res, team) ? 1: 0;
|
||||
ret.defeats += resultParser._hasLost(res, team) ? 1: 0;
|
||||
ret.draws += resultParser._isDraw(res) ? 1: 0;
|
||||
ret.pointsFor += resultParser._getPointsFor(res, team);
|
||||
ret.pointsAgaint += resultParser._getPointsForOpponent(res, team);
|
||||
ret.points += resultParser._getPointsForGame(res, team);
|
||||
});
|
||||
return ret;
|
||||
};
|
||||
|
||||
resultParser.getStats = function(rawResults){
|
||||
var allTeams = resultParser._getAllTeams(rawResults);
|
||||
var getTeamStats = _.partial(resultParser._getTeamStats, rawResults);
|
||||
return _.map(allTeams, getTeamStats);
|
||||
};
|
||||
|
||||
return resultParser;
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
define(['m', '_'], function (m, _) {
|
||||
var teams = {};
|
||||
|
||||
teams.getTeamColor = function(teamName){
|
||||
if(teamName == 'jaune'){
|
||||
return '#FF0';
|
||||
}
|
||||
if(teamName == 'rouge'){
|
||||
return '#F00';
|
||||
}
|
||||
if(teamName == 'bleu'){
|
||||
return '#00F';
|
||||
}
|
||||
if(teamName == 'gris'){
|
||||
return '#808080';
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
return teams;
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
define(['m'], function(m) {
|
||||
var util = {};
|
||||
util.loremIpsum = function(n){
|
||||
var loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a"+
|
||||
" diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula "+
|
||||
"ac quam viverra nec consectetur ante hendrerit. Donec et mollis"+
|
||||
" dolor. Praesent et diam eget libero egestas mattis sit amet"+
|
||||
" vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia "+
|
||||
"consectetur. Donec ut libero sed arcu vehicula ultricies a non"+
|
||||
" tortor. Lorem ipsum dolor sit amet, consectetur adipiscing "+
|
||||
"elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a "+
|
||||
"semper sed, adipiscing id dolor. Pellentesque auctor nisi id "+
|
||||
"magna consequat sagittis. Curabitur dapibus enim sit amet elit "+
|
||||
"pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero "+
|
||||
"in urna ultrices accumsan. Donec sed od";
|
||||
loremIpsum = loremIpsum.split(' ');
|
||||
n = n || loremIpsum.length;
|
||||
return loremIpsum.splice(0, n).join(" ");
|
||||
|
||||
};
|
||||
|
||||
util.formatDate = function(date){
|
||||
var monthNames = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',
|
||||
'juiller', 'août', 'septembre', 'octobre', 'novembre',
|
||||
'decembre'];
|
||||
return [date.getDate(),
|
||||
monthNames[date.getMonth()],
|
||||
date.getFullYear()].join(' ');
|
||||
|
||||
};
|
||||
|
||||
util.formatDateSmall = function(date){
|
||||
var smallMonthNames = ['janv', 'févr', 'mars', 'avr', 'mai', 'juin',
|
||||
'juill', 'août', 'sept', 'oct', 'nov',
|
||||
'dec'];
|
||||
return [date.getDate(),
|
||||
smallMonthNames[date.getMonth()],
|
||||
date.getFullYear() % 1000].join(' ');
|
||||
};
|
||||
|
||||
util.facebookLink = function(){
|
||||
return m('a[href="https://www.facebook.com/LigueDeBalleLesPhenix"]',
|
||||
m('i.fa.fa-facebook-square')
|
||||
);
|
||||
};
|
||||
|
||||
return util;
|
||||
});
|
||||
@@ -0,0 +1,136 @@
|
||||
define(['m', '_', 'util', 'resultParser', 'teams', 'views/topNavBar', 'views/footer', 'images/rain.svg'], function(m, _, util, resultParser, teams, topNavBar, footer, rainSvg) {
|
||||
var statsView = {};
|
||||
|
||||
statsView.controller = function(){
|
||||
var games = m.prop([]);
|
||||
return m.request({method: "GET", url: "api/resultats.json"})
|
||||
.then(games)
|
||||
.then(resultParser.getStats);
|
||||
};
|
||||
|
||||
statsView.getStatRow = function(teamStats){
|
||||
var formatStat = function(n){
|
||||
return teamStats.gamePlayed === 0 ? '-' : n;
|
||||
};
|
||||
return m('tr', [
|
||||
m('td', teamStats.team),
|
||||
m('td', teamStats.gamePlayed),
|
||||
m('td', formatStat(teamStats.victories)),
|
||||
m('td', formatStat(teamStats.defeats)),
|
||||
m('td', formatStat(teamStats.draws)),
|
||||
m('td', formatStat(teamStats.pointsFor)),
|
||||
m('td', formatStat(teamStats.pointsAgaint)),
|
||||
m('td', formatStat(teamStats.pointsFor - teamStats.pointsAgaint)),
|
||||
m('td', formatStat(teamStats.points))
|
||||
]);
|
||||
};
|
||||
|
||||
statsView.mainTable = function(stats){
|
||||
return m('table.uk-table.uk-table-hover.uk-table-striped',[
|
||||
m('thead', m('tr', [
|
||||
m('th', 'Équipes'),
|
||||
m('th', 'PJ'),
|
||||
m('th', 'V'),
|
||||
m('th', 'D'),
|
||||
m('th', 'N'),
|
||||
m('th', 'PP'),
|
||||
m('th', 'PC'),
|
||||
m('th', 'DIF'),
|
||||
m('th', 'PTS')
|
||||
])),
|
||||
m('tbody', _.map(stats, statsView.getStatRow))
|
||||
]);
|
||||
};
|
||||
|
||||
statsView.legend = function(){
|
||||
var items = ["PJ : Parties joués", "V : Victoire", "D : Défaite",
|
||||
"N : Nul", "PP : Points pour", "PC : Points contre",
|
||||
"DIF : Diférenciel","PTS : Points"];
|
||||
return m('ul.uk-subnav.uk-subnav-line.uk-flex-center',[
|
||||
_.map(items, function(itm){
|
||||
return m('li', itm);
|
||||
})
|
||||
]);
|
||||
};
|
||||
|
||||
statsView.view = function(stats){
|
||||
return m('div.uk-grid',
|
||||
m('div.uk-width-medium-1-1.uk-width-large-1-1.uk-container-center',[
|
||||
m('h2', 'Classement 2016'),
|
||||
statsView.mainTable(stats()),
|
||||
statsView.legend()
|
||||
]));
|
||||
|
||||
};
|
||||
|
||||
|
||||
var schedulView = {};
|
||||
|
||||
schedulView.controller = function(){
|
||||
var games = m.prop([]);
|
||||
return m.request({method: "GET", url: "api/resultats.json"})
|
||||
.then(games)
|
||||
.then(resultParser.getNightGames);
|
||||
};
|
||||
|
||||
schedulView._getTeamTag = function(teamName){
|
||||
var teamColor = teams.getTeamColor(teamName);
|
||||
return [
|
||||
m('i.fa.fa-flag', {style: {color: teamColor}}),
|
||||
m('span', ' ' + teamName)
|
||||
];
|
||||
};
|
||||
|
||||
schedulView._asGamePoints = function(points){
|
||||
return !_.isNumber(points) ? '-' : points + '';
|
||||
};
|
||||
|
||||
schedulView._gameName = function(game){
|
||||
if(game.rain){
|
||||
return [rainSvg('1.5em'), " ", game.time];
|
||||
}
|
||||
return [game.time, " ", m('span', {style: {visibility: 'hidden'}}, rainSvg('1.5em'))];
|
||||
};
|
||||
|
||||
schedulView._gameRow = function(game){
|
||||
|
||||
return m('tr',[
|
||||
m('td', schedulView._gameName(game)),
|
||||
m('td', schedulView._getTeamTag(game.home)),
|
||||
m('td', schedulView._asGamePoints(game.home_points)),
|
||||
m('td', 'vs'),
|
||||
m('td', schedulView._getTeamTag(game.away)),
|
||||
m('td', schedulView._asGamePoints(game.away_points))
|
||||
]);
|
||||
};
|
||||
|
||||
schedulView._gameView = function(gameNight){
|
||||
return m('div', [m('h3', util.formatDate(gameNight.jsDate)),
|
||||
m('table.uk-table.uk-table-hover.uk-table-condensed.uk-table-striped',
|
||||
m('tbody',[
|
||||
_.map(gameNight.games, schedulView._gameRow),
|
||||
])
|
||||
)
|
||||
]);
|
||||
|
||||
};
|
||||
|
||||
schedulView.view = function(games){
|
||||
return m('div.uk-grid',
|
||||
m('div.uk-width-large-3-5.uk-width-medium-1-1',
|
||||
_.concat([m('h2', 'Calendrier 2016')], _.map(games(), schedulView._gameView))));
|
||||
};
|
||||
|
||||
calendarPage = {};
|
||||
|
||||
calendarPage.view = function(){
|
||||
return [m.component(topNavBar),
|
||||
m('div.uk-grid.uk-margin-top.uk-margin-bottom',
|
||||
m('div.uk-width-large-3-5.uk-width-medium-4-5.uk-width-small-1-1.uk-container-center',[
|
||||
m.component(statsView),
|
||||
m.component(schedulView)])),
|
||||
m.component(footer)];
|
||||
};
|
||||
|
||||
return calendarPage;
|
||||
});
|
||||
@@ -0,0 +1,293 @@
|
||||
define(['m', '_', 'teams', 'views/topNavBar', 'views/footer'], function (m, _ , teams, topNavBar, footer) {
|
||||
|
||||
|
||||
var confidentialSelection = {};
|
||||
|
||||
confidentialSelection.toggleTeam = function(teamId, activatedTeams){
|
||||
return function(isActive){
|
||||
isActive = isActive != 'true';
|
||||
if(isActive){
|
||||
activatedTeams().push(teamId);
|
||||
return;
|
||||
}
|
||||
activatedTeams(_.difference(activatedTeams(), [teamId]));
|
||||
};
|
||||
};
|
||||
|
||||
confidentialSelection.teamInput = function(teamName, teamId, activatedTeams){
|
||||
var isActive = _.includes(activatedTeams(), teamId);
|
||||
var class_ = isActive ? 'uk-badge-success' : '';
|
||||
var callback = confidentialSelection.toggleTeam(teamId, activatedTeams);
|
||||
return m('div.uk-badge.uk-margin-left.uk-border-rounded',
|
||||
{class: class_, 'data-selected': isActive, onclick: m.withAttr("data-selected", callback)},
|
||||
m('h3', {style: {width: '80px'}}, teamName)
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
confidentialSelection.scoreInput = function(score, activatedScores){
|
||||
var isActive = _.includes(activatedScores(), score);
|
||||
var class_ = isActive ? 'uk-badge-success' : '';
|
||||
var callback = confidentialSelection.toggleTeam(score, activatedScores);
|
||||
return m('div.uk-badge.uk-margin-left.uk-border-rounded',
|
||||
{class: class_, 'data-selected': isActive, onclick: m.withAttr("data-selected", callback)},
|
||||
m('h3', {style: {width: '80px'}}, score)
|
||||
);
|
||||
};
|
||||
|
||||
confidentialSelection.chooseTeams = function(model){
|
||||
return m('form.uk-grid', {style: {'margin-top': '1em'}},
|
||||
m('div.uk-width-1-6', m('label', m('b', 'Équipes'))),
|
||||
m('div.uk-width-5-6',
|
||||
m('div.uk-grid', [
|
||||
confidentialSelection.teamInput('Bleu', 'bleu', model.activatedTeams),
|
||||
confidentialSelection.teamInput('Rouge', 'rouge', model.activatedTeams),
|
||||
confidentialSelection.teamInput('Jaune', 'jaune', model.activatedTeams),
|
||||
confidentialSelection.teamInput('Gris', 'gris', model.activatedTeams),
|
||||
]))
|
||||
);
|
||||
};
|
||||
|
||||
confidentialSelection.chooseScore = function(model){
|
||||
return m('form.uk-grid', {style: {'margin-top': '1em'}},
|
||||
m('div.uk-width-1-6', m('label', m('b', 'Score'))),
|
||||
m('div.uk-width-5-6',
|
||||
m('div.uk-grid', [
|
||||
confidentialSelection.scoreInput(1, model.activatedScores),
|
||||
confidentialSelection.scoreInput(2, model.activatedScores),
|
||||
confidentialSelection.scoreInput(3, model.activatedScores),
|
||||
confidentialSelection.scoreInput(4, model.activatedScores),
|
||||
confidentialSelection.scoreInput(5, model.activatedScores)
|
||||
]))
|
||||
);
|
||||
};
|
||||
|
||||
confidentialSelection.controller = function(model){
|
||||
return model;
|
||||
};
|
||||
|
||||
confidentialSelection.view = function(model){
|
||||
return m('div', [
|
||||
confidentialSelection.chooseTeams(model),
|
||||
confidentialSelection.chooseScore(model)
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
var confidentialTable = {};
|
||||
|
||||
confidentialTable._sortFunction = function(sortingElm){
|
||||
|
||||
};
|
||||
|
||||
confidentialTable._sortPlayers = function(sorting, playerList){
|
||||
var sortingKeys = _.map(sorting(), 'key');
|
||||
var sortingDirections = _.map(sorting(), function(o){
|
||||
return o.direction == 1 ? 'desc' : 'asc';
|
||||
});
|
||||
return _.orderBy(playerList, sortingKeys, sortingDirections);
|
||||
};
|
||||
|
||||
confidentialTable.controller = function(model){
|
||||
var players = m.prop([]);
|
||||
var ctrl = {};
|
||||
ctrl.model = model;
|
||||
|
||||
ctrl.players = m.request({method: "GET", url: "api/players.json"})
|
||||
.then(players);
|
||||
ctrl.sortPlayers = function(){
|
||||
ctrl.players(confidentialTable._sortPlayers(ctrl.model.sorting, ctrl.players()));
|
||||
};
|
||||
return ctrl;
|
||||
};
|
||||
|
||||
confidentialTable._getSortDict = function(sorting){
|
||||
var ret = {};
|
||||
_.each(sorting(), function(elm){
|
||||
ret[elm.key] = elm.direction;
|
||||
});
|
||||
return ret;
|
||||
|
||||
};
|
||||
|
||||
confidentialTable._isSortingUp = function(sorting, key){
|
||||
var dict = confidentialTable._getSortDict(sorting);
|
||||
return dict[key] === 1;
|
||||
};
|
||||
|
||||
confidentialTable._isSortingDown = function(sorting, key){
|
||||
var dict = confidentialTable._getSortDict(sorting);
|
||||
return dict[key] === -1;
|
||||
};
|
||||
|
||||
confidentialTable.arrows = function(sorting, key){
|
||||
var sortUp = confidentialTable._isSortingUp(sorting, key);
|
||||
var sortDown = confidentialTable._isSortingDown(sorting, key);
|
||||
var style = {
|
||||
display: 'inline-block',
|
||||
'line-height': '0.5em',
|
||||
'margin-right': '1em',
|
||||
'font-size': '0.7em'
|
||||
};
|
||||
var sortedStyle = {color: '#8cc14c', 'font-weight': 'bold'};
|
||||
return m('span', {style: style},
|
||||
m('i.fa.fa-chevron-up', {style: sortUp ? sortedStyle: {}}),
|
||||
m('br'),
|
||||
m('i.fa.fa-chevron-down', {style: sortDown ? sortedStyle: {}})
|
||||
);
|
||||
};
|
||||
|
||||
confidentialTable._setSorting = function(sorting, key){
|
||||
var newDirection = {key: key, direction: -1 * confidentialTable._getSortDict(sorting)[key]};
|
||||
var directions = _.filter(sorting(), function(o){
|
||||
return o.key != key;
|
||||
});
|
||||
sorting([newDirection].concat(directions));
|
||||
};
|
||||
|
||||
confidentialTable.tableHeader = function(sorting){
|
||||
var setSorting = function(key){
|
||||
return _.partial(confidentialTable._setSorting, sorting, key);
|
||||
};
|
||||
return m('thead',
|
||||
m('tr', [
|
||||
m('th', {onclick: setSorting('team')}, confidentialTable.arrows(sorting, 'team'), 'Équipe'),
|
||||
m('th', {onclick: setSorting('name')}, confidentialTable.arrows(sorting, 'name'), 'Nom'),
|
||||
m('th.uk-hidden-small', 'Courriel'),
|
||||
m('th.uk-hidden-small', 'Téléphone'),
|
||||
m('th', {onclick: setSorting('score')}, confidentialTable.arrows(sorting, 'score'), 'Cote')
|
||||
]));
|
||||
};
|
||||
|
||||
confidentialTable.getPlayerTeamIcon = function(player){
|
||||
var background = teams.getTeamColor(player.team);
|
||||
var style = {width: '20px', height: '20px', 'background-color': background};
|
||||
return m('div', {style: style}, m.trust(' '));
|
||||
};
|
||||
|
||||
confidentialTable.playerRow = function(player){
|
||||
return m('tr',[
|
||||
m('td', confidentialTable.getPlayerTeamIcon(player)),
|
||||
m('td', player.name),
|
||||
m('td.uk-hidden-small', player.email),
|
||||
m('td.uk-hidden-small', player.tel),
|
||||
m('td', player.score)
|
||||
]);
|
||||
};
|
||||
|
||||
confidentialTable.onlyPlayerOfTeam = function(visibleTeam){
|
||||
return function(player){
|
||||
return _.includes(visibleTeam, player.team);
|
||||
};
|
||||
};
|
||||
|
||||
confidentialTable.onlyPlayerOfScore = function(visibleScores){
|
||||
return function(player){
|
||||
return _.includes(visibleScores, player.score);
|
||||
};
|
||||
};
|
||||
|
||||
confidentialTable.tableBody = function(players, visibleTeam, activatedScores){
|
||||
return m('tbody',
|
||||
_(players)
|
||||
.filter(confidentialTable.onlyPlayerOfTeam(visibleTeam))
|
||||
.filter(confidentialTable.onlyPlayerOfScore(activatedScores))
|
||||
.map(confidentialTable.playerRow).value()
|
||||
);
|
||||
};
|
||||
|
||||
confidentialTable.view = function(ctrl){
|
||||
ctrl.sortPlayers();
|
||||
return m('table.uk-table.uk-table-hover.uk-table-striped',
|
||||
confidentialTable.tableHeader(ctrl.model.sorting),
|
||||
confidentialTable.tableBody(ctrl.players(),
|
||||
ctrl.model.activatedTeams(),
|
||||
ctrl.model.activatedScores()
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
var confidentialPageBody = {};
|
||||
|
||||
confidentialPageBody.controller = function(){
|
||||
var model = {};
|
||||
model.activatedTeams = m.prop(['bleu', 'rouge', 'jaune', 'gris']);
|
||||
model.activatedScores = m.prop([1, 2, 3, 4, 5]);
|
||||
model.sorting = m.prop([{key: 'team', direction: 1}, {key: 'score', direction: -1}, {key: 'name', direction: 1}]);
|
||||
return model;
|
||||
};
|
||||
|
||||
confidentialPageBody.view = function(model){
|
||||
return m('div.uk-grid.uk-margin-top.uk-margin-bottom',
|
||||
m('div.uk-width-large-3-5.uk-width-small-1-1.uk-container-center', [
|
||||
m.component(confidentialSelection, model),
|
||||
m.component(confidentialTable, model),
|
||||
]));
|
||||
};
|
||||
|
||||
|
||||
var loginComponent = {};
|
||||
|
||||
loginComponent.controller = function(){
|
||||
return {email: m.prop(), password: m.prop()};
|
||||
};
|
||||
|
||||
loginComponent.logo = function(){
|
||||
var style = 'height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);';
|
||||
return m('div.uk-cover-background.uk-container-center', {style: style});
|
||||
};
|
||||
|
||||
loginComponent.logoLine = function(){
|
||||
return m('div.uk-grid.uk-margin',
|
||||
m('div.uk-width-1-1', loginComponent.logo()));
|
||||
};
|
||||
|
||||
loginComponent.login = function(ctrl){
|
||||
return function(){
|
||||
var salt = "9'D)E@E{DSq[|l2bq!v";
|
||||
window.secret = salt + ctrl.email() + ctrl.password();
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
loginComponent.loginForm = function(ctrl){
|
||||
return m('div.uk-panel.uk-panel-box.uk-panel-box-secondary.uk-width-large-1-3.uk-container-center.uk-margin', [
|
||||
m('form.uk-text-center', {onsubmit: m.withAttr("form", loginComponent.login(ctrl))},
|
||||
m('div.uk-form-row',
|
||||
m('label', "Nom d'utilisateur ",
|
||||
m('input[type=text][required].uk-form-width-small', {oninput: m.withAttr("value", ctrl.email)}))),
|
||||
m('div.uk-form-row',
|
||||
m('label', "Mot de passe ",
|
||||
m('input[type=password][required].uk-form-width-small', {oninput: m.withAttr("value", ctrl.password)}))),
|
||||
m('div.uk-form-row', m('button.uk-button', m("i.fa.fa-mars-double"), " Pénétrez"))
|
||||
)
|
||||
]);
|
||||
};
|
||||
|
||||
loginComponent.view = function(ctrl){
|
||||
return m('div', [
|
||||
loginComponent.logoLine(),
|
||||
loginComponent.loginForm(ctrl)
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
var confidentialPage = {};
|
||||
|
||||
confidentialPage.view = function(){
|
||||
var body;
|
||||
window.secret = 'o'
|
||||
if(!window.secret){
|
||||
body = loginComponent;
|
||||
}else{
|
||||
body = confidentialPageBody;
|
||||
}
|
||||
return [
|
||||
m.component(topNavBar),
|
||||
m.component(body),
|
||||
m.component(footer)
|
||||
];
|
||||
};
|
||||
|
||||
return confidentialPage;
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
define(['m', '_', 'util', 'resultParser', 'views/topNavBar', 'views/footer'], function (m, _ , util, resultParser, topNavBar, footer) {
|
||||
|
||||
var contactBody = {};
|
||||
|
||||
contactBody.logo = function(){
|
||||
var style = 'height: 300px; width: 300px; background-size: 300px; background-image: url(images/logosansfond.JPG);';
|
||||
return m('div.uk-cover-background.uk-container-center', {style: style});
|
||||
};
|
||||
|
||||
contactBody.logoLine = function(){
|
||||
return m('div.uk-grid.uk-margin',
|
||||
m('div.uk-width-1-1', contactBody.logo()));
|
||||
};
|
||||
|
||||
contactBody.email = function(){
|
||||
return m('a[href=mailto:info@ballephenix.com]', 'info@ballephenix.com');
|
||||
};
|
||||
|
||||
contactBody.tel = function(){
|
||||
return ' (514) 544-8976';
|
||||
};
|
||||
|
||||
contactBody.address = function(){
|
||||
return m('p', ' 123 rue Dufresne', m('br'), 'Montréal, Québec H6Y 8U7');
|
||||
};
|
||||
|
||||
contactBody.contact = function(){
|
||||
return m('div.div.uk-panel.uk-panel-box.uk-panel-box-secondary.uk-container-center.uk-margin',[
|
||||
m('table.uk-table',
|
||||
m('tr',
|
||||
m('td.uk-text-right', m('i.fa.fa-desktop')),
|
||||
m('td', contactBody.email())
|
||||
),
|
||||
m('tr',
|
||||
m('td.uk-text-right', m('i.fa.fa-phone')),
|
||||
m('td', contactBody.tel())
|
||||
),
|
||||
m('tr',
|
||||
m('td.uk-text-right', m('i.fa.fa-envelope')),
|
||||
m('td', contactBody.address())
|
||||
)
|
||||
)
|
||||
]);
|
||||
|
||||
};
|
||||
|
||||
contactBody.view = function(){
|
||||
return m('div.uk-margin-top.uk-margin-bottom.uk-grid',
|
||||
m('div.uk-width-large-2-5.uk-width-medium-4-5.uk-width-small-1-1.uk-container-center', [
|
||||
contactBody.logoLine(),
|
||||
contactBody.contact()
|
||||
])
|
||||
);
|
||||
};
|
||||
|
||||
var contactPage = {};
|
||||
|
||||
contactPage.view = function(){
|
||||
return [
|
||||
m.component(topNavBar),
|
||||
m.component(contactBody),
|
||||
m.component(footer)
|
||||
];
|
||||
};
|
||||
|
||||
return contactPage;
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
define(['m', '_', 'util'], function (m, _, util) {
|
||||
var footer = {};
|
||||
|
||||
footer.wording = function(){
|
||||
return [
|
||||
m('span.uk-hidden-small', 'Ligue de balle les Phénix... pour le plaisir de jouer!'),
|
||||
m('h4.uk-visible-small', 'Ligue de balle les Phénix')
|
||||
];
|
||||
};
|
||||
|
||||
footer.view = function(){
|
||||
return m('footer.uk-grid.ph-footer', {style: {padding: '40px'}},
|
||||
m('div.uk-container.uk-container-center.uk-text-center', [
|
||||
m('div.uk-panel', footer.wording()),
|
||||
m('ul.uk-subnav.uk-subnav-line.uk-flex-center',
|
||||
m('li', m('a[href="mailto:info@ballephenix.com"]', 'info@ballephenix.com'))),
|
||||
m('h1', util.facebookLink())
|
||||
])
|
||||
);
|
||||
};
|
||||
|
||||
return footer;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
define(['m', '_', 'util', 'views/topNavBar', 'views/footer'], function (m, _ , util, topNavBar, footer) {
|
||||
|
||||
var loginComponent = {};
|
||||
|
||||
loginComponent.logo = function(){
|
||||
var style = 'height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);';
|
||||
return m('div.uk-cover-background.uk-container-center', {style: style});
|
||||
};
|
||||
|
||||
loginComponent.logoLine = function(){
|
||||
return m('div.uk-grid.uk-margin',
|
||||
m('div.uk-width-1-1', loginComponent.logo()));
|
||||
};
|
||||
|
||||
loginComponent.loginForm = function(){
|
||||
return m('div.uk-panel.uk-panel-box.uk-panel-box-secondary.uk-width-large-1-3.uk-container-center.uk-margin', [
|
||||
m('form.uk-text-center',
|
||||
m('div.uk-form-row', m('label', "Nom d'utilisateur ", m('input[type=text].uk-form-width-small'))),
|
||||
m('div.uk-form-row', m('label', "Mot de passe ", m('input[type=password].uk-form-width-small'))),
|
||||
m('div.uk-form-row', m('button.uk-button', m("i.fa.fa-mars-double"), " Pénétrez"))
|
||||
)
|
||||
]);
|
||||
};
|
||||
|
||||
loginComponent.view = function(){
|
||||
return m('div', [
|
||||
loginComponent.logoLine(),
|
||||
loginComponent.loginForm()
|
||||
]);
|
||||
};
|
||||
|
||||
var loginPage = {};
|
||||
|
||||
loginPage.view = function(){
|
||||
return [
|
||||
m.component(topNavBar),
|
||||
m.component(loginComponent),
|
||||
m.component(footer)
|
||||
];
|
||||
};
|
||||
|
||||
return loginPage;
|
||||
});
|
||||
@@ -0,0 +1,169 @@
|
||||
define(['m', '_', 'util', 'resultParser', 'views/topNavBar', 'views/footer', 'articles/articles'], function (m, _ , util, resultParser, topNavBar, footer, articles) {
|
||||
var mainPageLogo = {};
|
||||
|
||||
mainPageLogo.view = function(){
|
||||
return m('div.uk-grid', [
|
||||
m('div.uk-large-1-3.uk-medium-2-3.uk-container-center', [
|
||||
m('div.uk-cover-background.uk-container-center.uk-margin-left.uk-margin-top',{style: 'height:300px; width: 300px; background-size: 300px; background-image: url(images/logosansfond.JPG);'})
|
||||
])
|
||||
]);
|
||||
};
|
||||
|
||||
var mainPageNews = {};
|
||||
|
||||
mainPageNews.view = function(){
|
||||
var article = _.get(articles, 0, {});
|
||||
return m('div.uk-panel.uk-panel-box',[
|
||||
m('div.uk-panel-badge.uk-badge', [
|
||||
m('i.fa.fa-newspaper-o')
|
||||
]),
|
||||
m('h3.uk-panel-title', m('a.uk-link-muted', {href: '#/nouvelles'}, article.title)),
|
||||
m('p', article.smallBody || article.body)
|
||||
]);
|
||||
};
|
||||
|
||||
var nextGameDaySchedule = {};
|
||||
|
||||
nextGameDaySchedule.controller = function(){
|
||||
var games = m.prop([]);
|
||||
return m.request({method: "GET", url: "api/resultats.json"})
|
||||
.then(games)
|
||||
.then(resultParser.getNightGames)
|
||||
.then(function(nightGames){
|
||||
return nightGames[0].games;
|
||||
});
|
||||
};
|
||||
|
||||
nextGameDaySchedule._getTableHead = function(){
|
||||
return m('thead', m('tr', [
|
||||
m('td', 'Date'),
|
||||
m('td', 'Heure'),
|
||||
m('td', 'Visiteur'),
|
||||
m('td', 'Receveur')
|
||||
]));
|
||||
};
|
||||
|
||||
nextGameDaySchedule._responsoveText = function(largeText, smallText){
|
||||
return [m('span.uk-visible-large', largeText),
|
||||
m('span.uk-hidden-large', smallText)];
|
||||
};
|
||||
|
||||
nextGameDaySchedule._getGamesRow = function(game){
|
||||
return m('tr', [
|
||||
m('td', nextGameDaySchedule._responsoveText(util.formatDate(game.jsDate),
|
||||
util.formatDateSmall(game.jsDate))),
|
||||
m('td', game.time),
|
||||
m('td', game.away),
|
||||
m('td', game.home)
|
||||
]);
|
||||
};
|
||||
|
||||
nextGameDaySchedule._getGamesRows = function(games){
|
||||
return _.map(games(), nextGameDaySchedule._getGamesRow);
|
||||
};
|
||||
|
||||
nextGameDaySchedule.view = function(games){
|
||||
return m('table.uk-table.uk-table-hover.uk-table-striped.uk-table-condensed',[
|
||||
nextGameDaySchedule._getTableHead(),
|
||||
m('tbody',
|
||||
nextGameDaySchedule._getGamesRows(games)
|
||||
)]);
|
||||
};
|
||||
|
||||
var mainPageSchedule = {};
|
||||
|
||||
mainPageSchedule.view = function(){
|
||||
return m('div.uk-panel.uk-panel-box',[
|
||||
m('div.uk-panel-badge.uk-badge', m('i.fa.fa-clock-o')),
|
||||
m('h3.uk-panel-title', m('a.uk-link-muted', {href: '#/calendrier'}, 'Horaire')),
|
||||
m.component(nextGameDaySchedule)
|
||||
]);
|
||||
};
|
||||
|
||||
var mainMap = {};
|
||||
|
||||
mainMap.getMap = function(){
|
||||
var iframeUrl = "//www.openstreetmap.org/export/embed.html?bbox=-73.55889558792114%2C45.53089890181621%2C-73.55181455612183%2C45.53426212742867&layer=mapnik";
|
||||
var externalLink = "http://www.openstreetmap.org/#map=18/45.53258/-73.55536";
|
||||
var iframeParams = {
|
||||
style: {border: '1px solid black', 'min-height': '300px'},
|
||||
width: '100%',
|
||||
// height: '100%',
|
||||
frameborder: 0,
|
||||
scrolling: 'no',
|
||||
marginheight: 0,
|
||||
src: iframeUrl
|
||||
};
|
||||
return [
|
||||
m('iframe', iframeParams),
|
||||
m('br'),
|
||||
m('small', m('a', {href: externalLink}, 'Voir la carte'))
|
||||
];
|
||||
};
|
||||
|
||||
mainMap.view = function(){
|
||||
return m('div.uk-panel.uk-panel-box',[
|
||||
m('div.uk-panel-badge.uk-badge', [
|
||||
m('i.fa.fa-map-o')
|
||||
]),
|
||||
m('h3.uk-panel-title', 'Parc Walter-Stewart'),
|
||||
mainMap.getMap()
|
||||
]);
|
||||
};
|
||||
|
||||
var mainPageBottom = {};
|
||||
|
||||
mainPageBottom.regularSizeView = function(){
|
||||
return m('div.uk-grid.uk-visible-large.uk-grid-match', [
|
||||
m('div.uk-width-large-1-3.uk-width-medium-1-3', m.component(mainPageNews)),
|
||||
m('div.uk-width-large-1-3.uk-width-medium-1-3', m.component(mainPageSchedule)),
|
||||
m('div.uk-width-large-1-3.uk-width-medium-1-3', m.component(mainMap))
|
||||
]);
|
||||
};
|
||||
|
||||
mainPageBottom.mediumSizeView = function(){
|
||||
return m('div.uk-visible-medium', [
|
||||
m('div.uk-grid.uk-grid-match', [
|
||||
m('div.uk-width-medium-1-2', [m.component(mainPageNews)]),
|
||||
m('div.uk-width-medium-1-2', [m.component(mainPageSchedule)]),
|
||||
]),
|
||||
m('div.uk-grid',
|
||||
m('div.uk-width-medium-1-1', m.component(mainMap))
|
||||
)
|
||||
]);
|
||||
};
|
||||
|
||||
mainPageBottom.smallSizeView = function(){
|
||||
return m('div.uk-visible-small',
|
||||
[
|
||||
m('div.uk-grid', m('div.uk-width-small-1-1', m.component(mainPageNews))),
|
||||
m('div.uk-grid', m('div.uk-width-small-1-1', m.component(mainPageSchedule))),
|
||||
m('div.uk-grid', m('div.uk-width-small-1-1', m.component(mainMap)))
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
mainPageBottom.view = function(){
|
||||
return m('div.uk-margin-top.uk-margin-bottom.uk-grid',
|
||||
m('div.uk-width-large-3-5.uk-width-medium-4-5.uk-width-small-1-1.uk-container-center', [
|
||||
mainPageBottom.regularSizeView(),
|
||||
mainPageBottom.mediumSizeView(),
|
||||
mainPageBottom.smallSizeView()
|
||||
])
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
var mainPage = {};
|
||||
|
||||
mainPage.view = function(){
|
||||
return [
|
||||
topNavBar.view(),
|
||||
mainPageLogo.view(),
|
||||
mainPageBottom.view(),
|
||||
footer.view()
|
||||
];
|
||||
};
|
||||
|
||||
return mainPage;
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
define(['m', '_', 'util', 'resultParser', 'articles/articles', 'views/topNavBar', 'views/footer'], function (m, _ , util, resultParser, articles, topNavBar, footer) {
|
||||
|
||||
var newsPageBody = {};
|
||||
|
||||
newsPageBody.logo = function(){
|
||||
var style = 'height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);';
|
||||
return m('div.uk-cover-background.uk-container-center', {style: style});
|
||||
};
|
||||
|
||||
newsPageBody.getArticle = function(article){
|
||||
return m('article.uk-article.uk-margin-',
|
||||
m('h1.uk-article-title', article.title),
|
||||
m('p.uk-article-meta', article.meta),
|
||||
article.body
|
||||
);
|
||||
};
|
||||
|
||||
newsPageBody.view = function(){
|
||||
return m('div', _.map(articles, newsPageBody.getArticle));
|
||||
|
||||
};
|
||||
|
||||
var newsPage = {};
|
||||
|
||||
newsPage.view = function(){
|
||||
return [
|
||||
m.component(topNavBar),
|
||||
m('div.uk-grid.uk-margin-top.uk-margin-bottom',
|
||||
m('div.uk-width-large-2-5.uk-width-medium-3-5.uk-width-small-1-1.uk-container-center',
|
||||
m.component(newsPageBody))),
|
||||
m.component(footer)
|
||||
];
|
||||
};
|
||||
|
||||
return newsPage;
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
define(['m', '_', 'util', 'resultParser', 'views/topNavBar', 'views/footer'], function (m, _ , util, resultParser, topNavBar, footer) {
|
||||
|
||||
var rulesPageBody = {};
|
||||
|
||||
rulesPageBody.logo = function(){
|
||||
var style = 'height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);';
|
||||
return m('div.uk-cover-background.uk-container-center', {style: style});
|
||||
};
|
||||
|
||||
rulesPageBody.view = function(){
|
||||
return m('div.uk-grid',
|
||||
m('div.uk-width-1-1', rulesPageBody.logo()));
|
||||
};
|
||||
|
||||
var photosPage = {};
|
||||
|
||||
photosPage.view = function(){
|
||||
return [
|
||||
m.component(topNavBar),
|
||||
m.component(rulesPageBody),
|
||||
m.component(footer)
|
||||
];
|
||||
};
|
||||
|
||||
return photosPage;
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
define(['m', '_', 'util', 'resultParser', 'views/topNavBar', 'views/footer'], function (m, _ , util, resultParser, topNavBar, footer) {
|
||||
|
||||
var rulesPage = {};
|
||||
|
||||
rulesPage.missionText = function(){
|
||||
return "La ligue de balle Les Phénix a été fondée en 2004 afin "+
|
||||
"d'offrir aux membres de la communauté gaie et lesbienne et à "+
|
||||
"leurs amis hétéros l'opportunité de s'amuser et de pratiquer "+
|
||||
"un sport dans une ambiance amicale et décontractée. "+
|
||||
"L'ouverture d'esprit, la camaraderie et le plaisir de "+
|
||||
"pratiquer un sport à l'extérieur caractérisent cette ligue.";
|
||||
};
|
||||
|
||||
rulesPage.logo = function(){
|
||||
var style = 'height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);';
|
||||
return m('div.uk-cover-background.uk-container-center', {style: style});
|
||||
};
|
||||
|
||||
rulesPage.rules = function(){
|
||||
var urlASBM = 'http://montreal.baseballquebec.com/fr/publication/nouvelle/recherche_un_directeur_general_asbm.html';
|
||||
return m('div.uk-width-large-2-3.uk-width-small-1-1',
|
||||
m('div.uk-panel.uk-panel-box.uk-panel-box-secondary', [
|
||||
m('h2', 'Règlements 2016'),
|
||||
m('ul',[
|
||||
m('li', m('h3', m('a', {href: 'files/reglements_generaux.pdf'}, 'Règlements généraux'))),
|
||||
m('li', m('h3', m('a', {href: 'files/regles_procedures2015.pdf'},'Règles et procédures'))),
|
||||
m('li', m('h3', m('a', {href: 'files/reglements_de_terrain2015.pdf'},'Règlements de terrain'))),
|
||||
m('li', m('h3', m('a', {href: urlASBM}, 'Association des Sports de Balle à Montréal (ASBM)'))),
|
||||
])
|
||||
])
|
||||
);
|
||||
};
|
||||
|
||||
rulesPage.logoAndRules = function(){
|
||||
return m('div.uk-grid',[
|
||||
m('div.uk-width-large-1-3.uk-width-small-1-1', rulesPage.logo()),
|
||||
rulesPage.rules()
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
rulesPage.mission = function(){
|
||||
return m('div.uk-panel.uk-panel-box.uk-panel-box-secondary', [
|
||||
m('h2', 'Mission'),
|
||||
m('p', rulesPage.missionText())
|
||||
]);
|
||||
};
|
||||
|
||||
rulesPage.view = function(){
|
||||
return [
|
||||
m.component(topNavBar),
|
||||
|
||||
m('div.uk-margin-top.uk-margin-bottom.uk-grid',
|
||||
m('div.uk-width-large-3-5.uk-width-medium-4-5.uk-width-large-1-1.uk-container-center', [
|
||||
rulesPage.logoAndRules(),
|
||||
rulesPage.mission()
|
||||
])),
|
||||
m.component(footer)
|
||||
];
|
||||
};
|
||||
|
||||
return rulesPage;
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
define(['m', '_', 'util'], function (m, _, util) {
|
||||
var topNavBar = {};
|
||||
|
||||
topNavBar._urlMapping = {
|
||||
'': 'Accueil',
|
||||
nouvelles: 'Nouvelles',
|
||||
calendrier: 'Calendrier',
|
||||
reglement: 'Règlement',
|
||||
// photos: 'Photos',
|
||||
membre: 'Membre',
|
||||
contact: 'Nous Joindre'
|
||||
};
|
||||
|
||||
topNavBar.controller = function(){
|
||||
return {id: m.route.param("page")};
|
||||
};
|
||||
|
||||
topNavBar._getUrlForId = function(id_){
|
||||
return '#/' + id_;
|
||||
};
|
||||
|
||||
topNavBar._isActive = function(id_){
|
||||
return topNavBar._getUrlForId(id_) == window.location.hash;
|
||||
};
|
||||
|
||||
topNavBar._getItem = function(name, id){
|
||||
var class_ = topNavBar._isActive(id) ? 'uk-active' : 'uk-parent';
|
||||
var url = topNavBar._getUrlForId(id);
|
||||
return m("li", {class: class_}, [m("a",{href: url}, name)]);
|
||||
};
|
||||
|
||||
topNavBar.view = function(controller){
|
||||
return m("nav.uk-navbar.uk-navbar-attached",[
|
||||
m("ul.uk-navbar-nav.uk-navbar-center.uk-visible-large",
|
||||
m('li.uk-parent', m('div.uk-navbar-brand', util.facebookLink())),
|
||||
_.map(topNavBar._urlMapping, topNavBar._getItem)),
|
||||
m("ul.uk-navbar-nav.uk-hidden-large",
|
||||
m('li.uk-parent', util.facebookLink()),
|
||||
_.map(topNavBar._urlMapping, topNavBar._getItem)),
|
||||
]);
|
||||
};
|
||||
|
||||
return topNavBar;
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
// LESS related
|
||||
@import "uikit/scss/uikit-mixins.scss";
|
||||
@import "uikit/scss/core/variables.scss";
|
||||
|
||||
// Phenix colors
|
||||
|
||||
$navbar-background: #f08d28; //#dabd5e;
|
||||
// $foo: ; // #f8c694;
|
||||
|
||||
$panel-box-background: #fce3ca;
|
||||
$table-striped-background: #fce3ca;
|
||||
$navbar-nav-active-background: #fce3ca;
|
||||
$navbar-nav-hover-background: #fce3ca;
|
||||
$panel-box-secondary-background: #fce3ca;
|
||||
$badge-background: #fce3ca;
|
||||
$badge-color: black;
|
||||
$badge-font-size: 2em;
|
||||
|
||||
// Defaults
|
||||
@import "uikit/scss/core/base.scss";
|
||||
|
||||
// Layout
|
||||
@import "uikit/scss/core/grid.scss";
|
||||
@import "uikit/scss/core/panel.scss";
|
||||
@import "uikit/scss/core/block.scss";
|
||||
@import "uikit/scss/core/article.scss";
|
||||
@import "uikit/scss/core/comment.scss";
|
||||
@import "uikit/scss/core/cover.scss";
|
||||
|
||||
// Navs
|
||||
@import "uikit/scss/core/nav.scss";
|
||||
@import "uikit/scss/core/navbar.scss";
|
||||
@import "uikit/scss/core/subnav.scss";
|
||||
@import "uikit/scss/core/breadcrumb.scss";
|
||||
@import "uikit/scss/core/pagination.scss";
|
||||
@import "uikit/scss/core/tab.scss";
|
||||
@import "uikit/scss/core/thumbnav.scss";
|
||||
|
||||
// Elements
|
||||
@import "uikit/scss/core/list.scss";
|
||||
@import "uikit/scss/core/description-list.scss";
|
||||
@import "uikit/scss/core/table.scss";
|
||||
@import "uikit/scss/core/form.scss";
|
||||
|
||||
// Common
|
||||
@import "uikit/scss/core/button.scss";
|
||||
@import "uikit/scss/core/icon.scss";
|
||||
@import "uikit/scss/core/close.scss";
|
||||
@import "uikit/scss/core/badge.scss";
|
||||
@import "uikit/scss/core/alert.scss";
|
||||
@import "uikit/scss/core/thumbnail.scss";
|
||||
@import "uikit/scss/core/overlay.scss";
|
||||
@import "uikit/scss/core/column.scss";
|
||||
@import "uikit/scss/core/animation.scss";
|
||||
|
||||
// JavaScript
|
||||
@import "uikit/scss/core/dropdown.scss";
|
||||
@import "uikit/scss/core/modal.scss";
|
||||
@import "uikit/scss/core/offcanvas.scss";
|
||||
@import "uikit/scss/core/switcher.scss";
|
||||
|
||||
// Need to be loaded last
|
||||
@import "uikit/scss/core/text.scss";
|
||||
@import "uikit/scss/core/utility.scss";
|
||||
@import "uikit/scss/core/flex.scss";
|
||||
@import "uikit/scss/core/contrast.scss";
|
||||
@import "uikit/scss/core/print.scss";
|
||||
@@ -0,0 +1,9 @@
|
||||
@import "custom_uikit";
|
||||
.foo{
|
||||
border: solid;
|
||||
}
|
||||
|
||||
.ph-footer{
|
||||
background-color: $navbar-background;
|
||||
// height: 200px;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,5 +0,0 @@
|
||||
[Dolphin]
|
||||
SortRole=modificationtime
|
||||
Timestamp=2018,3,19,17,32,48
|
||||
Version=4
|
||||
ViewMode=1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 MiB |
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user