Compare commits

..

No commits in common. "main" and "1.1.0" have entirely different histories.
main ... 1.1.0

33 changed files with 2342 additions and 2677 deletions

View file

@ -19,15 +19,7 @@
"**/vendor/*.sass",
"**/vendor/**/*.sass",
"**/vendor/*.less",
"**/vendor/**/*.less",
"**/node_modules/*.css",
"**/node_modules/**/*.css",
"**/node_modules/*.scss",
"**/node_modules/**/*.scss",
"**/node_modules/*.sass",
"**/node_modules/**/*.sass",
"**/node_modules/*.less",
"**/node_modules/**/*.less"
"**/vendor/**/*.less"
],
"customSyntax": "postcss-scss",
"rules": {
@ -37,6 +29,8 @@
"order/properties-alphabetical-order": null,
"max-nesting-depth": 5,
"selector-max-compound-selectors": 5,
"declaration-colon-newline-after": null,
"value-list-comma-newline-after": null,
"scss/double-slash-comment-empty-line-before": [
"always",
{

View file

@ -1,5 +1,4 @@
{
"peacock.remoteColor": "#1fee8e",
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#4ef2a6",
"activityBar.background": "#4ef2a6",
@ -18,5 +17,6 @@
"titleBar.activeForeground": "#15202b",
"titleBar.inactiveBackground": "#1fee8e99",
"titleBar.inactiveForeground": "#15202b99"
}
},
"peacock.remoteColor": "#1fee8e"
}

View file

@ -1,5 +0,0 @@
install:
docker run --rm -v ${PWD}:/project electronuserland/builder:wine npm install
build:
docker run --rm -v ${PWD}:/project electronuserland/builder:wine npm run build

103
README.md
View file

@ -1,103 +1,8 @@
# Showroom - App Expo
Update : 25-09-2025
## Prerequisites
### Binaries
- Node & NPM
- Wine & Wine32
#### Wine
```bash
sudo dpkg --add-architecture i386 # Allow Win32 arch for packaging
sudo apt-get update
sudo apt-get install wine wine32
```
In Ubuntu, if you get an error for : libgphoto2-6t64:i386 related to libgd3:i386
```bash
sudo nano /etc/apt/preferences.d/99-libgd3-ubuntu.pref
```
Add :
```text
Package: libgd3
Pin: release o=Ubuntu
Pin-Priority: 1001
Package: libgd3:i386
Pin: release o=Ubuntu
Pin-Priority: 1001
Package: libgphoto2-6
Pin: release o=Ubuntu
Pin-Priority: 1001
Package: libgphoto2-6:i386
Pin: release o=Ubuntu
Pin-Priority: 1001
```
Then :
```bash
sudo apt update
sudo apt dist-upgrade
rm -rf ~/.wine
```
### Datas
Put .zip export from backend and put it in :
```bash
./static/data
```
ex:
```bash
ls static/data
```
return :
```bash
showroom-bo-export_25-09-2025_10-15-05.zip
```
/!\ You can have multiple .zip files, program always get the last one for building.
## Production
### Docker way
```bash
make install
make build
```
### Host way
```bash
npm run build
```
Last command give you an .exe in folder below :
```bash
release/
```
For example :
```bash
ls release/2.3.3
```
Should return :
```bash
'App UWIL Expo_2.3.3.exe' builder-debug.yml builder-effective-config.yaml win-unpacked
```
'App UWIL Expo_2.3.3.exe' is the production deliverable.
## Development
### Nuxt 3 Minimal Starter
# Nuxt 3 Minimal Starter
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
### Setup
## Setup
Make sure to install the dependencies:
@ -115,7 +20,7 @@ yarn install
bun install
```
### Development Server
## Development Server
Start the development server on `http://localhost:3000`:
@ -133,7 +38,7 @@ yarn dev
bun run dev
```
### Production
## Production
Build the application for production:

23
app.vue
View file

@ -11,7 +11,7 @@
>
<template v-if="!loading">
<AppHeader :active-brand="activeBrand" :active-range="activeRange" />
<div class="container-fluid overflow-auto p-0">
<div class="container-fluid overflow-y-scroll p-0">
<NuxtPage :page-key="(route: RouteLocation) => route.fullPath" />
</div>
<NavigationMenu v-if="showNavigation" />
@ -86,7 +86,6 @@ export default defineComponent({
this.loading = false;
this.setTimeout();
dataJson.fonts.forEach(font => this.injectFontFace(font.font_name, font.font));
this.redirectIfOneBrand(dataJson.items);
});
},
mounted() {
@ -104,9 +103,6 @@ export default defineComponent({
t(text: string, params: Record<string,string> = {}, localeToUse: string|null = null): string {
return ToolboxHelper.trans(text, params, localeToUse);
},
transField(model: Typei18nModel, field: Typei18nFieldList) {
return ToolboxHelper.getTranslatableField(model, field);
},
injectFontFace(fontName: string, fontPath: string|null) {
const newStyle = document.createElement("style");
if(fontPath) {
@ -117,18 +113,7 @@ export default defineComponent({
}
document.head.appendChild(newStyle);
},
/** Redirect to ranges.index if there is only one brand. */
redirectIfOneBrand(brands: Array<TypeBrand>): void {
if (brands.length === 1) {
useAppStore().setActiveBrand(brands[0]);
this.activeBrand = brands[0];
navigateTo(useLocaleRoute()({"name": "brands-slug", "params": {"slug": this.transField(brands[0], "slug")}}));
} else {
useAppStore().setActiveBrand(null);
this.activeBrand = null;
}
},
/** Prolong le timer pour revenir au home screen. */
/** Prolong le timer pour revenir au home screen */
setTimeout(): void {
if(this.timeout) {
clearTimeout(this.timeout);
@ -136,9 +121,7 @@ export default defineComponent({
this.$nextTick(() => {
this.timeout = setTimeout(() => {
useAppStore().setActiveRange(null);
window.ipcRendererObject.getJsonData().then((dataJson) => {
this.redirectIfOneBrand(dataJson.items);
});
useAppStore().setActiveBrand(null);
navigateTo(useLocaleRoute()({"name": "index"}));
}, useAppStore().getSettings().home_timeout * 1000);
});

View file

@ -11,8 +11,8 @@ $color-secondary: #6c757d;
// * FONTS
$font-default-family-base: system-ui, -apple-system, "Segoe UI", "Roboto",
"Helvetica Neue", "Arial", "Noto Sans", "Liberation Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; // - The default site font family.
"Helvetica Neue", "Arial", "Noto Sans", "Liberation Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; // - The default site font family.
// Display tres haute résolution, augmentation de font size 1rem => 1.8rem
$font-default-size-base: 1.4rem; // Assumes the browser default, typically `16px`
$line-default-height-base: 1.5;
@ -27,4 +27,4 @@ $container-max-widths: (
lg: 960px,
xl: 1140px,
xxl: 1520px
);
);

View file

@ -1,7 +1,7 @@
body {
@include font-size(1rem);
max-height: 100vh;
min-height: 100vh;
// * Use BS var to set BG as on home page
// background-color: unset;
@ -49,8 +49,7 @@ body {
@include font-size(4rem);
}
&::before,
&::after {
&::before,&::after {
position: absolute;
top: 50%;
display: inline-block;

View file

@ -3,6 +3,7 @@
@import "./sweetalert-custom";
@import 'animate.css';
// * App
@import "./layout";

View file

@ -1,9 +1,9 @@
<template>
<div class="container border-top border-3 border-secondary">
<div class="container">
<div class="row py-4">
<div class="col arrow pe-3 d-flex align-items-center justify-content-end">
<button
class="rounded-pill btn btn-secondary px-4 py-1"
class="rounded-pill btn btn-primary px-4 py-1"
:disabled="previousRange === null"
:title="previousRange ? t('view_range_products', {'range_name': transField(previousRange, 'name')}) : ''"
data-bs-toggle="tooltip"
@ -14,7 +14,7 @@
</div>
<div class="col home text-center px-3">
<button
class="rounded-pill btn btn-secondary px-4 py-1"
class="rounded-pill btn btn-primary px-4 py-1"
:title="activeBrand ? t('view_brand_ranges', {'brand_name': transField(activeBrand, 'name')}) : ''"
data-bs-toggle="tooltip"
@click="gotoBrand(activeBrand)"
@ -24,7 +24,7 @@
</div>
<div class="col arrow ps-3 d-flex align-items-center justify-content-start">
<button
class="rounded-pill btn btn-secondary px-4 py-1"
class="rounded-pill btn btn-primary px-4 py-1"
:disabled="nextRange === null"
:title="nextRange ? t('view_range_products', {'range_name': transField(nextRange, 'name')}) : ''"
data-bs-toggle="tooltip"

View file

@ -1,6 +1,6 @@
<template>
<div id="product-modal" ref="modal" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl modal-fullscreen-md-down">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xxl modal-fullscreen-md-down">
<div class="modal-content bg-white">
<div class="modal-header position-relative">
<h5

View file

@ -4,7 +4,10 @@
<div
v-for="(productPair, productIndex) of chunkInefficient(range.products, 2)"
:key="productIndex"
:class="{'row justify-content-center': true}"
:class="{
'row justify-content-center': true,
'shelf': displayShelves
}"
>
<div
v-for="(product, productPairIndex) of productPair"
@ -93,13 +96,20 @@ export default defineComponent({
},
data(): {
route: RouteLocationNormalizedLoaded;
displayShelves: boolean;
tooltips: Tooltips|null;
} {
return {
route: useRoute(),
displayShelves: this.range.shelf,
tooltips: null
};
},
watch: {
range() {
this.displayShelves = this.range.shelf;
}
},
mounted() {
this.$nextTick(() => {this.tooltips = Tooltips.make({type:"parent", parentSelector: "#product-list-component"});});
this.$nextTick(this.applySameHeight);

View file

@ -1,15 +1,11 @@
<template>
<footer
v-if="brands.length > 1 || versions.isDebug"
id="footer"
ref="footer"
class="container-fluid flex-grow-0"
:style="`background-color: ${activeRange && brandWithMultipleRanges ? activeRange.color : activeBrand?.color} !important`"
>
<div
v-if="brands.length > 1"
class="row"
>
<div class="row">
<div class="col-12 col-md-4 d-flex justify-content-center align-items-center">
<span
class="fw-bold d-block px-5"
@ -39,10 +35,10 @@
},
}"
>
<SwiperSlide v-for="(brand, brandIndex) of brands" :key="brandIndex">
<SwiperSlide v-for="(brand,brandIndex) of brands" :key="brandIndex">
<NuxtLinkLocale
class="swiper-slide"
:to="`/brands/${transField(brand, 'slug')}`"
:to="`/brands/${brand.slug}`"
data-bs-toggle="tooltip"
:title="t('view_brand_ranges', {'brand_name': transField(brand, 'name')})"
@click.prevent="gotoBrand(brand)"
@ -170,6 +166,7 @@ export default defineComponent({
return ToolboxHelper.getContrastYIQ(hexcolor);
},
gotoBrand(brand: TypeBrand) {
useAppStore().setActiveBrand(null);
useAppStore().setActiveRange(null);
useAppStore().setActiveBrand(brand);
navigateTo(useLocaleRoute()({"name": "brands-slug", "params": {"slug": this.transField(brand, "slug")}}));

View file

@ -14,14 +14,14 @@
'mx-auto': !activeRange,
}"
>
<button
<NuxtLinkLocale
:to="`/brands/${transField(activeBrand, 'slug')}`"
:class="{
'd-inline-block py-3 px-2 text-center bg-transparent border-0': true,
'd-inline-block py-3 px-2 text-center': true,
'flex-grow-1': !activeRange
}"
data-bs-toggle="tooltip"
:title="t('view_brand_ranges', {'brand_name': transField(activeBrand, 'name')})"
@click="goToBrand(activeBrand)"
>
<img
class="img-fluid main-logo"
@ -30,7 +30,7 @@
:title="t('brands_logo', {'brand_name': transField(activeBrand, 'name')})"
data-bs-toggle="tooltip"
>
</button>
</NuxtLinkLocale>
<div v-if="activeRange && brandWithMultipleRanges" class="flex-grow-1 text-center">
<span
:class="{...{
@ -76,22 +76,21 @@
</button>
<div id="navbar-menu" class="lang-bar navbar-collapse collapse flex-grow-0">
<div class="btn-group z-1">
<div class="btn-group me-4 z-1">
<button
v-for="(localeObject, localeIndex) of locales"
v-for="(localeObject,localeIndex) of locales"
:key="localeIndex"
:class="{
'btn ms-3 px-4 mx-0 shadow fw-bold': true,
'btn-secondary': locale === localeObject.iso,
'btn px-4 mx-3 shadow fw-bold': true,
'btn-white bg-white': locale !== localeObject.iso,
'btn-secondary': locale === localeObject.iso,
}"
:title="localeObject.label"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
@click.prevent="switchLocale(localeObject)"
>
<span class="text-uppercase fs-5">{{ localeObject.flag }}</span>
<span :class="`fi fi-${localeObject.flag}`" />
<span class="text-uppercase fs-1">{{ localeObject.flag }}</span>
<!-- <span :class="`fi fi-${localeObject.flag}`" /> -->
</button>
</div>
</div>
@ -167,10 +166,7 @@ export default defineComponent({
this.settings = useAppStore().data.settings();
const { locale, availableLocales } = useI18n({ useScope: "global"});
this.locale = locale.value;
let localeSortArr = [] as Array<string>;
window.ipcRendererObject.getJsonData().then((dataJson) => {
localeSortArr = dataJson.settings.locales;
});
const localeSortArr = ["fr", "nl"];
this.locales = availableLocales.sort((LocA, LocB) => localeSortArr.indexOf(LocA) - localeSortArr.indexOf(LocB)).map(localeStr => {
return {
iso: localeStr,
@ -212,13 +208,6 @@ export default defineComponent({
toRGBA(hexcolor: string, alpha: number = 1): string {
return ToolboxHelper.toRGBA(hexcolor, alpha);
},
goToBrand(activeBrand: TypeBrand): void {
if(!activeBrand) {
return;
}
useAppStore().setActiveRange(null);
navigateTo(useLocaleRoute()({"name": "brands-slug", "params": {"slug": activeBrand.slug[this.locale]}}));
}
}
});
</script>
@ -259,9 +248,7 @@ export default defineComponent({
.main-logo {
@include rfs(7rem, max-height);
& {
height: 20vh;
}
height: 20vh;
@include media-breakpoint-up(md) {
@include rfs(15rem, max-height);
}
@ -279,19 +266,11 @@ export default defineComponent({
@include rfs(5em, width);
}
}
.lang-bar {
position: absolute;
right: 1rem;
top: 0;
}
.lang-bar .btn-group {
border-radius: 0;
}
.lang-bar .btn-group button {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 1rem;
border-bottom-right-radius: 1rem;
right: 0;
top: 5rem;
}
}
</style>

View file

@ -3,7 +3,7 @@
*/
{
appId: "com.ldc.app-kiosk",
productName: "App UWIL Expo",
productName: "App Kiosk",
asar: false,
directories: {
output: "release/${version}",
@ -12,18 +12,18 @@
mac: {
artifactName: "${productName}_${version}.${ext}",
target: ["dmg"],
icon: "uwil-expo-icon.png",
icon: "ldc-intl.png",
},
win: {
target: [
{
target: "portable",
target: "nsis",
arch: ["x64"],
},
],
artifactName: "${productName}_${version}.${ext}",
icon: "uwil-expo-icon.png",
publisherName: "LDC DIGITAL Groupe",
icon: "ldc-intl.png",
publisherName: "LDC Service Web",
},
linux: {
category: "Utility",

View file

@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "path";
import AdmZip from "adm-zip";
import { Ajv } from "ajv";
import Ajv from "ajv";
import addFormats from "ajv-formats";
import log from "electron-log/main";
@ -48,18 +48,13 @@ export default abstract class UnzipData {
const zip = new AdmZip(fs.readFileSync(UnzipData.zipFileToUse));
UnzipData.removeOldExtractedFiles();
zip.extractAllTo(publicPath + "/data");
// * Schemas Copy for production build
if (!isDev) {
fs.cpSync(path.join(root, "public/schemas"), path.join(publicPath, "schemas"), { recursive: true });
}
zip.extractAllTo("public/data");
}
private static removeOldExtractedFiles() {
public static removeOldExtractedFiles() {
// * Clear export dir
fs.rmSync(publicPath + "/data/pictures", { recursive: true, force: true });
fs.rmSync(publicPath + "/data/data.json", { recursive: true, force: true });
fs.rmSync("public/data/pictures", { recursive: true, force: true });
fs.rmSync("public/data/data.json", { recursive: true, force: true });
}
/**

View file

@ -71,14 +71,13 @@ app.whenReady().then(() => {
// width: 1280,
// height: 900,
center: true,
kiosk: process.env.NODE_ENV !== "development",
kiosk: true,
closable: false,
alwaysOnTop: true,
fullscreen: process.env.NODE_ENV !== "development",
fullscreen: true,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
devTools: process.env.NODE_ENV === "development",
preload: path.join(__dirname, "preload.js")
}
});

4
electron/renderer.ts Normal file
View file

@ -0,0 +1,4 @@
// console.log("versions.chrome()");
// console.log(app.chrome());

View file

@ -1,18 +1,14 @@
export default defineI18nConfig(async () => {
const dataJson = await window.ipcRendererObject.getJsonData();
const localeCodes = dataJson.settings.locales;
// import en from "./locales/en";
import fr from "./locales/fr";
import nl from "./locales/nl";
const messages: Record<string, any> = {};
for (const locale of localeCodes) {
messages[locale] = (await import(`./locales/${locale}.ts`)).default;
export default defineI18nConfig(() => ({
legacy: false,
globalInjection: true,
locale: "nl",
fallbackLocale: "fr",
messages: {
fr,
nl
}
return {
legacy: false,
globalInjection: true,
locale: "fr",
fallbackLocale: "fr",
messages,
};
});
}));

10
index.d.ts vendored
View file

@ -1,12 +1,14 @@
export { };
import type { RouteLocation as NRouteLocation } from "vue-router";
import type { ipcRendererObject, versions } from "./electron/preload";
import type { RouteLocation as NRouteLocation } from "vue-router";
import type { ipcRendererObject, versions } from "./electron/preload";
// * --- MODELS From JSON Schema
type Locale = string;
type i18nFieldList = "name" | "slug" | "description" | "sub_title" | "footer_phrase";
type i18nFieldList =
"name" | "slug" | "description" |
"sub_title" | "footer_phrase";
type i18nField = Record<string, string>;
type i18nModel = SettingsModel | BrandModel | RangeModel | ProductModel;
@ -21,8 +23,6 @@ type AppModel = {
/** Settings from Showroom Bo */
type SettingsModel = {
/** Langues disponibles dans l'application */
locales: Array<string>
/** Sous-titre de l'application */
sub_title: i18nField;
/** Texte en bas de page */

BIN
ldc-intl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View file

@ -1,19 +0,0 @@
export default {
"_flag": "de",
"_lang": "Deutsch",
"error_occured": "Ein Fehler ist aufgetreten.",
"loading": "Laden",
"show_hide_languages": "Sprachen anzeigen/ausblenden",
"view_brand_ranges": "Sortimente der Marke {brand_name} anzeigen",
"brands_logo": "Logo für die Marke {brand_name}",
"no_brands_available": "Keine Marken verfügbar",
"view_range_products": "Produkte der Reihe {range_name} anzeigen",
"ranges_logo": "Logo für die Produktreihe {range_name}",
"no_ranges_available": "Keine Bereiche verfügbar",
"more_about_this_product": "Mehr über dieses Produkt",
"close_products_modal": "Produktbeschreibung schließen",
"products_logo": "Logo für das Produkt {product_name}",
"no_products_available": "Keine Produkte verfügbar",
"welcome_to_ldc": "Willkommen bei LDC",
"discover_our_brands": "Entdecken Sie unsere Marken"
};

View file

@ -1,19 +0,0 @@
export default {
"_flag": "es",
"_lang": "Español",
"error_occured": "Se ha producido un error",
"loading": "Loading",
"show_hide_languages": "Mostrar / Ocultar idiomas",
"view_brand_ranges": "Ver las gamas de la marca {brand_name}",
"brands_logo": "Logotipo de la marca {brand_name}",
"no_brands_available": "No hay marcas disponibles",
"view_range_products": "Ver los productos de la gama {range_name}",
"ranges_logo": "Logotipo de la gama {range_name}",
"no_ranges_available": "No hay gamas disponibles",
"more_about_this_product": "Más información sobre este producto",
"close_products_modal": "Cerrar descripción de productos",
"products_logo": "Logotipo del producto {product_name}",
"no_products_available": "No hay productos disponibles",
"welcome_to_ldc": "bienvenido a LDC",
"discover_our_brands": "Descubra nuestras marcas"
};

View file

@ -1,8 +1,6 @@
import { resolve } from "path";
import log from "electron-log/main";
import UnzipData from "./electron/UnzipData";
UnzipData.loadZipFileContent();
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
@ -11,7 +9,7 @@ export default defineNuxtConfig({
if (["typecheck", "postinstall"].filter(action => action === process.env.npm_lifecycle_event).length) {
return;
}
log.info("Typecheck and lint OK");
UnzipData.loadZipFileContent();
}
},
experimental: {
@ -47,7 +45,7 @@ export default defineNuxtConfig({
pageTransition: { name: "page", mode: "out-in" },
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: "UWIL Expo by LDC",
title: "showroom",
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
@ -60,6 +58,7 @@ export default defineNuxtConfig({
}
},
},
plugins: [
{ src: "~/plugins/toolboxhelper.ts", mode: "client" },
{ src: "~/plugins/boostrap.ts", mode: "client" },
@ -67,13 +66,15 @@ export default defineNuxtConfig({
{ src: "~/plugins/localStorage.ts", mode: "client" },
{ src: "~/plugins/emitter.ts", mode: "client" },
],
alias: {
// images: resolve(__dirname, "./static/assets/images"),
data: resolve(__dirname, "./static/data"),
pinia: "/node_modules/@pinia/nuxt/node_modules/pinia/dist/pinia.mjs"
},
i18n: {
locales: UnzipData.loadJsonDataFile()?.settings.locales,
locales: ["fr", "nl"],
defaultLocale: "fr",
// * Ajouter aussi la locale dans ce fichier
vueI18n: "./i18n.config.ts"

4229
package-lock.json generated Executable file → Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
{
"author": {
"name": "LDC DIGITAL Groupe",
"email": "digital@ldc.fr"
"name": "LDC Service Web",
"email": "equipe.web@ldc.fr"
},
"description": "UWIL Expo",
"version": "2.3.3",
"name": "uwil-expo",
"description": "Application Kiosk",
"version": "1.1.0",
"name": "app-kiosk",
"private": true,
"type": "commonjs",
"main": "dist-electron/main.js",
@ -14,8 +14,8 @@
"static/**/*"
],
"scripts": {
"build": "nuxi build --prerender && electron-builder -w",
"dev": "cross-env NODE_ENV=development nuxt dev",
"build": "nuxi build --prerender && electron-builder",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"cleanup": "nuxt cleanup",
@ -24,68 +24,66 @@
"lint:ts": "npm run typecheck",
"lint:js": "eslint --ext \".js,.ts,.vue\" --ignore-path .gitignore .",
"lint:style": "node ./node_modules/.bin/stylelint --config './.stylelintrc.json' --max-warnings 0 \"assets/**/*.{css,scss,sass,html,vue}\" --ignore-path .gitignore",
"lint": "npm run lint:js && npm run lint:style && npm run lint:ts",
"lint": "npm run lint:js && npm run lint:style && lint:ts",
"lint:fix": "npm run lint:js --fix && npm run lint:style --fix",
"validate": "npm-run-all --parallel lint:js lint:style lint:ts",
"prepare": "husky"
"prepare": "husky install"
},
"devDependencies": {
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-regular-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/vue-fontawesome": "^3.0.8",
"@nuxt/devtools": "^1.3.9",
"@nuxtjs/eslint-config-typescript": "^12.1.0",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.5",
"@nuxt/devtools": "^1.0.0-beta.1",
"@nuxtjs/eslint-config-typescript": "latest",
"@nuxtjs/i18n": "^8.0.0",
"@pinia/nuxt": "^0.5.1",
"@popperjs/core": "^2.11.8",
"@types/adm-zip": "^0.5.7",
"@types/adm-zip": "^0.5.5",
"@types/bootstrap": "^5.2.10",
"@types/konami-code-js": "^0.8.3",
"@types/dompurify": "^3.0.3",
"@types/konami-code-js": "^0.8.1",
"@vue/eslint-config-typescript": "^12.0.0",
"adm-zip": "^0.5.16",
"ajv": "^8.17.1",
"adm-zip": "^0.5.10",
"ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"animate.css": "^4.1.1",
"bootstrap": "^5.3.7",
"cross-env": "^10.0.0",
"dompurify": "^3.2.6",
"bootstrap": "^5.3.2",
"dompurify": "^3.0.6",
"electron": "^28.1.1",
"electron-builder": "^24.9.1",
"electron-log": "^5.0.3",
"electron-serve": "^1.2.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-nuxt": "^4.0.0",
"eslint": "latest",
"eslint-config-prettier": "latest",
"eslint-plugin-nuxt": "latest",
"eslint-plugin-vue": "^9.17.0",
"flag-icons": "^7.5.0",
"husky": "^9.1.7",
"flag-icons": "^7.1.0",
"husky": "^8.0.3",
"jest": "^29.7.0",
"konami-code-js": "^0.8.3",
"konami-code-js": "^0.8.1",
"mitt": "^3.0.1",
"npm-run-all": "^4.1.5",
"nuxt": "^3.7.4",
"nuxt-electron": "^0.7.0",
"pinia": "^3.0.3",
"postcss": "^8.4.31",
"postcss-html": "^1.5.0",
"postcss-import": "^16.0.0",
"postcss-url": "^10.1.3",
"prettier": "^3.2.4",
"sass": "^1.70.0",
"prettier": "latest",
"sass": "latest",
"stylelint": "^15.11.0",
"stylelint-config-idiomatic-order": "github:ream88/stylelint-config-idiomatic-order",
"stylelint-config-sass-guidelines": "^10.0.0",
"stylelint-config-standard-scss": "^11.1.0",
"stylelint-scss": "^5.3.2",
"sweetalert2": "^11.22.1",
"swiper": "^11.2.8",
"sweetalert2": "^11.7.32",
"swiper": "^11.0.5",
"typescript": ">=4.3.5 <5.3.0",
"vite": "^4.4.11",
"vite-plugin-electron": "^0.15.5",
"vite-plugin-electron-renderer": "^0.14.5",
"vue": "^3.5.17",
"vue-router": "^4.5.1",
"vue-tsc": "^2.2.10"
"vue": "^3.3.4",
"vue-router": "^4.2.5"
}
}

View file

@ -5,7 +5,11 @@
<div
v-for="(rangePair, rangePairIndex) of chunkInefficientCustom(brand.ranges, 2)"
:key="rangePairIndex"
:class="{'row justify-content-center mt-5 pt-5 mb-5 pb-5': true}"
:class="{
'row justify-content-center mt-5 pt-5': true,
'mb-5 pb-5': !displayShelves,
'shelf': displayShelves
}"
>
<div
v-for="(range, rangeIndex) of rangePair"
@ -77,6 +81,7 @@ export default defineComponent({
animateTimeout: NodeJS.Timeout|undefined;
animateIndex: number|null;
animations: Array<string>;
displayShelves: boolean;
tooltips: Tooltips|null;
} {
return {
@ -86,6 +91,7 @@ export default defineComponent({
animateTimeout: undefined,
animateIndex: null,
animations: ["heartBeat", "tada", "shakeX", "rubberBand"],
displayShelves: false,
tooltips: null
};
},
@ -99,6 +105,7 @@ export default defineComponent({
return ;
}
this.brand = brand;
this.displayShelves = this.brand.shelf;
const firstRange = this.brand.ranges.at(0);
@ -132,32 +139,21 @@ export default defineComponent({
chunkInefficientCustom(ranges: Array<TypeRange>, chunkSize: number):Array<Array<TypeRange>> {
const out: Array<Array<TypeRange>> = [];
let row: Array<TypeRange> = [];
ranges
.sort((a, b) => a.order - b.order)
.forEach((range, _i) => {
// Handle special width=2 case immediately
if (range.width === 2) {
if (row.length > 0) {
out.push(row);
row = [];
}
out.push([range]);
return;
}
// Add to current row
row.push(range);
// Push row if it reaches chunk size
if (row.length === chunkSize) {
ranges.forEach((range: TypeRange, i: number) => {
if (range.width === 2) {
if(row.length) {
out.push(row);
row = [];
}
});
// Push any remaining elements
if (row.length > 0) {
out.push(row);
}
out.push([range]);
return;
}
row.push(range);
if (i % chunkSize) {
out.push(row);
row = [];
}
});
return out;
},
t(text: string, params: Record<string,string> = {}, localeToUse: string|null = null): string {

View file

@ -1,7 +1,7 @@
<template>
<div :class="{'page-home d-flex': true, 'text-bg-light': multipleBrands}">
<div class="page-home d-flex text-bg-light">
<div class="container-fluid justify-content-center d-flex flex-column">
<div v-if="multipleBrands" class="row">
<div class="row">
<div class="col-12 text-center overflow-hidden pb-5">
<div class="home-title">
{{ t('welcome_to_ldc') }}
@ -22,22 +22,24 @@
</video>
</div>
</div>
<div v-if="appState.brands" class="row h-100 align-items-center">
<div v-if="appState.brands" class="row">
<div class="col-12 text-center overflow-hidden pb-5">
<div class="home-title">
{{ t('discover_our_brands') }}
</div>
</div>
<div
v-for="(brand, brandIndex) of appState.brands()"
:key="brandIndex"
:class="{
'align-items-center': true,
'col-12': !multipleBrands,
'col-12 col-md-6 px-5 my-3': multipleBrands,
'col-12 col-md-6 px-5 my-3': true,
}"
>
<div
:class="{
'd-flex h-100 my-2': true,
'justify-content-start': brandIndex %2 !== 0 && multipleBrands,
'justify-content-end': brandIndex %2 === 0 && multipleBrands,
'justify-content-center': !multipleBrands,
'd-flex align-items-center h-100 my-5': true,
'justify-content-start': brandIndex %2 !== 0,
'justify-content-end': brandIndex %2 === 0,
}"
>
<div
@ -47,7 +49,7 @@
data-bs-toggle="tooltip"
@click="gotoBrand(brand)"
>
<div class="d-inline-block brand-picture-wrapper shadow">
<div class="d-inline-block brand-picture-wrapper">
<img
class="img-fluid"
:src="`/data/${brand.picture}`"
@ -74,7 +76,7 @@
<span class="h4">{{ t('no_brands_available') }}</span>
</div>
</div>
<div v-if="multipleBrands" class="row my-5 pb-5">
<div class="row my-5 pb-5">
<div class="col py-5 my-5 pb-5">
<img
src="assets/pictures/layout/home-bottom-banner.png"
@ -102,21 +104,18 @@ export default defineComponent({
animateIndex: number|null;
animations: Array<string>;
tooltips: Tooltips|null;
multipleBrands: boolean;
} {
return {
appState: {} as AppState,
animateTimeout: undefined,
animateIndex: null,
animations: ["heartBeat", "tada", "shakeX", "rubberBand"],
tooltips: null,
multipleBrands: false,
tooltips: null
};
},
mounted() {
this.$nextTick(() => {this.tooltips = Tooltips.make({type:"parent", parentSelector: ".page-home"});});
this.appState = useAppStore().data;
this.multipleBrands = this.appState.brands().length > 1;
// * ANIMATIONS
clearTimeout(this.animateTimeout);
@ -148,7 +147,7 @@ export default defineComponent({
},
setBrandToAnimate(): void {
clearTimeout(this.animateTimeout);
this.animateIndex = ToolboxHelper.randomInteger(0, this.appState.brands().length - 1);
this.animateIndex = ToolboxHelper.randomInteger(0, this.appState.brands().length -1);
this.animateTimeout = setTimeout(this.setBrandToAnimate, ToolboxHelper.randomInteger(2000, 6000));
},
titleAnimations(brandIndex: number) {
@ -176,17 +175,15 @@ export default defineComponent({
.page-home, .page-home>div {
min-height: 100%;
.brand-picture-wrapper {
@include rfs(5rem, border-radius);
background-color: $color-white;
@include rfs(3rem, padding-top);
@include rfs(3rem, padding-bottom);
@include rfs(8rem, padding-right);
@include rfs(8rem, padding-left);
background-color: $color-white;
}
.brand {
border-radius: 2rem;
}
}
</style>

View file

@ -5,6 +5,7 @@ type Events = {
const emitter = mitt<Events>();
const $bus = {
$on: emitter.on,
$emit: emitter.emit,

View file

@ -43,6 +43,10 @@
"description": "Couleur de la marque",
"$ref": "#/$defs/hexcolor"
},
"shelf": {
"description": "Les enfant sont rendus sur un étagere.",
"type": "boolean"
},
"status": {
"description": "Visible ? (présent dans l'export).",
"type": "boolean"
@ -78,6 +82,7 @@
"name",
"slug",
"color",
"shelf",
"status",
"picture",
"created_at",

View file

@ -58,6 +58,10 @@
"type": "integer",
"minimum": 1
},
"shelf": {
"description": "Les enfant sont rendus sur un étagere.",
"type": "boolean"
},
"status": {
"description": "Visible ? (présent dans l'export).",
"type": "boolean"
@ -100,6 +104,7 @@
"slug",
"picture",
"order",
"shelf",
"status",
"brand_id",
"font_id",

View file

@ -4,10 +4,6 @@
"description": "Settings from Showroom Bo",
"type": "object",
"properties": {
"locales": {
"description": "Langues disponibles dans l'application",
"type": "array"
},
"sub_title": {
"description": "Sous-titre de l'application",
"type": "object",
@ -63,7 +59,6 @@
}
},
"required": [
"locales",
"sub_title",
"footer_phrase",
"logo",

253
static/data/test.json Normal file
View file

@ -0,0 +1,253 @@
{
"logo": {
"src": "https://www.legaulois.fr/assets/images/logo-lgl_378.webp",
"width": "300px"
},
"title": "SIRHA 2023",
"modalSettings": {
"ctaBtnText": "Je suis intéressé(e) par ce produit",
"ctaDisclaimerText": "* en cochant la case j'accepte le RGPD etc ...",
"ctaSaveBtn": "Enregister ma demande"
},
"itemsByLine": 4,
"items": [
{
"id": 1,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 2,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 3,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 4,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 5,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 6,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 7,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 8,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 9,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 10,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 11,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 12,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 13,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 14,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 15,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 16,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 17,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 18,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 19,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 20,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 21,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 22,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 23,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 24,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 25,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 26,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 27,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 28,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 29,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 30,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 31,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 32,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 33,
"name": "Brochettes traditionnelles de poulet Thym-Citron",
"teaser": "Les brochettes comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/1d0f4ad0c7d173c2dfa2cd6e8aea3b69_95c0cd5b-8db4-41bf-8037-195b8d31b376-brochettes-traditionnelle-de-poulet-thym-citron-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
},
{
"id": 34,
"name": "Brochettes traditionnelles de poulet Provençale",
"teaser": "Les brochettes traditionnelles comme chez le boucher",
"img": "https://www.legaulois.fr/storage/cache/images/d879530b9284a7f17901269256cb3c1c_9865467c-86b6-493c-9a30-fabbaeabdff2-brochettes-poulet-provencale-le-gauloispng.",
"description": "Le Gaulois Professionnel vous propose ses brochettes de filet de poulet extra tendre marinées thym - citron.Cette brochette généreuse(160 - 190 g) est constituée d’ un filet de poulet né, élevé et préparé en France.Présentée de façon traditionnelle et qualitative, sa marinade thym citron, douce et typée,ravira tous les gourmands, petits et grands.<br><br>Conseils de préparation : <br><br>À la plancha: Snacker votre brochette 3 minutes sur chaque faces pour obtenir une belle coloration puis, à feu doux, finir la cuisson environ 10 à 15 minutes. <br>Au four: Enfourner vos brochettes à 160° C et laisser cuire 15 à 20 minutes. <br>Au barbecue: environ 15 minutes"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB