Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Image Docker custom de grist aux couleur de la Marianne #7

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/docker-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ jobs:
image: lasuite/keycloak-apps
path: dockerfiles/keycloak-apps
cmd_version: "echo \"$(cat dockerfiles/keycloak-apps/Dockerfile | head -n1 | cut -d' ' -f2)\" >> $GITHUB_ENV"
- dockerfile: dockerfiles/grist/Dockerfile
image: lasuite/grist
path: dockerfiles/grist
cmd_version: "grep -Po \"GRIST_\\KVERSION=.*\" dockerfiles/grist/Dockerfile | head -n 1 >> $GITHUB_ENV"
steps:
-
uses: actions/create-github-app-token@v1
Expand Down
41 changes: 41 additions & 0 deletions dockerfiles/grist/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
ARG GRIST_VERSION=1.1.14

FROM gristlabs/grist:$GRIST_VERSION

WORKDIR /grist/static

ARG LASUITE_VERSION=1.0.1
ARG LASUITE_ARCHIVE=gouvfr-lasuite-integration-$LASUITE_VERSION.tgz

RUN apt-get update
RUN apt-get install -y wget

RUN wget https://github.com/numerique-gouv/lasuite-integration/releases/download/integration-v$LASUITE_VERSION/$LASUITE_ARCHIVE
RUN tar -zxvf $LASUITE_ARCHIVE

# Archive is extracted as "package"
# We move it to @gouvfr-lasuite/integration to be complient with
# https://integration.lasuite.numerique.gouv.fr/guides/gaufre/
RUN mkdir @gouvfr-lasuite
RUN mv package @gouvfr-lasuite/integration

RUN rm $LASUITE_ARCHIVE

COPY ressources/* ./
RUN mv marianne-48x48.png ui-icons/Logo/

RUN apt-get remove --purge -y wget

WORKDIR /grist

RUN \
groupadd grist -g 10022 && \
useradd -ms /bin/bash grist -g grist -u 10022 && \
chown -R grist:grist /grist && \
chown -R grist:grist /persist

USER grist

# Variable to force grist to use custom.css and dinum-custom.js
ENV APP_STATIC_INCLUDE_CUSTOM_CSS true
ENV GRIST_INCLUDE_CUSTOM_SCRIPT_URL /v/unknown/dinum-custom.js
59 changes: 59 additions & 0 deletions dockerfiles/grist/ressources/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@import url("@gouvfr-lasuite/integration/dist/css/gaufre.css");

:root {
/* logo */
--icon-GristLogo: url("ui-icons/Logo/marianne-48x48.png") !important;
--grist-logo-bg: #ffffff !important;
--grist-logo-size: 22px 22px !important;

/* colors */
--grist-color-light-grey: #f6f6f6 !important;
--grist-color-medium-grey: #dddddd99 !important;
--grist-color-medium-grey-opaque: #e5e5e5 !important;
--grist-color-dark-grey: #dddddd !important;
--grist-color-light: #ffffff !important;
--grist-color-dark: #2f2f2f !important;
--grist-color-dark-bg: #2f2f2f !important;
--grist-color-slate: #929292 !important;
--grist-color-light-green: #000091 !important;
--grist-color-dark-green: #2323ff !important;
--grist-color-darker-green: #2323ff !important;
--grist-color-lighter-green: #cacafb !important;
--grist-color-lighter-blue: #0078f3 !important;
--grist-color-light-blue: #0063cb !important;
--grist-color-cursor: #000091 !important;
--grist-color-selection: #ececfe !important;
--grist-color-selection-opaque: #ececfe !important;
--grist-color-selection-darker-opaque: #e3e3fd !important;
--grist-color-inactive-cursor: #cacafb !important;
--grist-color-hover: #cecece !important;
--grist-color-error: #d64d00 !important;
--grist-color-warning: #fea941 !important;
--grist-color-warning-bg: #dd962c !important;
--grist-color-backdrop: #3a3a3a !important;
--grist-label-text-bg: #ffffff !important;
--grist-label-active-bg: #f0f0f0 !important;
--grist-primary-fg: #000091 !important;
--grist-primary-fg-hover: #2323ff !important;
--grist-primary-bg: #ffffff !important;
--grist-control-bg: #ffffff !important;
--grist-control-fg: #000091 !important;
--grist-primary-fg-hover: #2323ff !important;
--grist-control-border: 1px solid #2323ff !important;
--grist-toast-bg: #040404 !important;

/* Custom inputs colors*/
--grist-actual-cell-color: #6e6ef2 !important;
--accent-color: #6e6ef2 !important;
}

