From 4a898dc490d09b1bc03ddd74bcd73e9849eb96d5 Mon Sep 17 00:00:00 2001 From: Yohann Valentin Date: Thu, 31 Jul 2025 10:37:00 +0200 Subject: [PATCH 1/8] feat: refactor Baserow table IDs to use configuration class --- .../src/common/baserow/abstractBaserow.ts | 9 ++-- libs/data/src/common/baserow/imageBaserow.ts | 3 +- .../data/src/common/baserow/programBaserow.ts | 7 +-- .../src/common/baserow/testimonyBaserow.ts | 3 +- libs/data/src/common/baserow/types.ts | 6 +++ libs/data/src/config.ts | 8 +++ libs/data/src/configBaserow.ts | 53 +++++++++++++++++++ 7 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 libs/data/src/config.ts create mode 100644 libs/data/src/configBaserow.ts diff --git a/libs/data/src/common/baserow/abstractBaserow.ts b/libs/data/src/common/baserow/abstractBaserow.ts index 3bb1d6f90..08e91db37 100644 --- a/libs/data/src/common/baserow/abstractBaserow.ts +++ b/libs/data/src/common/baserow/abstractBaserow.ts @@ -2,6 +2,7 @@ import axios from 'axios' import dotenv from 'dotenv' import path from 'path' import { fileURLToPath } from 'url' +import ConfigBaserow from '../../configBaserow' import { Id, LinkObject } from './types' dotenv.config() @@ -10,10 +11,10 @@ export abstract class AbstractBaserow { protected readonly __dirname = path.dirname(fileURLToPath(import.meta.url)) private readonly _apiToken = this._setBaserowToken() private readonly _baseUrl = 'https://api.baserow.io/api' - protected readonly _themeTableId = 305258 - protected readonly _operatorTableId = 314410 - protected readonly _geographicAreasTableId = 314474 - protected readonly _projectTableId = 305253 + protected readonly _themeTableId = ConfigBaserow.THEME_ID + protected readonly _operatorTableId = ConfigBaserow.OPERATOR_ID + protected readonly _geographicAreasTableId = ConfigBaserow.GEOGRAPHIC_AREAS_ID + protected readonly _projectTableId = ConfigBaserow.PROJECT_ID private readonly _axiosHeader = { headers: { diff --git a/libs/data/src/common/baserow/imageBaserow.ts b/libs/data/src/common/baserow/imageBaserow.ts index ac48f2914..5cab42bc5 100644 --- a/libs/data/src/common/baserow/imageBaserow.ts +++ b/libs/data/src/common/baserow/imageBaserow.ts @@ -2,6 +2,7 @@ import fs from 'fs' import axios from 'axios' import path from 'path' import sharp from 'sharp' +import ConfigBaserow from '../../configBaserow' import { AbstractBaserow } from './abstractBaserow' import { LinkObject, ImageTable, Image } from './types' import { Result } from 'true-myth' @@ -11,7 +12,7 @@ interface ImageMetadata { } export class ImageBaserow extends AbstractBaserow { - private readonly _imageTableId = 315189 + private readonly _imageTableId = ConfigBaserow.IMAGE_ID private _metadata: ImageMetadata = {} private _processedImages: Set = new Set() diff --git a/libs/data/src/common/baserow/programBaserow.ts b/libs/data/src/common/baserow/programBaserow.ts index 08f5acc8c..907bc96e5 100644 --- a/libs/data/src/common/baserow/programBaserow.ts +++ b/libs/data/src/common/baserow/programBaserow.ts @@ -1,4 +1,5 @@ import fs from 'fs' +import ConfigBaserow from '../../configBaserow' import { AbstractBaserow } from './abstractBaserow' import { ConditionalValues, Program } from './types' import { @@ -14,9 +15,9 @@ import { Theme } from '../../theme/types/domain' import { FileManager } from '../fileManager' export class ProgramBaserow extends AbstractBaserow { - private readonly _geographicCoverageTableId = 314470 - private readonly _programTableId = 314437 - private readonly _conditionnalValuesTableId = 351202 + private readonly _geographicCoverageTableId = ConfigBaserow.GEOGRAPHIC_COVERAGE_ID + private readonly _programTableId = ConfigBaserow.PROGRAM_ID + private readonly _conditionnalValuesTableId = ConfigBaserow.CONDITIONAL_VALUES_ID private _operators: Operator[] = [] private _geographicAreas: GeographicCoverage[] = [] diff --git a/libs/data/src/common/baserow/testimonyBaserow.ts b/libs/data/src/common/baserow/testimonyBaserow.ts index 8edac3913..9355794b4 100644 --- a/libs/data/src/common/baserow/testimonyBaserow.ts +++ b/libs/data/src/common/baserow/testimonyBaserow.ts @@ -1,3 +1,4 @@ +import ConfigBaserow from '../../configBaserow' import { AbstractBaserow } from './abstractBaserow' import { BaserowTestimony } from './types' import { Testimony } from '../../testimony/types/shared' @@ -5,7 +6,7 @@ import { ImageBaserow } from './imageBaserow' import path from 'path' export class TestimonyBaserow extends AbstractBaserow { - private readonly _testimoniesTableId = 399896 + private readonly _testimoniesTableId = ConfigBaserow.TESTIMONIES_ID private readonly _logPath: string = path.join(this.__dirname, '../../../static/testimony_images_download_info.json') private _imageDownloader: ImageBaserow private readonly _imagePath = '/images/testimony/' diff --git a/libs/data/src/common/baserow/types.ts b/libs/data/src/common/baserow/types.ts index d374583a2..b30b8f0df 100644 --- a/libs/data/src/common/baserow/types.ts +++ b/libs/data/src/common/baserow/types.ts @@ -132,3 +132,9 @@ export interface BaserowTestimony extends Id, BaserowSectors { 'Mise en avant': number 'Nom entreprise': string } + +export interface BaserowFaq extends Id { + Question: string + Réponse: string + Actif: boolean +} diff --git a/libs/data/src/config.ts b/libs/data/src/config.ts new file mode 100644 index 000000000..3b33c0d4e --- /dev/null +++ b/libs/data/src/config.ts @@ -0,0 +1,8 @@ +import { ConfigCommon } from '@tee/common' +import dotenv from 'dotenv' + +export default class Config extends ConfigCommon { + public static loadDotEnv() { + dotenv.config() + } +} diff --git a/libs/data/src/configBaserow.ts b/libs/data/src/configBaserow.ts new file mode 100644 index 000000000..574a837b9 --- /dev/null +++ b/libs/data/src/configBaserow.ts @@ -0,0 +1,53 @@ +import { ConfigCommon } from '@tee/common' + +export default class ConfigBaserow extends ConfigCommon { + private static _TABLE_ID_CONDITIONAL_VALUES = 351202 + private static _TABLE_ID_GEOGRAPHIC_AREAS = 314474 + private static _TABLE_ID_GEOGRAPHIC_COVERAGE = 314470 + private static _TABLE_ID_IMAGE = 315189 + private static _TABLE_ID_OPERATOR = 314410 + private static _TABLE_ID_PROGRAM = 314437 + private static _TABLE_ID_PROJECT = 305253 + private static _TABLE_ID_TESTIMONIES = 399896 + private static _TABLE_ID_THEME = 305258 + + public static get TOKEN() { + return this.getEnvValue('BASEROW_TOKEN') + } + + public static get CONDITIONAL_VALUES_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_CONDITIONAL_VALUES', this._TABLE_ID_CONDITIONAL_VALUES.toString())) + } + + public static get GEOGRAPHIC_AREAS_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_GEOGRAPHIC_AREAS', this._TABLE_ID_GEOGRAPHIC_AREAS.toString())) + } + + public static get GEOGRAPHIC_COVERAGE_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_GEOGRAPHIC_COVERAGE', this._TABLE_ID_GEOGRAPHIC_COVERAGE.toString())) + } + + public static get IMAGE_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_IMAGE', this._TABLE_ID_IMAGE.toString())) + } + + public static get OPERATOR_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_OPERATOR', this._TABLE_ID_OPERATOR.toString())) + } + + public static get PROGRAM_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_PROGRAM', this._TABLE_ID_PROGRAM.toString())) + } + + public static get PROJECT_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_PROJECT', this._TABLE_ID_PROJECT.toString())) + } + + public static get TESTIMONIES_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_TESTIMONIES', this._TABLE_ID_TESTIMONIES.toString())) + } + + public static get THEME_ID() { + return parseInt(this.getEnvValue('BASEROW_TABLE_ID_THEME', this._TABLE_ID_THEME.toString())) + } +} From 90c28ad26b4b052e6be04e4b1864228396e6c827 Mon Sep 17 00:00:00 2001 From: Yohann Valentin Date: Thu, 31 Jul 2025 10:37:00 +0200 Subject: [PATCH 2/8] feat: refactor Baserow table IDs to use configuration class --- libs/data/src/common/baserow/types.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/data/src/common/baserow/types.ts b/libs/data/src/common/baserow/types.ts index d374583a2..b30b8f0df 100644 --- a/libs/data/src/common/baserow/types.ts +++ b/libs/data/src/common/baserow/types.ts @@ -132,3 +132,9 @@ export interface BaserowTestimony extends Id, BaserowSectors { 'Mise en avant': number 'Nom entreprise': string } + +export interface BaserowFaq extends Id { + Question: string + Réponse: string + Actif: boolean +} From d77213e96b0a64a99de5a781c9dc1fe2a0ef47a2 Mon Sep 17 00:00:00 2001 From: Yohann Valentin Date: Thu, 31 Jul 2025 16:23:04 +0200 Subject: [PATCH 3/8] feat: add BaserowData interface for paginated results --- .../src/common/baserow/abstractBaserow.ts | 33 +++++++++++-------- libs/data/src/common/baserow/types.ts | 13 ++++---- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/libs/data/src/common/baserow/abstractBaserow.ts b/libs/data/src/common/baserow/abstractBaserow.ts index 08e91db37..8fe368de1 100644 --- a/libs/data/src/common/baserow/abstractBaserow.ts +++ b/libs/data/src/common/baserow/abstractBaserow.ts @@ -3,13 +3,13 @@ import dotenv from 'dotenv' import path from 'path' import { fileURLToPath } from 'url' import ConfigBaserow from '../../configBaserow' -import { Id, LinkObject } from './types' +import { BaserowData, Id, LinkObject } from './types' dotenv.config() export abstract class AbstractBaserow { protected readonly __dirname = path.dirname(fileURLToPath(import.meta.url)) - private readonly _apiToken = this._setBaserowToken() + private readonly _apiToken = ConfigBaserow.TOKEN private readonly _baseUrl = 'https://api.baserow.io/api' protected readonly _themeTableId = ConfigBaserow.THEME_ID protected readonly _operatorTableId = ConfigBaserow.OPERATOR_ID @@ -22,18 +22,30 @@ export abstract class AbstractBaserow { } } + protected get _axios() { + return axios.create(this._axiosHeader) + } + + protected async _getData(tableId: number) { + return await this._axios.get>(`${this._baseUrl}/database/rows/table/${tableId}/?user_field_names=true`) + } + + protected async _getDatum(tableId: number, rowId: number) { + return await this._axios.get(`${this._baseUrl}/database/rows/table/${tableId}/${rowId}/?user_field_names=true`) + } + protected async _getTableData(tableId: number): Promise { try { - const response = await axios.get(`${this._baseUrl}/database/rows/table/${tableId}/?user_field_names=true`, this._axiosHeader) + const response = await this._getData(tableId) await this._delay(100) // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access let results = response.data.results let next = response.data.next while (next) { - const newResponse = await axios.get(next, this._axiosHeader) + const response = await this._axios.get(next) await this._delay(100) - results = results.concat(newResponse.data.results) - next = newResponse.data.next + results = results.concat(response.data.results) + next = response.data.next } return results } catch (error) { @@ -44,7 +56,7 @@ export abstract class AbstractBaserow { protected async _getRowData(tableId: number, rowId: number): Promise { try { - const response = await axios.get(`${this._baseUrl}/database/rows/table/${tableId}/${rowId}/?user_field_names=true`, this._axiosHeader) + const response = await this._getDatum(tableId, rowId) // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access return response.data @@ -67,11 +79,4 @@ export abstract class AbstractBaserow { return tableData.filter((item) => item !== undefined) as T[] } - - private _setBaserowToken(): string { - if (process.env['BASEROW_TOKEN']) { - return process.env['BASEROW_TOKEN'] - } - throw Error('Baserow token not found.') - } } diff --git a/libs/data/src/common/baserow/types.ts b/libs/data/src/common/baserow/types.ts index b30b8f0df..1f17f491e 100644 --- a/libs/data/src/common/baserow/types.ts +++ b/libs/data/src/common/baserow/types.ts @@ -4,6 +4,13 @@ export interface Id { id: number } +export interface BaserowData { + count: number + next: string | null + previous: string | null + results: T[] +} + export interface BaserowProject extends Id, BaserowSectors { order: string Nom: string @@ -132,9 +139,3 @@ export interface BaserowTestimony extends Id, BaserowSectors { 'Mise en avant': number 'Nom entreprise': string } - -export interface BaserowFaq extends Id { - Question: string - Réponse: string - Actif: boolean -} From daa6e2af724f7ba45689c4d2f86f139edc84ca02 Mon Sep 17 00:00:00 2001 From: Yohann Valentin Date: Thu, 31 Jul 2025 18:50:44 +0200 Subject: [PATCH 4/8] feat: add meta title and description fields to Baserow data models and update SEO metadata usage --- .../components/element/TeeContentBlock.vue | 2 +- .../program/detail/ProgramDetail.vue | 5 +++-- .../project/details/ProjectDetail.vue | 5 +++-- apps/nuxt/src/tools/metaSeo.ts | 7 +++---- .../program-with-publicodes-schema.json | 8 ++++++++ .../data/src/common/baserow/programBaserow.ts | 20 +++++++++---------- .../data/src/common/baserow/projectBaserow.ts | 4 +++- libs/data/src/common/baserow/types.ts | 10 ++++++++-- libs/data/src/program/types/domain.ts | 4 ++-- libs/data/src/program/types/program.ts | 8 ++++++++ .../program/yamlGenerator/coreGenerator.ts | 2 ++ libs/data/src/project/types/shared.ts | 2 ++ 12 files changed, 53 insertions(+), 24 deletions(-) diff --git a/apps/nuxt/src/components/element/TeeContentBlock.vue b/apps/nuxt/src/components/element/TeeContentBlock.vue index 7a9f57576..7bb247a28 100644 --- a/apps/nuxt/src/components/element/TeeContentBlock.vue +++ b/apps/nuxt/src/components/element/TeeContentBlock.vue @@ -15,7 +15,7 @@