Skip to content

Commit

Permalink
Devoxx FR 2023 - new home page using TailwindCSS
Browse files Browse the repository at this point in the history
  • Loading branch information
nicmarti committed Nov 19, 2022
1 parent 38083b4 commit 065c1c1
Show file tree
Hide file tree
Showing 12 changed files with 525 additions and 1,715 deletions.
80 changes: 67 additions & 13 deletions README_FRONT.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,101 @@
cfp-devoxxfr
============

Tailwind is used to generate the stylesheets for the website.
Tailwind is used to generate the stylesheets for the website and the home page.

# Pre-requisites

Install `nvm`

- Install `nvm`
- Install and activate the correct version of nodejs
- Install `npm`
- Install `tailwindcss` and its dependencies
- Install `postcss` and its dependencies
- Install `autoprefixer` and its dependencies

## Install node v16.4.0

`nvm install v16.4.0`
```
nvm install v16.4.0
v16.4.0 is already installed.
Now using node v16.4.0 (npm v6.13.4)
```

Load the version from the `.nvmrc` file

```
nvm use
Found '~/Dev/cfp-devoxx/.nvmrc' with version <16.4.0>
Now using node v16.4.0 (npm v6.13.4)
```

After the installation, restart a shell and check that the node version is v16.4.0 :

