java -fullversion openjdk full version "17.0.5+1"
Installer
Prérequis
Pour commencer, vous aurez besoin des éléments suivants :
-
Java (JDK-17 or JDK-19)
-
git
En option, vous pouvez aussi installer :
-
Solr-9.6.x (Used for intranet-wide search bar)
-
Postgresql
Version de Java
Commande affichant la version:
Sur Mac, on peut utiliser brew pour l’installation du Jdk :
brew install openjdk@17
Clonez le projet Intranet clé en main
git clone https://github.com/Taack/intranet.git
Ce dépôt contient une version simplifiée d’un Intranet dans lequel vous pourrez ajouter d’autres applications. Il contient "Crew", qui est le système de gestion des utilisateurs, ainsi que sa dépendance de sécurité : Spring Security Plugin.
Lancez votre futur Intranet
Allez dans le répertoire intranet nouvellement cloné et démarrez le serveur en exécutant cette commande :
./gradlew server:bootRun
Si vous souhaitez que Gradle observe les modifications des fichiers pour recharger à chaud les modifications, lancer avec l’option -Dgrails.run.active=true
:
./gradlew -Dgrails.run.active=true server:bootRun
Après un certain temps, vous devriez voir dans la console le message suivant :
Grails application running at http://localhost:9442...
Vous pouvez maintenant accéder à l’Intranet en allant à cette adresse depuis votre navigateur.
Vous pouvez aussi vous identifier avec les identifiants par défaut (identifiant : admin, mot de passe : ChangeIt).
Le mot de passe peut être remplacé dans le fichier server/grails-app/conf/application.yml
.
Base de données persistante
Éditer le fichier server/grails-app/conf/application.yml
, la section dataSource
. Les base de données relationnelle et non relationnelle sont supportées.
Pour que les données de H2 soit persistante en mode développement :
environments:
development:
dataSource:
dbCreate: update (1)
url: jdbc:h2:./prodDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE (2)
1 | Mode de création des schémas (voir Grails GORM documentation) |
2 | prodDb : la racine du nom du fichier utilisé |
Tâche Gradle pour création de binaire Tomcat
À la place de bootRun
, utiliser la tâche assemble
:
./gradlew server:assemble
Le binaire se trouvera dans le répertoire server/build/libs
. Pour l’importer ensuite dans Tomcat :
cd server/build/libs
java -jar server-[version].jar
L’exécution sera plus rapide, les fichiers statiques seront compressés et concaténés.
Soyez sûr de ne pas avoir une instance déjà en train de fonctionner |
Configurez votre IDE
Nous recommandons fortement d’utiliser la dernière version d'IntelliJ Ultimate Edition, pour son support étendu de Groovy et Grails. Nous étudions actuellement le support d’autres IDE (Eclipse, Visual Studio Code), ainsi que le support des autres versions d’IntelliJ.
IntelliJ Ultimate Edition
Nous vous recommandons d’installer les plugins Taack pour IntelliJ que vous pouvez trouver dans le store Intellij TaackUiASTAutocomplete ou en compilant les sources ici.
Pour ouvrir le projet, sélectionnez "Open projet" et sélectionnez intranet/settings.gradle
.
Visual Studio Code
Si vous voulez vraiment utiliser Visual Studio Code, nous vous recommandons les extensions suivantes pour utiliser ce framework :
Gardez à l’esprit que la plupart des fonctionnalités de Grails et de Taack Framework ne seront pas reconnues par VSCode mais celui-ci peut toujours être utilisé. De plus, VSCode ne vous proposera pas d’aide avec les importations, la navigation dans le code ainsi que de nombreuses autres fonctionnalités pratiques puisque le support de Groovy n’est pas aussi avancé que sur IntelliJ.
Première application
Comment une application fonctionne avec Taack Framework ?
Votre projet Intranet possède deux parties :
-
Les plugins d’applications, qui sont regroupés dans le répertoire
app
: ce sont des micro-projets Gradle qui contiennent chacun leurs propres dépendances, dossier build, etc. Par exemple,Crew
est plugin d’application.
Enregistrer une application pour en savoir plus sur la façon dont les plugins d’application sont implémentés sur le serveur.
* Le serveur principal, qui va gérer tous les plugins d’applications définis dans build.gradle
et les ajouter sur la page principale de l’Intranet.
Créer une nouvelle application
Pour créer une nouvelle appliquette (un plugin Grails ou module Gradle), assurez-vous d’avoir la dernière version Github de l’Intranet (voir installation).
Ceci fait, exécuter la commande suivante :
./gradlew -DmodName=myToto server:generateTaackAppTask
Une nouvelle appliquette apparaîtra dans le répertoire app
. Pensez à recharger Gradle pour détecter sa présence dans Intellij.
Mot sur la maintenance
La plupart du temps, mettre à jour votre Intranet ne devrait impliquer que de mettre à jour le répertoire buildSrc
, et le fichier gradle.properties
.
Ne soyez pas effrayé par ce genre de procedure. Il n’y a pas vraiment de méthode parfaite. |
Créer un menu
Avant toute chose, penchons-nous sur la navigation de votre nouvelle application. La première chose à faire est de définir comment le menu va être construit. Nous pouvons commencer à partir du modèle de base suivant :
static private UiMenuSpecifier buildMenu(String q = null) {
new UiMenuSpecifier().ui {
menu SomeController.&action as MC
menu this.&anotherAction as MC
// import org.codehaus.groovy.runtime.MethodClosure as MC
}
}
Nous créons tout d’abord un objet UiMenuSpecifier, puis nous définissons le contenu du menu :
menu TurboController.&action as MC
Ici, menu
crée un simple lien dans notre bar de navigation. 'Action'
est le nom du lien affiché et TurboController.&action as MethodClosure
définie l’action vers laquelle le lien va rediriger.
Vous pouvez consulter la liste complète des éléments que vous pouvez ajouter dans votre menu ici : Menu DSL.
Créer un tableau
Maintenant, affichons un tableau dans votre page index. Commençons avec ce modèle de base :
UiTableSpecifier tableSpecifier = new UiTableSpecifier()
tableSpecifier.ui Book, {
//Add table content inside the closure here
}
Ici, nous avons défini un nouveau tableau qui va lister des instances de Book. Nous pouvons ensuite définir l’en-tête du tableau en ajoutant dans la closure le code suivant :
UiTableSpecifier tableSpecifier = new UiTableSpecifier()
tableSpecifier.ui {
// -- Header --
header {
column {
fieldHeader object.title_
}
}
}
Puisque nous avons défini notre tableau dans une closure, nous pouvons ajouter des conditions, des boucles, etc.
Ajoutons maintenant une colonne qui va être affichée uniquement si l’utilisateur possède le rôle ROLE_ADMIN
:
// Look if the current user has the Role "ROLE_ADMIN"
User cu = springSecurityService.currentUser as User
boolean isAdmin = cu.authorities*.authority.contains("ROLE_ADMIN")
new UiTableSpecifier().ui {
header {
column {
label object.title_
}
// Column only shown to admin
if (isAdmin) {
column {
label "Delete book"
}
}
}
}
La colonne avec l’en-tête "Delete book" sera affichée seulement si l’utilisateur courant est un admin.
Maintenant, nous allons remplir notre tableau. Nous allons lister toutes les instances de Book dans la base de données en utilisant l’instruction iterate
du DSL des tables.
User cu = springSecurityService.currentUser as User
boolean isAdmin = cu.authorities*.authority.contains("ROLE_ADMIN")
new UiTableSpecifier().ui {
header {
column {
label object.title_
}
// Column only shown to admin
if (isAdmin) {
column {
label "Delete book"
}
}
}
iterate(taackFilterService.getBuilder(Book)
.setMaxNumberOfLine(8)
.setSortOrder(TaackFilter.Order.DESC, object.title_)
.build()) { Book book ->
rowColumn {
rowField book.title_ //The underscore is needed here
}
// If the user is an admin display a column with a button link
// to redirect towards the book deletion action
if (isAdmin) {
rowColumn {
rowAction ActionIcon.DELETE,
this.&deleteBook as MC, book.id
}
}
}
}
Pour chaque livre dans notre liste, nous créons une nouvelle ligne avec son titre dans la première colonne et un bouton "supprimer" dans la seconde colonne si l’utilisateur est un admin (pour le moment, nous sommes redirigés vers index
puisque nous n’avons pas encore créé de méthode de suppression).
Votre tableau est désormais complet. Nous devons maintenant simplement l’afficher sur la page.
Pour afficher les UiSpecifiers que nous avons précédemment construits, nous devons utiliser taackUiService
. Il devrait être déjà importé dans le contrôleur créé par la commande create-taack-app
.
Ajoutez le code suivant sous le code de votre tableau :
taackUiService.show(new UiBlockSpecifier().ui {
table tableSpecifier
}, buildMenu())
taackUiService.show(UiBlockSpecifier block, UiMenuSpecifier menu)
sera en charge d’afficher la spécification que nous lui avons donnée. Dans ce cas, nous voulons afficher un ajaxBlock
qui contient une table
nommée "Book table". Nous passons notre tableSpecifier
précédemment créé en tant qu’argument et nous réglons la largeur du tableau à MAX
afin qu’il occupe toute la largeur de la page.
Nous utilisons également notre méthode statique buildMenu()
créée auparavant, et nous la passons en tant que second argument de show()
pour afficher notre menu avec la page.
Vous pouvez maintenant lancer le serveur et accéder à votre nouvelle application. Votre tableau devrait fonctionner, mais pour le moment, vous ne devriez voir que les en-têtes, car vous n’avez pas encore de livres dans votre base de données. Continuons donc avec la création du formulaire et la sauvegarde de l’objet dans la base de données.
Ajouter des boutons dans le tableau
Nous allons ajouter un bouton dans notre tableau Book qui va ouvrir un modal en ajax pour créer un nouveau livre. Pour cela, nous devons ajouter une closure dans le tableau comme ceci :
taackUiService.show(new UiBlockSpecifier().ui {
table 'Book table', tableSpecifier, BlockSpec.Width.MAX, {
//Added Closure here
if (isAdmin())
action ActionIcon.CREATE, this.&bookForm as MC
}
}, buildMenu())
Maintenant un admin pourra voir un bouton "Créer" en haut à droite du tableau.
La méthode action
est composée des paramètres suivants :
-
L’icône du bouton ;
-
L’action vers laquelle le bouton va rediriger ;
-
Le libellé sera composé et traduit en utilisant le nom de l’action.
Créer un formulaire et sauvegarder des objets
Nous allons maintenant créer le formulaire qui sera utilisé à la fois pour la création et la mise à jour des livres. Pour gérer les deux cas, nous allons d’abord définir notre action bookForm
et ensuite initialiser soit un nouveau livre, soit regarder si l’identifiant d’une instance de livre a été passé en paramètre de la requête.
def bookForm(Book book) {
book ?= new Book(params)
}
Maintenant, nous allons créer un FormSpecifier
pour définir notre formulaire et son contenu :
UiFormSpecifier form = new UiFormSpecifier()
form.ui book, {
//Section of fields
section "Book details", {
field book.title_
field book.author_
}
//Save button
formAction this.&saveBook as MC
}
Maintenant que votre formulaire est défini, affichons-le en utilisant taackUiService.show()
.
UiBlockSpecifier b = new UiBlockSpecifier()
b.ui {
modal {
form form, BlockSpec.Width.MAX
}
}
taackUiService.show(b)
Cette fois, nous n’allons pas spécifier buildMenu
dans notre show, car nous ne voulons pas que le menu soit affiché dans le modal !
N’oubliez pas de créer l’action saveBook
:
@Secured("ROLE_ADMIN")
@Transactional
def saveBook(String redirectAction) {
taackSaveService.saveThenReloadOrRenderErrors(Book)
}
Puisque nous voulons autoriser seulement les administrateurs à créer des livres, l’annotation @Secured
a été ajoutée au niveau de la méthode saveBook. Pour plus d’informations, nous vous invitons à consulter le chapitre détaillé sur les annotations de sécurité : grails-spring-security-core.
Afficher un objet
Maintenant que nous pouvons créer des livres et les lister dans un tableau, affichons leurs détails dans un modal.
Encore une fois, nous allons définir le Specifier et l’afficher dans un bloc via taackUiService.show()
:
def showUser(Book book) {
// Define the show displayed fields
UiShowSpecifier showSpec = new UiShowSpecifier().ui(book, {
fieldLabeled book.title_
fieldLabeled book.author_
})
taackUiService.show(new UiBlockSpecifier().ui {
modal {
show showSpec
}
})
}
Nous devons également ajouter un lien vers cette page dans le tableau. Pour ajouter un lien dans le tableau, ajoutez la ligne suivante dans la même rowColumn (sous le champ title du livre par exemple) que celle où vous voulez que le bouton apparaisse :
rowAction
ActionIcon.SHOW * StyleModifier.SCALE_DOWN, (1)
TurboController.&showBook as MC, book.id
1 | Cela créera un petit bouton dans la cellule du tableau qui ouvrira un modal avec les détails du livre correspondant. |
Notez qu’ici, ActionIcon
a été multiplié avec un IconStyle
pour modifier la taille de l’icône.
Supprimer un objet
Vous souvenez-vous du bouton de suppression que nous avons placé dans notre tableau ? Nous allons maintenant le faire fonctionner. Pour cela, remplacez le nom de l’action dans le tableau par "&deleteBook
", puis créez une nouvelle action avec le même nom dans le contrôleur :
@Transactional
@Secured(['ROLE_ADMIN'])
def deleteBook(Book book) {
book.delete()
redirect action: 'index'
}
C’est tout ! Nous utilisons la méthode delete
pour supprimer le livre de la base de données, puis on redirige vers l’action index
afin de revenir au tableau.
Vous disposez maintenant d’un CRUD entièrement fonctionnel pour votre classe Book sans avoir touché aux fichiers HTML/GSP !
Vous êtes maintenant prêt à vous plonger dans les fonctionnalités plus complexes de Taack Ui Framework.
Bienvenue !