From 6d4cadc2aef93ffa77d3cb790617b4798431764b Mon Sep 17 00:00:00 2001 From: Olivier DOSSMANN Date: Mon, 3 Sep 2018 23:08:32 +0200 Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation=20initiale=20du=20projet=20Amber?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .amber.yml | 4 + .gitignore | 15 +++ Dockerfile | 12 ++ README.md | 41 ++++++- config/application.cr | 131 ++++++++++++++++++++++ config/environments/.production.enc | Bin 0 -> 752 bytes config/environments/development.yml | 36 ++++++ config/environments/test.yml | 36 ++++++ config/initializers/database.cr | 6 + config/initializers/i18n.cr | 24 ++++ config/routes.cr | 42 +++++++ config/webpack/common.js | 69 ++++++++++++ config/webpack/development.js | 7 ++ config/webpack/production.js | 11 ++ db/migrations/.gitkeep | 0 docker-compose.yml | 42 +++++++ package.json | 27 +++++ public/crossdomain.xml | 15 +++ public/favicon.ico | Bin 0 -> 15086 bytes public/favicon.png | Bin 0 -> 452 bytes public/robots.txt | 3 + shard.yml | 47 ++++++++ spec/spec_helper.cr | 16 +++ src/assets/fonts/.gitkeep | 0 src/assets/images/.gitkeep | 0 src/assets/images/logo.png | Bin 0 -> 18007 bytes src/assets/javascripts/main.js | 23 ++++ src/assets/stylesheets/main.scss | 117 +++++++++++++++++++ src/cdj_carnetdejeu.cr | 3 + src/controllers/application_controller.cr | 6 + src/controllers/home_controller.cr | 5 + src/locales/en.yml | 2 + src/views/home/index.slang | 9 ++ src/views/layouts/_nav.slang | 2 + src/views/layouts/application.slang | 32 ++++++ 35 files changed, 781 insertions(+), 2 deletions(-) create mode 100644 .amber.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 config/application.cr create mode 100644 config/environments/.production.enc create mode 100644 config/environments/development.yml create mode 100644 config/environments/test.yml create mode 100644 config/initializers/database.cr create mode 100644 config/initializers/i18n.cr create mode 100644 config/routes.cr create mode 100644 config/webpack/common.js create mode 100644 config/webpack/development.js create mode 100644 config/webpack/production.js create mode 100644 db/migrations/.gitkeep create mode 100644 docker-compose.yml create mode 100644 package.json create mode 100644 public/crossdomain.xml create mode 100644 public/favicon.ico create mode 100644 public/favicon.png create mode 100644 public/robots.txt create mode 100644 shard.yml create mode 100644 spec/spec_helper.cr create mode 100644 src/assets/fonts/.gitkeep create mode 100644 src/assets/images/.gitkeep create mode 100644 src/assets/images/logo.png create mode 100644 src/assets/javascripts/main.js create mode 100644 src/assets/stylesheets/main.scss create mode 100644 src/cdj_carnetdejeu.cr create mode 100644 src/controllers/application_controller.cr create mode 100644 src/controllers/home_controller.cr create mode 100644 src/locales/en.yml create mode 100644 src/views/home/index.slang create mode 100644 src/views/layouts/_nav.slang create mode 100644 src/views/layouts/application.slang diff --git a/.amber.yml b/.amber.yml new file mode 100644 index 0000000..6eff810 --- /dev/null +++ b/.amber.yml @@ -0,0 +1,4 @@ +type: app +database: pg +language: slang +model: granite diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0113c5b --- /dev/null +++ b/.gitignore @@ -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 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b0ea544 --- /dev/null +++ b/Dockerfile @@ -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 diff --git a/README.md b/README.md index 34d538d..2ba5858 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,41 @@ # carnetdejeu -Gérer sa collection de jeux vidéos, consoles et figurines. -Et plus si affinités. \ No newline at end of file +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 d’informations, veuillez lire [la licence EUPL 1.2](https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12). diff --git a/config/application.cr b/config/application.cr new file mode 100644 index 0000000..429e84c --- /dev/null +++ b/config/application.cr @@ -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 diff --git a/config/environments/.production.enc b/config/environments/.production.enc new file mode 100644 index 0000000000000000000000000000000000000000..14d34054bb5d6340624dd7a69e7d086c0abf8350 GIT binary patch literal 752 zcmV>k+<&$%9z+@m6F+`6Zb$FKa2XXbjXX? zqHwMgKcf2(PPLQ%#Px*m+_6F#{Vyr+0*>}fHi)BWh+xn&zWnp~-a0`>0&!_+qzf_e z1<)!o=kr+e<}b>XGfuvA?Wr6GY@4yutmtvj#=oWVK@-RN*%qX1vs2|qRd3p=(y0no zmc+emSzoFBDNv^=fSrqG=Z8OwD_rn=xIaZ6v;Bx%D#1Lnzt&~Yz=NEV@+>bdp#vA` zS#xK;sU#~2oVfAliXWNOttKmSDE4jOWRGQ|ZhzWG-1laXLCbf*(|h@R2X6V<>l8;!Oj!UBmQ<%K;svF=hU1q-E9uOk0^p zqcEOsMrd@JuIgg-D*Y*{{#B5ISYG}Z8WJce`?6Mkc&cChRUBuNi90(_9^G4EltbE; z#KGGP^yB3%Pz?JLb%`5^c%=l+sX{IhK~d&`j-loVcC`bdr3SIaKwMC4B`JLX{W2i= zh3Yg1kGVy9jtlAB=fO6zRzeg+S~^a-t0u9VXYt&^K#{i_vcrqlH6M&ix_QP6!T+q! zhrMqWT7tr-cpMXWFfzu@Vt%cb%K%NER3%n!)2X3y^HZ197ncEr6Hw43X^LGi&JmIn zTtCrWpdtVHI6HXc+FTsxyQchr>|Nl^E!zXjY0;hIn+RrWD>&8y*St(#nkxzF0BVEW zR^JKi^^@w4;h%K@n{lk^w|=2`@os9xwJv-a@ClvotN*HA-wjTA<#kkt90GcR#2u&V zsfG74g91)9^VD(XLf312W09EGhG!CipR0SbteCxZD`bAF_nf{&h}%t!mlsoT{wH=8 i_((-o$Y(z?HeL9#teQUNDUexhK9NCCG9e2~zCAN|{d;Nv literal 0 HcmV?d00001 diff --git a/config/environments/development.yml b/config/environments/development.yml new file mode 100644 index 0000000..5a5edc1 --- /dev/null +++ b/config/environments/development.yml @@ -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. + diff --git a/config/environments/test.yml b/config/environments/test.yml new file mode 100644 index 0000000..f90f93f --- /dev/null +++ b/config/environments/test.yml @@ -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. + diff --git a/config/initializers/database.cr b/config/initializers/database.cr new file mode 100644 index 0000000..69378b7 --- /dev/null +++ b/config/initializers/database.cr @@ -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" + diff --git a/config/initializers/i18n.cr b/config/initializers/i18n.cr new file mode 100644 index 0000000..1b005b2 --- /dev/null +++ b/config/initializers/i18n.cr @@ -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 diff --git a/config/routes.cr b/config/routes.cr new file mode 100644 index 0000000..0c9e0e3 --- /dev/null +++ b/config/routes.cr @@ -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 diff --git a/config/webpack/common.js b/config/webpack/common.js new file mode 100644 index 0000000..336418e --- /dev/null +++ b/config/webpack/common.js @@ -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; diff --git a/config/webpack/development.js b/config/webpack/development.js new file mode 100644 index 0000000..3ec0d95 --- /dev/null +++ b/config/webpack/development.js @@ -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' +}); diff --git a/config/webpack/production.js b/config/webpack/production.js new file mode 100644 index 0000000..4a44b47 --- /dev/null +++ b/config/webpack/production.js @@ -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 } + }) + ] +}); diff --git a/db/migrations/.gitkeep b/db/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..13ff841 --- /dev/null +++ b/docker-compose.yml @@ -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 + + + + + + + + + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..edb2d9c398fa241769b9420727238cf13d38939a GIT binary patch literal 15086 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 + +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 diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr new file mode 100644 index 0000000..ecec995 --- /dev/null +++ b/spec/spec_helper.cr @@ -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 + diff --git a/src/assets/fonts/.gitkeep b/src/assets/fonts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/images/.gitkeep b/src/assets/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..457789a19220d1fe3692ebb3d184986412751fda GIT binary patch literal 18007 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 literal 0 HcmV?d00001 diff --git a/src/assets/javascripts/main.js b/src/assets/javascripts/main.js new file mode 100644 index 0000000..4b3eb94 --- /dev/null +++ b/src/assets/javascripts/main.js @@ -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()) ; + }; + + }()); +} diff --git a/src/assets/stylesheets/main.scss b/src/assets/stylesheets/main.scss new file mode 100644 index 0000000..638d392 --- /dev/null +++ b/src/assets/stylesheets/main.scss @@ -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; + } +} \ No newline at end of file diff --git a/src/cdj_carnetdejeu.cr b/src/cdj_carnetdejeu.cr new file mode 100644 index 0000000..66d2b28 --- /dev/null +++ b/src/cdj_carnetdejeu.cr @@ -0,0 +1,3 @@ +require "../config/*" + +Amber::Server.start diff --git a/src/controllers/application_controller.cr b/src/controllers/application_controller.cr new file mode 100644 index 0000000..0967557 --- /dev/null +++ b/src/controllers/application_controller.cr @@ -0,0 +1,6 @@ +require "jasper_helpers" + +class ApplicationController < Amber::Controller::Base + include JasperHelpers + LAYOUT = "application.slang" +end diff --git a/src/controllers/home_controller.cr b/src/controllers/home_controller.cr new file mode 100644 index 0000000..2543e78 --- /dev/null +++ b/src/controllers/home_controller.cr @@ -0,0 +1,5 @@ +class HomeController < ApplicationController + def index + render("index.slang") + end +end diff --git a/src/locales/en.yml b/src/locales/en.yml new file mode 100644 index 0000000..28c4419 --- /dev/null +++ b/src/locales/en.yml @@ -0,0 +1,2 @@ +--- +welcome_to_amber: "Welcome to Amber Framework!" diff --git a/src/views/home/index.slang b/src/views/home/index.slang new file mode 100644 index 0000000..1dbac34 --- /dev/null +++ b/src/views/home/index.slang @@ -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 diff --git a/src/views/layouts/_nav.slang b/src/views/layouts/_nav.slang new file mode 100644 index 0000000..0888270 --- /dev/null +++ b/src/views/layouts/_nav.slang @@ -0,0 +1,2 @@ +- active = context.request.path == "/" ? "active" : "" +a class="nav-item #{active}" href="/" Home diff --git a/src/views/layouts/application.slang b/src/views/layouts/application.slang new file mode 100644 index 0000000..aa83d80 --- /dev/null +++ b/src/views/layouts/application.slang @@ -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"