From a4745cf37794c7c561b639a88c7396cdd1af93e2 Mon Sep 17 00:00:00 2001 From: Dick van Hirtum Date: Sat, 20 Dec 2025 10:50:30 +0100 Subject: [PATCH 1/3] added technology radar components --- nodesource_setup.sh | 113 ++++++++++++++++++ .../article/content-types/article/schema.json | 9 +- .../content-types/radar-item/schema.json | 67 +++++++++++ src/api/radar-item/controllers/radar-item.js | 9 ++ src/api/radar-item/routes/radar-item.js | 9 ++ src/api/radar-item/services/radar-item.js | 9 ++ src/api/tag/content-types/tag/schema.json | 10 +- types/generated/contentTypes.d.ts | 52 +++++++- 8 files changed, 271 insertions(+), 7 deletions(-) create mode 100644 nodesource_setup.sh create mode 100644 src/api/radar-item/content-types/radar-item/schema.json create mode 100644 src/api/radar-item/controllers/radar-item.js create mode 100644 src/api/radar-item/routes/radar-item.js create mode 100644 src/api/radar-item/services/radar-item.js diff --git a/nodesource_setup.sh b/nodesource_setup.sh new file mode 100644 index 0000000..357fd5e --- /dev/null +++ b/nodesource_setup.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# Logger Function +log() { + local message="$1" + local type="$2" + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + local color + local endcolor="\033[0m" + + case "$type" in + "info") color="\033[38;5;79m" ;; + "success") color="\033[1;32m" ;; + "error") color="\033[1;31m" ;; + *) color="\033[1;34m" ;; + esac + + echo -e "${color}${timestamp} - ${message}${endcolor}" +} + +# Error handler function +handle_error() { + local exit_code=$1 + local error_message="$2" + log "Error: $error_message (Exit Code: $exit_code)" "error" + exit $exit_code +} + +# Function to check for command availability +command_exists() { + command -v "$1" &> /dev/null +} + +check_os() { + if ! [ -f "/etc/debian_version" ]; then + echo "Error: This script is only supported on Debian-based systems." + exit 1 + fi +} + +# Function to Install the script pre-requisites +install_pre_reqs() { + log "Installing pre-requisites" "info" + + # Run 'apt update' + if ! apt update -y; then + handle_error "$?" "Failed to run 'apt update'" + fi + + # Run 'apt install' + if ! apt install -y apt-transport-https ca-certificates curl gnupg; then + handle_error "$?" "Failed to install packages" + fi + + if ! mkdir -p /usr/share/keyrings; then + handle_error "$?" "Makes sure the path /usr/share/keyrings exist or run ' mkdir -p /usr/share/keyrings' with sudo" + fi + + rm -f /usr/share/keyrings/nodesource.gpg || true + rm -f /etc/apt/sources.list.d/nodesource.list || true + + # Run 'curl' and 'gpg' to download and import the NodeSource signing key + if ! curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg; then + handle_error "$?" "Failed to download and import the NodeSource signing key" + fi + + # Explicitly set the permissions to ensure the file is readable by all + if ! chmod 644 /usr/share/keyrings/nodesource.gpg; then + handle_error "$?" "Failed to set correct permissions on /usr/share/keyrings/nodesource.gpg" + fi +} + +# Function to configure the Repo +configure_repo() { + local node_version=$1 + + arch=$(dpkg --print-architecture) + if [ "$arch" != "amd64" ] && [ "$arch" != "arm64" ] && [ "$arch" != "armhf" ]; then + handle_error "1" "Unsupported architecture: $arch. Only amd64, arm64, and armhf are supported." + fi + + echo "deb [arch=$arch signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$node_version nodistro main" | tee /etc/apt/sources.list.d/nodesource.list > /dev/null + + # N|solid Config + echo "Package: nsolid" | tee /etc/apt/preferences.d/nsolid > /dev/null + echo "Pin: origin deb.nodesource.com" | tee -a /etc/apt/preferences.d/nsolid > /dev/null + echo "Pin-Priority: 600" | tee -a /etc/apt/preferences.d/nsolid > /dev/null + + # Nodejs Config + echo "Package: nodejs" | tee /etc/apt/preferences.d/nodejs > /dev/null + echo "Pin: origin deb.nodesource.com" | tee -a /etc/apt/preferences.d/nodejs > /dev/null + echo "Pin-Priority: 600" | tee -a /etc/apt/preferences.d/nodejs > /dev/null + + # Run 'apt update' + if ! apt update -y; then + handle_error "$?" "Failed to run 'apt update'" + else + log "Repository configured successfully." + log "To install Node.js, run: apt install nodejs -y" "info" + log "You can use N|solid Runtime as a node.js alternative" "info" + log "To install N|solid Runtime, run: apt install nsolid -y \n" "success" + fi +} + +# Define Node.js version +NODE_VERSION="22.x" + +# Check OS +check_os + +# Main execution +install_pre_reqs || handle_error $? "Failed installing pre-requisites" +configure_repo "$NODE_VERSION" || handle_error $? "Failed configuring repository" diff --git a/src/api/article/content-types/article/schema.json b/src/api/article/content-types/article/schema.json index db71299..e292f7b 100644 --- a/src/api/article/content-types/article/schema.json +++ b/src/api/article/content-types/article/schema.json @@ -41,7 +41,10 @@ }, "site": { "type": "enumeration", - "enum": ["dotnet", "cloud"], + "enum": [ + "dotnet", + "cloud" + ], "required": true, "default": "dotnet", "pluginOptions": { @@ -68,7 +71,9 @@ "type": "media", "multiple": false, "required": true, - "allowedTypes": ["images"], + "allowedTypes": [ + "images" + ], "pluginOptions": { "i18n": { "localized": true diff --git a/src/api/radar-item/content-types/radar-item/schema.json b/src/api/radar-item/content-types/radar-item/schema.json new file mode 100644 index 0000000..3bae483 --- /dev/null +++ b/src/api/radar-item/content-types/radar-item/schema.json @@ -0,0 +1,67 @@ +{ + "kind": "collectionType", + "collectionName": "radar_items", + "info": { + "singularName": "radar-item", + "pluralName": "radar-items", + "displayName": "Radar Item" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "slug": { + "type": "uid", + "targetField": "title", + "required": true + }, + "quadrant": { + "type": "enumeration", + "required": true, + "enum": [ + "Techniques", + "Tools", + "Platforms", + "Languages & Frameworks" + ] + }, + "ring": { + "type": "enumeration", + "required": true, + "enum": [ + "Adopt", + "Trial", + "Assess", + "Hold" + ] + }, + "title": { + "type": "string", + "required": true + }, + "description": { + "type": "richtext", + "required": true + }, + "pros": { + "type": "component", + "component": "elements.list-item", + "repeatable": true + }, + "cons": { + "type": "component", + "component": "elements.list-item", + "repeatable": true + }, + "conclusion": { + "type": "richtext" + }, + "tags": { + "type": "relation", + "relation": "manyToMany", + "target": "api::tag.tag", + "inversedBy": "radar_items" + } + } +} diff --git a/src/api/radar-item/controllers/radar-item.js b/src/api/radar-item/controllers/radar-item.js new file mode 100644 index 0000000..9445aae --- /dev/null +++ b/src/api/radar-item/controllers/radar-item.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * radar-item controller + */ + +const { createCoreController } = require('@strapi/strapi').factories; + +module.exports = createCoreController('api::radar-item.radar-item'); diff --git a/src/api/radar-item/routes/radar-item.js b/src/api/radar-item/routes/radar-item.js new file mode 100644 index 0000000..ce037ac --- /dev/null +++ b/src/api/radar-item/routes/radar-item.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * radar-item router + */ + +const { createCoreRouter } = require('@strapi/strapi').factories; + +module.exports = createCoreRouter('api::radar-item.radar-item'); diff --git a/src/api/radar-item/services/radar-item.js b/src/api/radar-item/services/radar-item.js new file mode 100644 index 0000000..0d837fa --- /dev/null +++ b/src/api/radar-item/services/radar-item.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * radar-item service + */ + +const { createCoreService } = require('@strapi/strapi').factories; + +module.exports = createCoreService('api::radar-item.radar-item'); diff --git a/src/api/tag/content-types/tag/schema.json b/src/api/tag/content-types/tag/schema.json index 25b9f17..11c7153 100644 --- a/src/api/tag/content-types/tag/schema.json +++ b/src/api/tag/content-types/tag/schema.json @@ -8,9 +8,9 @@ "description": "" }, "options": { - "draftAndPublish": true, - "populateCreatorFields": true + "draftAndPublish": true }, + "pluginOptions": {}, "attributes": { "title": { "type": "string", @@ -21,6 +21,12 @@ "relation": "manyToMany", "target": "api::article.article", "mappedBy": "tags" + }, + "radar_items": { + "type": "relation", + "relation": "manyToMany", + "target": "api::radar-item.radar-item", + "mappedBy": "tags" } } } diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index c1494f4..e5e7021 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -803,6 +803,46 @@ export interface ApiPagePage extends Struct.CollectionTypeSchema { }; } +export interface ApiRadarItemRadarItem extends Struct.CollectionTypeSchema { + collectionName: 'radar_items'; + info: { + displayName: 'Radar Item'; + pluralName: 'radar-items'; + singularName: 'radar-item'; + }; + options: { + draftAndPublish: true; + }; + attributes: { + conclusion: Schema.Attribute.RichText; + cons: Schema.Attribute.Component<'elements.list-item', true>; + createdAt: Schema.Attribute.DateTime; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + description: Schema.Attribute.RichText & Schema.Attribute.Required; + locale: Schema.Attribute.String & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::radar-item.radar-item' + > & + Schema.Attribute.Private; + pros: Schema.Attribute.Component<'elements.list-item', true>; + publishedAt: Schema.Attribute.DateTime; + quadrant: Schema.Attribute.Enumeration< + ['Techniques', 'Tools', 'Platforms', 'Languages & Frameworks'] + > & + Schema.Attribute.Required; + ring: Schema.Attribute.Enumeration<['Adopt', 'Trial', 'Assess', 'Hold']> & + Schema.Attribute.Required; + slug: Schema.Attribute.UID<'title'> & Schema.Attribute.Required; + tags: Schema.Attribute.Relation<'manyToMany', 'api::tag.tag'>; + title: Schema.Attribute.String & Schema.Attribute.Required; + updatedAt: Schema.Attribute.DateTime; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + }; +} + export interface ApiTagTag extends Struct.CollectionTypeSchema { collectionName: 'tags'; info: { @@ -813,19 +853,24 @@ export interface ApiTagTag extends Struct.CollectionTypeSchema { }; options: { draftAndPublish: true; - populateCreatorFields: true; }; attributes: { articles: Schema.Attribute.Relation<'manyToMany', 'api::article.article'>; createdAt: Schema.Attribute.DateTime; - createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'>; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation<'oneToMany', 'api::tag.tag'> & Schema.Attribute.Private; publishedAt: Schema.Attribute.DateTime; + radar_items: Schema.Attribute.Relation< + 'manyToMany', + 'api::radar-item.radar-item' + >; title: Schema.Attribute.String & Schema.Attribute.Required; updatedAt: Schema.Attribute.DateTime; - updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'>; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; }; } @@ -1344,6 +1389,7 @@ declare module '@strapi/strapi' { 'api::global-setting.global-setting': ApiGlobalSettingGlobalSetting; 'api::homepage.homepage': ApiHomepageHomepage; 'api::page.page': ApiPagePage; + 'api::radar-item.radar-item': ApiRadarItemRadarItem; 'api::tag.tag': ApiTagTag; 'plugin::content-releases.release': PluginContentReleasesRelease; 'plugin::content-releases.release-action': PluginContentReleasesReleaseAction; From 4010dea7f21f337a78e004491546dca2ed822b8f Mon Sep 17 00:00:00 2001 From: Dick van Hirtum Date: Tue, 23 Dec 2025 14:55:45 +0100 Subject: [PATCH 2/3] added technology radar ui component --- src/api/page/content-types/page/schema.json | 39 +++++++++++---------- src/api/page/middlewares/page-populate.js | 3 ++ src/components/ui/technology-radar.json | 15 ++++++++ types/generated/components.d.ts | 12 +++++++ types/generated/contentTypes.d.ts | 1 + 5 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 src/components/ui/technology-radar.json diff --git a/src/api/page/content-types/page/schema.json b/src/api/page/content-types/page/schema.json index c7c962e..8890ade 100644 --- a/src/api/page/content-types/page/schema.json +++ b/src/api/page/content-types/page/schema.json @@ -18,24 +18,29 @@ "attributes": { "title_website": { "type": "string", - "required": true, "pluginOptions": { "i18n": { "localized": true } - } + }, + "required": true }, "description": { "type": "text", - "required": true, "pluginOptions": { "i18n": { "localized": true } - } + }, + "required": true }, "components": { "type": "dynamiczone", + "pluginOptions": { + "i18n": { + "localized": true + } + }, "components": [ "ui.text", "ui.opsomming", @@ -43,35 +48,31 @@ "ui.quote", "ui.page-image", "ui.artikelen", - "ui.directeuren" - ], - "pluginOptions": { - "i18n": { - "localized": true - } - } + "ui.directeuren", + "ui.technology-radar" + ] }, "site": { "type": "enumeration", - "enum": [ - "cloud", - "dotnet" - ], - "required": true, - "default": "dotnet", "pluginOptions": { "i18n": { "localized": false } - } + }, + "required": true, + "default": "dotnet", + "enum": [ + "cloud", + "dotnet" + ] }, "title_cms": { + "type": "string", "pluginOptions": { "i18n": { "localized": true } }, - "type": "string", "required": true }, "slug": { diff --git a/src/api/page/middlewares/page-populate.js b/src/api/page/middlewares/page-populate.js index 18f0609..f756378 100644 --- a/src/api/page/middlewares/page-populate.js +++ b/src/api/page/middlewares/page-populate.js @@ -44,6 +44,9 @@ const populate = { }, }, }, + 'ui.technology-radar': { + fields: ['title'], + }, }, }, }; diff --git a/src/components/ui/technology-radar.json b/src/components/ui/technology-radar.json new file mode 100644 index 0000000..4614b1c --- /dev/null +++ b/src/components/ui/technology-radar.json @@ -0,0 +1,15 @@ +{ + "collectionName": "components_ui_technology_radars", + "info": { + "displayName": "Technology Radar", + "icon": "globe" + }, + "options": {}, + "attributes": { + "title": { + "type": "string", + "required": true + } + }, + "config": {} +} diff --git a/types/generated/components.d.ts b/types/generated/components.d.ts index 16956db..baae135 100644 --- a/types/generated/components.d.ts +++ b/types/generated/components.d.ts @@ -267,6 +267,17 @@ export interface UiTeam extends Struct.ComponentSchema { }; } +export interface UiTechnologyRadar extends Struct.ComponentSchema { + collectionName: 'components_ui_technology_radars'; + info: { + displayName: 'Technology Radar'; + icon: 'globe'; + }; + attributes: { + title: Schema.Attribute.String & Schema.Attribute.Required; + }; +} + export interface UiText extends Struct.ComponentSchema { collectionName: 'components_ui_texts'; info: { @@ -313,6 +324,7 @@ declare module '@strapi/strapi' { 'ui.page-image': UiPageImage; 'ui.quote': UiQuote; 'ui.team': UiTeam; + 'ui.technology-radar': UiTechnologyRadar; 'ui.text': UiText; 'ui.titel': UiTitel; } diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index e5e7021..e29892f 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -753,6 +753,7 @@ export interface ApiPagePage extends Struct.CollectionTypeSchema { 'ui.page-image', 'ui.artikelen', 'ui.directeuren', + 'ui.technology-radar', ] > & Schema.Attribute.SetPluginOptions<{ From cddc2a4d75916ed2890bed0b09b966ac84b60485 Mon Sep 17 00:00:00 2001 From: Dick van Hirtum Date: Mon, 29 Dec 2025 15:42:28 +0100 Subject: [PATCH 3/3] renamed quadrants --- src/api/radar-item/content-types/radar-item/schema.json | 6 +++--- types/generated/contentTypes.d.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/radar-item/content-types/radar-item/schema.json b/src/api/radar-item/content-types/radar-item/schema.json index 3bae483..0abea16 100644 --- a/src/api/radar-item/content-types/radar-item/schema.json +++ b/src/api/radar-item/content-types/radar-item/schema.json @@ -20,10 +20,10 @@ "type": "enumeration", "required": true, "enum": [ - "Techniques", + "Technieken", "Tools", - "Platforms", - "Languages & Frameworks" + "Platformen", + "Talen & Frameworks" ] }, "ring": { diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index e29892f..d1272bc 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -830,7 +830,7 @@ export interface ApiRadarItemRadarItem extends Struct.CollectionTypeSchema { pros: Schema.Attribute.Component<'elements.list-item', true>; publishedAt: Schema.Attribute.DateTime; quadrant: Schema.Attribute.Enumeration< - ['Techniques', 'Tools', 'Platforms', 'Languages & Frameworks'] + ['Technieken', 'Tools', 'Platformen', 'Talen & Frameworks'] > & Schema.Attribute.Required; ring: Schema.Attribute.Enumeration<['Adopt', 'Trial', 'Assess', 'Hold']> &