.test-rule-permissions [class*=deny] {
background-color: #ff0000;
background-image: linear-gradient(-45deg, #ff0000 14px, white 15px 16px, #ff0000 16px);
border-color: #ff0000;
}

.test-rule-permissions [class*=allow] {
background-color: #16b378;
border-color: #16b378;
}
147 changes: 147 additions & 0 deletions dockerfiles/grist/ressources/dinum-custom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// ========================
// START dialog
// ========================
(function maintainanceDialog() {
// CONFIGURER ICI
const config = {
// CEST = heure d'été (+0200), CET = heure d'hiver ().
selectedTz: 'CEST',

// Date du début de la maintenance
startDateWithoutTimezone: '2024-04-18T17:30:00',

// Durée de la maitenance prévue (en minutes).
// ASTUCE: Si la maintenance dure moins longtemps que prévu, réduire a postériori la valeur de cette variable de sorte à ce qu'elle n'apparaisse plus.
// Pas besoin de committer ensuite le changement dans le repo.
maintainanceDurationMinutes: 60,
};
// FIN CONFIGURER

const tz = { CEST: '0200', CET: '0100' };

const maintainanceStartDate = new Date(`${config.startDateWithoutTimezone}+${tz[config.selectedTz]}`);
const maintainanceEndDate = (function () {
const date = new Date(maintainanceStartDate); // If I may, Date API is really ackward, especially because it is not immutable
date.setMinutes(maintainanceStartDate.getMinutes() + config.maintainanceDurationMinutes);
return date;
})();


function showDialog() {
const dialog = document.createElement('dialog');
dialog.id = 'maintenancePopin';
const dateFormatter = new Intl.DateTimeFormat('fr-FR', {
dateStyle: 'full',
timeStyle: 'short',
timeZone: 'Europe/Paris',
});
const timeFormatter = new Intl.DateTimeFormat('fr-FR', {
timeStyle: 'short',
timeZone: 'Europe/Paris',
});

dialog.innerHTML = `
<p>
Une maintenance de Grist est prévue le ${dateFormatter.format(maintainanceStartDate)} heure de Paris
jusqu'à ${timeFormatter.format(maintainanceEndDate)}, période durant laquelle le service sera momentanément indisponible. <br>
Pour toute remarque ou question, merci de nous contacter via <a href="mailto:[email protected]">[email protected]</a></p>
<p>Merci de votre compréhension</p>
<form method="dialog">
<p>
<input type="checkbox" id="jaiCompris">
<label for="jaiCompris">J'ai lu et compris, merci de ne plus me montrer ce message</label>
</p>
<button disabled id="fermerPopinMaintenance">Fermer</button>
</form>
`;
document.body.appendChild(dialog);
document.getElementById('fermerPopinMaintenance').onclick = function onMessageUnderstood() {
localStorage.maintainanceStartDateAgreement = maintainanceStartDate.toISOString();
}
document.getElementById('jaiCompris').onchange = function (ev) {
document.getElementById('fermerPopinMaintenance').disabled = !ev.target.checked;
}
dialog.showModal();
}

if (Date.now() < maintainanceEndDate.getTime() &&
(!localStorage.maintainanceStartDateAgreement || localStorage.maintainanceStartDateAgreement !== maintainanceStartDate.toISOString())) {
window.addEventListener('load', showDialog);
}
})();

// ========================
// END dialog
// ========================

// ========================
// START gauffre
// ========================


window.addEventListener('load', async (event) => {
await waitForElm('body.interface-full');
// gristApp.topAppModel.appObs is not populated at that point, listen for the observer to their first change

let listener;
listener = gristApp.topAppModel.appObs.addListener( async (appObs) => {
// Gauffre must be displayed only in home pages
if (appObs.pageType.get() !== "home"){
return 1;
}
// We wait for header bar to be available in DOM to insert Gauffre in it
await waitForElm('.test-top-header');

// Create gauffre button Tag
const gristBar = document.getElementsByClassName('test-top-header')[0];
const gauffreDiv = document.createElement('div');
const gauffreButton = document.createElement('button');
const gauffreText = "Les services de La Suite numérique";

gauffreDiv.className = 'gauffre-container';
gauffreButton.type = "button";
gauffreButton.className = "lasuite-gaufre-btn lasuite-gaufre-btn--vanilla js-lasuite-gaufre-btn";
gauffreButton.title = gauffreText;
gauffreButton.text = gauffreText;
gauffreDiv.appendChild(gauffreButton);
gristBar.insertBefore(gauffreDiv, gristBar.lastChild);

// Create gauffre script Tag
const gauffreScript = document.createElement('script');

gauffreScript.id = "lasuite-gaufre-script";
gauffreScript.setAttribute('async', true);
gauffreScript.setAttribute('defer', true);
gauffreScript.src = "https://integration.lasuite.numerique.gouv.fr/api/v1/gaufre.js";
document.head.insertBefore(gauffreScript, document.head.lastChild);

// Should be disposed so we only listen for changes once, but failed to achieve doing that.
// listener.dispose();
});
});

// from https://stackoverflow.com/a/61511955
function waitForElm(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}

const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});

// If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}

// ========================
// END gauffre
// ========================
Binary file added dockerfiles/grist/ressources/marianne-48x48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading