Création initiale du projet Amber

This commit is contained in:
Olivier DOSSMANN 2018-09-03 23:08:32 +02:00
parent a2c4523880
commit 6d4cadc2ae
35 changed files with 781 additions and 2 deletions

4
.amber.yml Normal file
View File

@ -0,0 +1,4 @@
type: app
database: pg
language: slang
model: granite

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
/doc/
/lib/
/.crystal/
/.shards/
/.vscode/
/tmp/
.env
.encryption_key
production.yml
.DS_Store
/bin/
/node_modules
/public/dist
shard.lock
package-lock.json

12
Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM amberframework/amber:v0.9.0
WORKDIR /app
COPY shard.* /app/
RUN shards install
COPY . /app
RUN rm -rf /app/node_modules
CMD amber watch

View File

@ -1,4 +1,41 @@
# carnetdejeu
Gérer sa collection de jeux vidéos, consoles et figurines.
Et plus si affinités.
Carnet de jeu (CDJ) est une application web permettant de gérer sa collection de jeux vidéos, consoles et figurines.
Site officiel : [https://carnetdejeu.fr/](https://carnetdejeu.fr/)
# Motivation
L'idée principale de ce projet est d'avoir - enfin - un site web francophone concernant sa collection de jeux vidéos.
Mais également d'avoir une alternative OpenSource au très connu Backloggery.com.
# Pré-requis
* Crystal 0.26.0
* Amber 0.9.0
* shards 0.8.1
# Installation des dépendances Crystal
```bash
shards install
```
# Aperçu de l'application
```
amber w
```
# Fabriqué avec
* [Amber](https://amberframework.org/) - framework pour créer des applications simples, rapides et agréables
# Contributeurs
* Olivier DOSSMANN - création initiale - [blankoworld](https://github.com/blankoworld/)
# Licence
Ce projet est délivré sous les termes de la licence EUPL 1.2. Pour plus dinformations, veuillez lire [la licence EUPL 1.2](https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12).

131
config/application.cr Normal file
View File

@ -0,0 +1,131 @@
require "./initializers/**"
require "amber"
require "../src/controllers/application_controller"
require "../src/controllers/**"
# About Application.cr File
#
# This is Amber application main entry point. This file is responsible for loading
# initializers, classes, and all application related code in order to have
# Amber::Server boot up.
#
# > We recommend to not modify the order of the require since the order will
# affect the behavior of the application.
#
# With `Amber::Server.configure` block you can redefine the Server configuration
# settings and use ENVIRONMENT variables and/or values evaluated at runtime.
#
# > Important! Yaml configurations are first class citizen and are loaded first before
# this file, we recommend to use yaml configurations before changing any settings here.
# Any uncommented setting here will override the YAML with the value set here.
Amber::Server.configure do |settings|
# Use your environment variables settings here.
#
# Name: A name that identifies this application. This is not internally
# used by the framework.
#
# settings.name = "Cdj Carnetdejeu web application."
#
#
# Colorize Logging: specifies whether or not to use ANSI color codes
# when logging information, display the time and/or to display the severity level.
# Defaults to true.
#
# Log Level defines the verbosity of the Amber logger. This option defaults to
# debug for all environments. The available log levels are: debug, info, warn,
# error, fatal, and unknown.
#
# settings.logging.colorize = true
# settings.logging.severity = "debug"
# settings.logging.filter = %w(password confirm_password)
# settings.logging.skip = %w()
# settings.logging.context = %w(request headers cookies session params)
#
#
# Secret Key Base: is used for specifying a key which allows sessions
# for the application to be verified against a known secure key to
# prevent tampering. Applications get Amber.secret_key
# initialized to a random key present in `ENV["AMBER_SECRET_KEY"]` or
# `.amber_secret_key` in this order.
#
# settings.secret_key_base= FEHWm3Fpm7vrPejFPM9x-3PLkj7C_fho6N-nIaBa19g
#
#
# Host: is the application server host address or ip address. Useful for when
# deploying Amber to a PAAS and likely the assigned server IP is either
# known or unknown. Defaults to an environment variable HOST
#
# settings.host = ENV["HOST"] if ENV["HOST"]?
#
#
# Port Reuse: Amber supports clustering mode which allows to spin
# multiple app instances per core. This setting allows to bind the different
# instances to the same port. Default this setting to true if the number or process
# is greater than 1.
#
# > Read more about Linux PORT REUSE https://lwn.net/Articles/542629/
#
# settings.port_reuse = true
#
#
# Process Count: This will enable Amber to be used in cluster mode,
# spinning an instance for each number of process specified here.
# Rule of thumb, always leave at least 1 core available for system processes/resources.
#
# settings.process_count = ENV["PROCESS_COUNT"].to_i if ENV["PROCESS_COUNT"]?
#
#
# PORT: This is the port that you're application will run on. Examples would be (80, 443, 3000, 8080)
#
settings.port = ENV["PORT"].to_i if ENV["PORT"]?
#
#
# Redis URL: Redis is an in memory key value storage. Amber utilizes redis as
# a storing option for session information.
#
# settings.redis_url = ENV["REDIS_URL"] if ENV["REDIS_URL"]?
#
#
# Database URL: This is the database connection string or data file url.
# The connection string contains the information to establish a connection to the
# database or the data file. Defaults to the database provider you chose at
# at app generation.
#
# settings.database_url = ENV["DATABASE_URL"] if ENV["DATABASE_URL"]?
#
#
# SSL Key File: The private key is a text file used initially to generate a
# Certificate Signing Request (CSR), and later to secure and verify connections
# using the certificate created per that request. The private key is used to create
# a digital signature as you might imagine from the name, the private key should be
# ``closely guarded.
#
# settings.ssl_key_file = ENV["SSL_KEY_FILE"] if ENV["SSL_KEY_FILE"]?
#
#
# SSL Cert File: This represents the signed certificate file. SSL Certificates are
# small data files that digitally bind a cryptographic key to an organization's
# details. When installed on a web server, it activates the padlock and the https
# protocol and allows secure connections from a web server to a browser.
#
# settings.ssl_cert_file = ENV["SSL_CERT_FILE"] if ENV["SSL_CERT_FILE"]?
#
#
# Session: A Hash that specifies the session storage mechanism, expiration and key to be used
# for the application. The `key` specifies the name of the cookie to be used defaults to
# "amber.session". The store can be `encrypted_cookie`, `signed_cookie` or `redis`. Expires
# when set to 0 means this is indefinitely and is expressed in seconds.
#
# settings.session = { "key" => "amber.session", "store" => "signed_cookie", "expires" => 0 }
#
#
# Logger: is the logger that Amber and other capable shards in the project will use
# instead of writing directly to STDOUT. Supply a custom logger to write to syslog, etc.
#
# settings.logger = Amber::Environment::Logger.new(File.open("cdj_carnetdejeu.log", "w"))
#
#
end

Binary file not shown.

View File

@ -0,0 +1,36 @@
secret_key_base: cie0hbJtXS-F51akAYdEeNof67tLG4q-L5bpaLqgPTE
port: 3000
name: cdj_carnetdejeu
logging:
severity: debug
colorize: true
filter:
- password
- confirm_password
context:
- request
- session
- headers
- cookies
- params
host: 0.0.0.0
port_reuse: true
process_count: 1
# ssl_key_file:
# ssl_cert_file:
redis_url: "redis://localhost:6379"
database_url: postgres://postgres:@localhost:5432/cdj_carnetdejeu_development
session:
key: amber.session
store: signed_cookie
expires: 0
smtp:
enabled: false
secrets:
description: Store your development secrets credentials and settings here.

View File

@ -0,0 +1,36 @@
secret_key_base: 2jEkAoKdioIl6U1W0T-Zu2U7V5HRQ3-GpeIxOeEVjms
port: 3000
name: cdj_carnetdejeu
logging:
severity: debug
colorize: true
filter:
- password
- confirm_password
context:
- request
- session
- headers
- cookies
- params
host: 0.0.0.0
port_reuse: false
process_count: 1
# ssl_key_file:
# ssl_cert_file:
redis_url: "redis://localhost:6379"
database_url: postgres://postgres:@localhost:5432/cdj_carnetdejeu_test
session:
key: amber.session
store: signed_cookie
expires: 0
smtp:
enabled: false
secrets:
description: Store your development secrets credentials and settings here.

View File

@ -0,0 +1,6 @@
require "granite/adapter/pg"
Granite::Adapters << Granite::Adapter::Pg.new({name: "pg", url: Amber.settings.database_url})
Granite.settings.logger = Amber.settings.logger.dup
Granite.settings.logger.progname = "Granite"

View File

@ -0,0 +1,24 @@
require "citrine-i18n"
Citrine::I18n.configure do |settings|
# Backend storage (as supported by i18n.cr)
# settings.backend = I18n::Backend::Yaml.new
# Default locale (defaults to "en" and "./src/locales/**/en.yml").
# For a new default locale to be accepted, it must be found by the
# backend storage and reported in "settings.available_locales".
# settings.default_locale = "en"
# Separator between sublevels of data (defaults to '.')
# e.g. I18n.translate("some/thing") instead of "some.thing"
# settings.default_separator = '.'
# Returns the current exception handler. Defaults to an instance of
# I18n::ExceptionHandler.
# settings.exception_handler = ExceptionHandler.new
# The path from where the translations should be loaded
settings.load_path += ["./src/locales"]
end
I18n.init

42
config/routes.cr Normal file
View File

@ -0,0 +1,42 @@
Amber::Server.configure do
pipeline :web do
# Plug is the method to use connect a pipe (middleware)
# A plug accepts an instance of HTTP::Handler
plug Amber::Pipe::PoweredByAmber.new
# plug Amber::Pipe::ClientIp.new(["X-Forwarded-For"])
plug Citrine::I18n::Handler.new
plug Amber::Pipe::Error.new
plug Amber::Pipe::Logger.new
plug Amber::Pipe::Session.new
plug Amber::Pipe::Flash.new
plug Amber::Pipe::CSRF.new
end
pipeline :api do
plug Amber::Pipe::PoweredByAmber.new
plug Amber::Pipe::Error.new
plug Amber::Pipe::Logger.new
plug Amber::Pipe::Session.new
plug Amber::Pipe::CORS.new
end
# All static content will run these transformations
pipeline :static do
plug Amber::Pipe::PoweredByAmber.new
plug Amber::Pipe::Error.new
plug Amber::Pipe::Static.new("./public")
end
routes :web do
get "/", HomeController, :index
end
routes :api do
end
routes :static do
# Each route is defined as follow
# verb resource : String, controller : Symbol, action : Symbol
get "/*", Amber::Controller::Static, :index
end
end

69
config/webpack/common.js Normal file
View File

@ -0,0 +1,69 @@
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
let config = {
entry: {
'main.bundle.js': './src/assets/javascripts/main.js',
'main.bundle.css': './src/assets/stylesheets/main.scss'
},
output: {
filename: '[name]',
path: path.resolve(__dirname, '../../public/dist'),
publicPath: '/dist'
},
resolve: {
alias: {
amber: path.resolve(__dirname, '../../lib/amber/assets/js/amber.js')
}
},
module: {
rules: [
{
test: /\.css$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
},
{
test: /\.(png|svg|jpg|gif)$/,
exclude: /node_modules/,
use: [
'file-loader?name=/images/[name].[ext]'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
exclude: /node_modules/,
use: [
'file-loader?name=/[name].[ext]'
]
},
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['env']
}
}
]
},
plugins: [
new ExtractTextPlugin('main.bundle.css'),
],
// For more info about webpack logs see: https://webpack.js.org/configuration/stats/
stats: 'errors-only'
};
module.exports = config;

View File

@ -0,0 +1,7 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./common.js');
module.exports = merge(common, {
devtool: 'inline-source-map'
});

View File

@ -0,0 +1,11 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./common.js');
module.exports = merge(common, {
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
})
]
});

0
db/migrations/.gitkeep Normal file
View File

42
docker-compose.yml Normal file
View File

@ -0,0 +1,42 @@
version: '2'
services:
app:
build: .
image: cdj_carnetdejeu
command: amber watch
environment:
DATABASE_URL: postgres://admin:password@db:5432/cdj_carnetdejeu_development
ports:
- 3000:3000
links:
- db
volumes:
- .:/app
- nodes:/app/node_modules
- shards:/app/lib
migrate:
build: .
image: cdj_carnetdejeu
command: bash -c 'while ! nc -q 1 db 5432 </dev/null; do sleep 1; done && amber db migrate seed'
environment:
DATABASE_URL: postgres://admin:password@db:5432/cdj_carnetdejeu_development
volumes:
- .:/app
links:
- db
db:
image: postgres
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: cdj_carnetdejeu_development
volumes:
- db:/var/lib/postgres/data
volumes:
db:
nodes:
shards:

27
package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "cdj_carnetdejeu",
"version": "0.1.0",
"description": "Cdj Carnetdejeu with Amber",
"private": true,
"author": "Olivier DOSSMANN",
"license": "UNLICENSED",
"scripts": {
"build": "webpack --config config/webpack/development.js",
"watch": "webpack -w --config config/webpack/development.js",
"release": "webpack -p --config config/webpack/production.js",
"test": "echo \"No test specified\" && exit 1"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"node-sass": "^4.9.0",
"sass-loader": "^7.0.1",
"style-loader": "^0.21.0",
"webpack": "^3.12.0",
"webpack-merge": "^4.1.2",
"extract-text-webpack-plugin": "^3.0.2"
}
}

15
public/crossdomain.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
<!-- Most restrictive policy: -->
<site-control permitted-cross-domain-policies="none"/>
<!-- Least restrictive policy: -->
<!--
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>
-->
</cross-domain-policy>

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

3
public/robots.txt Normal file
View File

@ -0,0 +1,3 @@
# http://www.robotstxt.org
User-agent: *
Disallow:

47
shard.yml Normal file
View File

@ -0,0 +1,47 @@
name: cdj_carnetdejeu
version: 0.1.0
authors:
- Olivier DOSSMANN <git@dossmann.net>
crystal: 0.26.0
license: UNLICENSED
targets:
cdj_carnetdejeu:
main: src/cdj_carnetdejeu.cr
amber:
main: lib/amber/src/amber/cli.cr
dependencies:
amber:
github: amberframework/amber
version: 0.9.0
#branch: master
granite:
github: amberframework/granite
version: ~> 0.13.0
quartz_mailer:
github: amberframework/quartz-mailer
version: ~> 0.5.1
jasper_helpers:
github: amberframework/jasper-helpers
version: ~> 0.2.0
pg:
github: will/crystal-pg
version: ~> 0.15.0
citrine-i18n:
github: amberframework/citrine-i18n
version: 0.3.2
development_dependencies:
garnet_spec:
github: amberframework/garnet-spec
version: ~> 0.2.1