```cfp-devoxx git:(dev) ✗ node -v
v16.4.0
```
npm -v
6.13.4
```

## How to install Tailwind

Update browserlits :

```
npx browserslist@latest --update-db
```

Then :

```
npm install --save-dev "browserslist@>= 4.21.0"
```

## Check your version of node
Install Tailwind and additional modules :

# How to install Tailwind
```
npm install -D tailwindcss postcss autoprefixer
```

```npm install```
This is the version we used :
+ tailwindcss@3.2.4
+ autoprefixer@10.4.13
+ postcss@8.4.19

# For local developpement

## For the main CFP website

```
npx tailwindcss -i ./tailwind/src/cfp_devoxx_fr_2023.css -o ./public/devoxx_fr_2023/devoxx_fr_2023.css --watch
```

## Public web pages for program

If you need to work on the public web pages of the CFP (program, speakers's bio, agenda, etc.), you can use the following command to generate the stylesheets:

```npx tailwindcss -i ./public/css/dvx_tailwind.css -o ./public/css/devoxx_generated_tailwind.css --watch```
```
npx tailwindcss -i ./public/css/dvx_tailwind.css -o ./public/css/devoxx_generated_tailwind.css --watch
```

## CFP pages


## For production before deployment

Make sure to update and to save on Git the generated CSS file.
No extra npm tasks are executed on the production environment at deployment time.

```npx tailwindcss -i ./public/css/dvx_tailwind.css -o ./public/css/devoxx_generated_tailwind.css --minify```
```
npx tailwindcss -i ./public/css/dvx_tailwind.css -o ./public/css/devoxx_generated_tailwind.css --minify
```

# Trouble shooting
# Trouble shooting on MacOS

If `npx` returns the following error, you need to install the latest version of node

```cfp-devoxx git:(dev) ✗ npx
```
cfp-devoxx git:(dev) ✗ npx
<function>:32
#unloaded = false
^
Expand Down
2 changes: 1 addition & 1 deletion app/views/Application/home.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

@import helper.twitterBootstrap._

@main(Messages("cfp.title")) {
@main(Messages("cfp.title"), showNav=false) {
<div class="row">
<div class="col-12">
<div class="page-header">
Expand Down
204 changes: 119 additions & 85 deletions app/views/Application/index.scala.html
Original file line number Diff line number Diff line change
@@ -1,118 +1,152 @@
@()(implicit lang: Lang, flash: Flash, req:RequestHeader)
@()(implicit lang: Lang, flash: Flash, req: RequestHeader)
@import library.FormatDate

@main(Messages("cfp.title")){
<div class="container">
<div class="jumbotron dvx_2023">
<img src="@routes.Assets.at(path="/public",file="devoxx_fr_2023/logo_devoxx_fr_2023.png")" alt="Logo Devoxx France" height="100" width="1000">
<h1 class="display-3"><i class="far fa-comment"></i> @Messages("appel.conf")</h1>
<p class="lead">@Messages("appel.conf.dates")</p>
<hr class="my-4">
</div>
<div class="row">
@if(flash.get("error").isDefined) {
<div class="col-md-12">
<div class="alert alert-danger alert-dismissable">
<strong>Error :</strong>
@flash.get("error").get
</div>
</div>
}
@if(flash.get("success").isDefined) {
<div class="col-md-12">
<div class="alert alert-success alert-dismissable">
@flash.get("success").get
</div>
</div>
}
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="card mb-3">
<h3 class="card-header"><i class="far fa-calendar-alt"></i> Agenda</h3>
<div class="card-body">
<p class="card-text"><strong>@Messages("cfp.opening") :</strong> @FormatDate.jodaFullDateFormat(ConferenceDescriptor.current().timing.cfpOpenedOn, lang)</p>
<p class="card-text"><strong>@Messages("cfp.closing") :</strong> @FormatDate.jodaFullDateFormat(ConferenceDescriptor.current().timing.cfpClosedOn, lang)</p>
@if(ConferenceDescriptor.isCFPOpen){
<p class="card-text"><strong>@Messages("cfp.reminder") :</strong> <span class="badge badge-warning">@Messages("cfp.reminder.proposals")</span> </p>
}else{
<p class="card-text"><strong>@Messages("cfp.reminder") :</strong> <span class="badge badge-danger">@Messages("cfp.isClosed")</span> </p>
}
<p class="card-text"><strong>@Messages("cfp.program")</strong> @Messages("cfp.program.date", FormatDate.jodaFullDateFormat(ConferenceDescriptor.current().timing.scheduleAnnouncedOn, lang))</p>
</div>
</div>
<!doctype html>
<html lang="en" class="text-dvx-white bg-dvx-mainback font-sans-serif">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CFP @Messages("CONF.title")</title>
<meta name="generator" content="Play! 2.3 Scala"/>
<link rel="shortcut icon" href="@routes.Assets.at(path = "/public", file = "images/favicon.ico")">

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Aldrich&Big+Shoulders+Inline+Display">
<link rel="stylesheet" type="text/css" href="@routes.Assets.at(path = "/public", file = "devoxx_fr_2023/devoxx_fr_2023.css")">
<script src="//code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf8" ></script>
<script src="//kit.fontawesome.com/6cd398e38d.js" crossorigin="anonymous"></script>
</head>
<body>
<section class="bg-dvx-back">
<div class="container mx-auto py-2 lg:py-4">
<a href="https://www.devoxx.fr"><h1>DEVOX<span class="text-dvx-accent">X</span> <span class="text-white text-uppercase">France</span></h1></a>
</div>
</section>

<div class="col-lg-6 col-md-6 col-sm-12">
<div class="card mb-3">
<h3 class="card-header"><i class="fab fa-youtube"></i> @Messages("video.title")</h3>
<div class="card-body">
<p class="card-text">@Messages("video.tag") <a href="https://www.youtube.com/channel/UCsVPQfo5RZErDL41LoWvk0A" class="btn btn-primary" target="new">YouTube channel</a> </p>
</div>
<section class="bg-fixed bg-clip-content bg-center bg-cover bg-no-repeat" style="background-image: url('/assets/devoxx_fr_2023/devoxx_fr_call_for_paper_2023.jpeg')">
<div class="grid max-w-screen-xl px-4 py-8 mx-auto lg:gap-8 xl:gap-0 lg:py-16 lg:grid-cols-12">
<div class="mr-auto place-self-center lg:col-span-7 bg-gradient-to-b bg-dvx-mainback p-4">

<h1 class="max-w-2xl mb-4 text-4xl font-extrabold tracking-tight leading-none md:text-5xl xl:text-6xl bg-clip-text text-transparent bg-gradient-to-bl from-yellow-100 to-orange-700">@Messages("appel.conf")</h1>
<p class="max-w-2xl mb-6 font-light text-black-200 lg:mb-8 md:text-lg lg:text-xl">11ème édition - du 12 au 14 avril 2023</p>
@if(ConferenceDescriptor.isCFPOpen) {
<h2>@Messages("cfp.isOpen")</h2>
<a href="@routes.Application.home()" class="btn-primary inline-flex items-center justify-center px-5 py-3 mr-3 text-base font-medium text-center text-white rounded-lg bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:focus:ring-primary-900">
<svg class="w-5 h-5 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
&nbsp;@Messages("cfp.open.enter")
</a>
} else {
<h2>@Messages("cfp.isClosed")</h2>
}

</div>
<div class="hidden lg:mt-0 lg:col-span-5 lg:flex">
<img src="/assets/devoxx_fr_2023/robot7.png" alt="Call for Paper Devoxx France 2023">
</div>
</div>
</section>

<div class="container mx-auto pt-4 lg:pt-8">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="card mb-3">
@if(ConferenceDescriptor.isCFPOpen){
<h3 class="card-header"><i class="fas fa-bullhorn"></i> @Messages("cfp.isOpen")</h3>
}else{
<h3 class="card-header"><i class="fas fa-bullhorn"></i> @Messages("cfp.isClosed")</h3>
}
<div class="card-body">
<div class="bg-dvx-box border-solid border-2 border-dvx-orange p-3 rounded mb-4">
<h2>Agenda</h2>

<p class="text-normal">@Messages("cfp.opening")
: <span class="text-dvx-accent">@FormatDate.jodaFullDateFormat(ConferenceDescriptor.current().timing.cfpOpenedOn, lang)</span> </p>
<p class="text-normal">@Messages("cfp.closing")
: <span class="text-dvx-accent">@FormatDate.jodaFullDateFormat(ConferenceDescriptor.current().timing.cfpClosedOn, lang)</span></p>
@if(ConferenceDescriptor.isCFPOpen) {
<a href="@routes.Application.home()" class="btn btn-primary">@Messages("cfp.open.enter")</a>
<p class="text-normal">@Messages("cfp.reminder")
: <span class="text-dvx-accent">@Messages("cfp.reminder.proposals")</span> </p>
} else {
<p>@Messages("cfp.isClosed.expl")</p>
<a href="@routes.Application.home()" class="btn btn-primary">@Messages("cfp.closed.enter")</a>
<p class="text-normal">@Messages("cfp.reminder")
: <span class="text-dvx-accent">@Messages("cfp.isClosed")</span> </p>
}
</div>
<p class="text-normal">@Messages("cfp.program") <span class="text-dvx-accent">@Messages("cfp.program.date", FormatDate.jodaFullDateFormat(ConferenceDescriptor.current().timing.scheduleAnnouncedOn, lang))</span></p>

</div>
</div>

<div class="bg-dvx-box border-solid border-2 border-dvx-orange p-3 rounded mb-4">
<h2>@Messages("video.title")</h2>
<div class="items-center space-y-4 sm:space-x-4 sm:flex sm:space-y-0">
<p class="text-normal">@Messages("video.tag") <a href="https://www.youtube.com/channel/UCsVPQfo5RZErDL41LoWvk0A" class="btn-primary" target="new">
YouTube Devoxx France</a> </p>
</div>

</div>

<div class="bg-dvx-box border-solid border-2 border-dvx-orange p-3 rounded mb-4">
@if(ConferenceDescriptor.isCFPOpen) {
<h2>@Messages("cfp.isOpen")</h2>
} else {
<h2>@Messages("cfp.isClosed")</h2>
}

<div class="items-center space-y-4 sm:space-x-4 sm:flex sm:space-y-0">
@if(ConferenceDescriptor.isCFPOpen) {
<a href="@routes.Application.home()" class="btn-primary">@Messages("cfp.open.enter")</a>
} else {
<p class="text-normal">@Messages("cfp.isClosed.expl")</p>
<a href="@routes.Application.home()" class="btn-primary">@Messages("cfp.closed.enter")</a>
}
</div>
</div>


@if(ConferenceDescriptor.isGoldenTicketActive) {
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="card mb-3">
<h3 class="card-header"><i class="fas fa-ticket-alt"></i> @Messages("cfp.goldenTicket")</h3>
<div class="card-body">
<p class="card-text"><a href="@routes.GoldenTicketController.authenticate()" class="btn btn-primary">@Messages("cfp.gt.enter")</a></p>
</div>
<div class="bg-dvx-box border-solid border-2 border-dvx-orange p-3 rounded mb-4">
<h2>@Messages("cfp.goldenTicket")</h2>
<div class="items-center space-y-4 sm:space-x-4 sm:flex sm:space-y-0">
<a href="@routes.GoldenTicketController.authenticate()" class="btn-primary">@Messages("cfp.gt.enter")</a>
</div>
</div>
}

@if(ProgramSchedule.publishedProgramSchedule().map(_.favoritesActivated).getOrElse(false)){
<div class="col-12">
<div class="card mb-3">
<h3 class="card-header"><i class="far fa-calendar-alt"></i> @Messages("cfp.showAgenda.title")</h3>
<div class="card-body">
<p class="card-text"><A href="@routes.Publisher.homePublisher()" class="btn btn-primary" title="See the conference agenda">@Messages("cfp.showAgenda.txt")</A> </p>
</div>
@if(ProgramSchedule.publishedProgramSchedule().map(_.favoritesActivated).getOrElse(false)) {
<div class="bg-dvx-box border-solid border-2 border-dvx-orange p-3 rounded mb-4">
<h2>@Messages("cfp.showAgenda.title")</h2>
<div class="items-center space-y-4 sm:space-x-4 sm:flex sm:space-y-0">
<A href="@routes.Publisher.homePublisher()" class="btn-primary" title="See the conference agenda">@Messages("cfp.showAgenda.txt")</A>
</div>
</div>
<div class="clearfix">
</div>
}

<div class="col-12">
<div class="card mb-1">
<h3 class="card-header"><i class="fas fa-books"></i> @Messages("theme.title")</h3>
<div class="card-body">
<p class="card-text">@Messages("theme.track")</p>
<table class="table table-bordered table-striped">
<div class="bg-dvx-box border-solid border-2 border-dvx-orange p-3 rounded mb-4">
<h2>@Messages("theme.title")</h2>
<div class="items-center space-y-4 sm:space-x-4 sm:flex sm:space-y-0">
<p class="text-dvx-white">@Messages("theme.track")</p>
<div class="overflow-x-auto relative shadow-md rounded-lg">
<table class="w-full text-left text-dvx-white border-collapse border-spacing-2 border border-slate-400">
<tbody>
@for(track <- ConferenceDescriptor.ConferenceTracksDescription.ALL) {
<tr>
<td>@Messages(track.i18nTitleProp)</td>
<td>@Messages(track.i18nDescProp)</td>
</tr>
}
@for(track <- ConferenceDescriptor.ConferenceTracksDescription.ALL) {
<tr>
<td class="border border-slate-300 py-3 px-6 bg-dvx-back">@Messages(track.i18nTitleProp)</td>
<td class="border border-slate-300 py-3 px-6">@Messages(track.i18nDescProp)</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>


<!-- ****************************************************************************** //-->

<div class="container mx-auto bg-dvx-back p-8">
<div class="flex items-center justify-between text-center">
<span class="text-sm text-dvx-orange text-center dark:text-gray-400 mt-4 sm:mt-0">© 2012-2023 Quantixx SARL - Tous droits réservés - <a href="https://www.devoxx.fr" class="hover:underline text-dvx-accent">Devoxx France</a></span>
<div class="flex text-sm mt-4 space-x-6 justify-center sm:mt-0 text-dvx-orange">
@if(SecureCFPController.isLoggedIn(req)) {
<p>Logged in as <span class="text-dvx-accent">@SecureCFPController.getCurrentUser(req).map(_.cleanName)</span></p>
<p><a href="@routes.Authentication.logout" class="btn-primary">Logout</a> and close your session</p>
} else {
<a href="@routes.Application.home()" class="btn-primary">@Messages("login")</a>
}
</div>
</div>
</div>
</body>
</html>

</div>
}

0 comments on commit 065c1c1

Please sign in to comment.