16
spec/spec_helper.cr Normal file
View File

@ -0,0 +1,16 @@
ENV["AMBER_ENV"] ||= "test"
require "spec"
require "micrate"
require "garnet_spec"
require "../config/*"
Micrate::DB.connection_url = Amber.settings.database_url
# Automatically run migrations on the test database
Micrate::Cli.run_up
# Disable Granite logs in tests
Granite.settings.logger = Logger.new nil

View File

View File

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,23 @@
import Amber from 'amber'
if (!Date.prototype.toGranite) {
(function() {
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
Date.prototype.toGranite = function() {
return this.getUTCFullYear() +
'-' + pad(this.getUTCMonth() + 1) +
'-' + pad(this.getUTCDate()) +
' ' + pad(this.getUTCHours()) +
':' + pad(this.getUTCMinutes()) +
':' + pad(this.getUTCSeconds()) ;
};
}());
}

View File

@ -0,0 +1,117 @@
$font-stack: "Helvetica Neue", Helvetica, Arial, sans-serif;
$background-color: #f4994b;
$nav-item-color: #ffe4cd;
/*
* Globals
*/
body {
font-family: $font-stack;
color: #555;
}
h1, .h1,
h2, .h2,
h3, .h3,
h4, .h4,
h5, .h5,
h6, .h6 {
margin-top: 0;
font-family: $font-stack;
font-weight: normal;
color: #333;
}
/*
* Override Bootstrap's default container.
*/
@media (min-width: 1200px) {
.container {
width: 970px;
}
}
/*
* Masthead for nav
*/
.masthead {
background-color: $background-color;
-webkit-box-shadow: inset 0 -2px 5px rgba(0,0,0,.1);
box-shadow: inset 0 -2px 5px rgba(0,0,0,.1);
}
/* Nav links */
.nav-item {
position: relative;
display: inline-block;
padding: 10px;
font-weight: 500;
color: $nav-item-color;
}
.nav-item:hover,
.nav-item:focus {
color: #fff;
text-decoration: none;
}
/* Active state gets a caret at the bottom */
.nav .active {
color: #fff;
}
.nav .active:after {
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 0;
margin-left: -5px;
vertical-align: middle;
content: " ";
border-right: 5px solid transparent;
border-bottom: 5px solid;
border-left: 5px solid transparent;
}
.main {
padding-top: 20px;
}
#logo {
background-color: $background-color;
background-image: url("../images/logo.png");
background-size:contain;
width: 200px;
height:278px;
}
/* Hide logo in small screens */
@media (max-width: 767px) {
#logo {
display: none;
}
}
.table td, .table th {
vertical-align: middle;
}
.alert {
margin-top: 1em;
p {
margin-top: 0;
margin-bottom: 0;
}
}
// For Navigation pulling right
.nav-item-auth {
&.nav-item-auth-signout, &.nav-item-auth-signup {
order: 9999;
}
&.nav-item-auth-profile, &.nav-item-auth-signin {
order: 9990;
margin-left: auto;
}
}

3
src/cdj_carnetdejeu.cr Normal file
View File

@ -0,0 +1,3 @@
require "../config/*"
Amber::Server.start

View File

@ -0,0 +1,6 @@
require "jasper_helpers"
class ApplicationController < Amber::Controller::Base
include JasperHelpers
LAYOUT = "application.slang"
end

View File

@ -0,0 +1,5 @@
class HomeController < ApplicationController
def index
render("index.slang")
end
end

2
src/locales/en.yml Normal file
View File

@ -0,0 +1,2 @@
---
welcome_to_amber: "Welcome to Amber Framework!"

View File

@ -0,0 +1,9 @@
.row
#logo
.col-sm-12.col-md-6
h2 = t "welcome_to_amber"
p Thank you for trying out the Amber Framework. We are working hard to provide a super fast and reliable framework that provides all the productivity tools you are used to without sacrificing the speed.
.list-group
a.list-group-item.list-group-item-action target="_blank" href="https://docs.amberframework.org" Getting Started with Amber Framework
a.list-group-item.list-group-item-action target="_blank" href="https://github.com/veelenga/awesome-crystal" List of Awesome Crystal projects and shards
a.list-group-item.list-group-item-action target="_blank" href="https://crystalshards.xyz" What's hot in Crystal right now

View File

@ -0,0 +1,2 @@
- active = context.request.path == "/" ? "active" : ""
a class="nav-item #{active}" href="/" Home

View File

@ -0,0 +1,32 @@
doctype html
html
head
title Cdj Carnetdejeu using Amber
meta charset="utf-8"
meta http-equiv="X-UA-Compatible" content="IE=edge"
meta name="viewport" content="width=device-width, initial-scale=1"
link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
link rel="stylesheet" href="/dist/main.bundle.css"
link rel="apple-touch-icon" href="/favicon.png"
link rel="icon" href="/favicon.png"
link rel="icon" type="image/x-icon" href="/favicon.ico"
body
.masthead
.container
nav.nav
== render(partial: "layouts/_nav.slang")
.container
.row
.col-sm
- flash.each do |key, value|
div class="alert alert-#{key}"
p = flash[key]
.row
.col-sm-12.main
== content
script src="https://code.jquery.com/jquery-3.3.1.min.js"
script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"
script src="/dist/main.bundle.js"