mirror of
https://gitea.com/mcereda/oam.git
synced 2026-02-09 05:44:23 +00:00
refactor: rename containers as docker compositions, as they are
This commit is contained in:
4
docker compositions/techradar/aoe/.gitignore
vendored
Normal file
4
docker compositions/techradar/aoe/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/.techradar
|
||||
/build
|
||||
/node_modules
|
||||
/package-lock.json
|
||||
21
docker compositions/techradar/aoe/Makefile
Normal file
21
docker compositions/techradar/aoe/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env make
|
||||
|
||||
bootstrap:
|
||||
@npm install
|
||||
@${MAKE} staticsite-build
|
||||
|
||||
|
||||
staticsite-build:
|
||||
@npm run build
|
||||
|
||||
local-serve: staticsite-build
|
||||
@npm run serve
|
||||
|
||||
|
||||
composition-go-brrr: staticsite-build
|
||||
@docker compose up -d
|
||||
|
||||
composition-stop:
|
||||
@docker compose down
|
||||
|
||||
composition-refresh: composition-stop composition-go-brrr
|
||||
21
docker compositions/techradar/aoe/README.md
Normal file
21
docker compositions/techradar/aoe/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Tech radar
|
||||
|
||||
Based upon [AOE's technology radar](https://github.com/AOEpeople/aoe_technology_radar).
|
||||
|
||||
Bootstrap:
|
||||
|
||||
1. Run `npm install`.
|
||||
1. Run `npm run build` to create the initial radar.<br/>
|
||||
This will also create a basic bootstrap of all required files, including `config.json` and `about.md` if they do not
|
||||
exist yet.
|
||||
|
||||
Customization:
|
||||
|
||||
1. Change the `about.md`, `config.json`, `custom.css` files accordingly.
|
||||
1. Create a folder named as a date in the `radar` folder to create a new revision.
|
||||
1. Add markdown files in there for each change. Follow the instructions of the base.
|
||||
|
||||
Serve:
|
||||
|
||||
1. Execute `docker compose up -d`.
|
||||
1. Open your browser at <http://localhost:8080/techradar/>.
|
||||
11
docker compositions/techradar/aoe/about.md
Normal file
11
docker compositions/techradar/aoe/about.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# How to use the Technology Radar
|
||||
|
||||
## Introduction
|
||||
|
||||
Edit this file to your needs to provide an introduction to the technology radar. Explain the purpose
|
||||
of the radar and how it is created. This is a good place to explain the quadrants and rings, too.
|
||||
|
||||
## Contributing to the AOE Technology Radar
|
||||
|
||||
Contributions and source code of the AOE Tech Radar are on
|
||||
GitHub: [AOE Tech Radar on GitHub](https://github.com/AOEpeople/aoe_technology_radar)
|
||||
134
docker compositions/techradar/aoe/config.json
Normal file
134
docker compositions/techradar/aoe/config.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"basePath": "/techradar",
|
||||
"baseUrl": "",
|
||||
"logoFile": "logo.svg",
|
||||
"toggles": {
|
||||
"showChart": true,
|
||||
"showTagFilter": true,
|
||||
"showQuadrantList": true,
|
||||
"showEmptyRings": false
|
||||
},
|
||||
"sections": [
|
||||
"radar",
|
||||
"tags",
|
||||
"list"
|
||||
],
|
||||
"colors": {
|
||||
"foreground": "#fcf2e6",
|
||||
"background": "#113521",
|
||||
"highlight": "#d4a373",
|
||||
"content": "#fff",
|
||||
"text": "#575757",
|
||||
"link": "#bc6c25",
|
||||
"border": "rgba(255, 255, 255, 0.1)",
|
||||
"tag": "rgba(255, 255, 255, 0.1)"
|
||||
},
|
||||
"quadrants": [
|
||||
{
|
||||
"id": "languages-and-frameworks",
|
||||
"title": "Languages & Frameworks",
|
||||
"description": "A selection of programming languages, alongside essential frameworks for building a variety of custom software.",
|
||||
"color": "#a3b18a"
|
||||
},
|
||||
{
|
||||
"id": "methods-and-patterns",
|
||||
"title": "Methods & Patterns",
|
||||
"description": "Key software development methods and design patterns, covering everything from continuous integration and testing to architecture.",
|
||||
"color": "#588157"
|
||||
},
|
||||
{
|
||||
"id": "platforms-and-operations",
|
||||
"title": "Platforms & Operations",
|
||||
"description": "Technologies and tools for software and infrastructure operations, including platforms and services for managing and scaling applications.",
|
||||
"color": "#3f633e"
|
||||
},
|
||||
{
|
||||
"id": "tools",
|
||||
"title": "Tools",
|
||||
"description": "A range of software tools, from simple productivity enhancers to comprehensive project solutions, catering to various project needs.",
|
||||
"color": "#40713f"
|
||||
}
|
||||
],
|
||||
"rings": [
|
||||
{
|
||||
"id": "adopt",
|
||||
"title": "Adopt",
|
||||
"description": "",
|
||||
"color": "#588157",
|
||||
"radius": 0.5,
|
||||
"strokeWidth": 5
|
||||
},
|
||||
{
|
||||
"id": "trial",
|
||||
"title": "Trial",
|
||||
"description": "",
|
||||
"color": "#457b9d",
|
||||
"radius": 0.69,
|
||||
"strokeWidth": 3
|
||||
},
|
||||
{
|
||||
"id": "assess",
|
||||
"title": "Assess",
|
||||
"description": "",
|
||||
"color": "#bc6c25",
|
||||
"radius": 0.85,
|
||||
"strokeWidth": 2
|
||||
},
|
||||
{
|
||||
"id": "hold",
|
||||
"title": "Hold",
|
||||
"description": "",
|
||||
"color": "#d62828",
|
||||
"radius": 1,
|
||||
"strokeWidth": 0.75
|
||||
}
|
||||
],
|
||||
"flags": {
|
||||
"new": {
|
||||
"color": "#f1235a",
|
||||
"title": "New",
|
||||
"titleShort": "N",
|
||||
"description": "New in this version"
|
||||
},
|
||||
"changed": {
|
||||
"color": "#40a7d1",
|
||||
"title": "Changed",
|
||||
"titleShort": "C",
|
||||
"description": "Recently changed"
|
||||
},
|
||||
"default": {
|
||||
"description": "Unchanged"
|
||||
}
|
||||
},
|
||||
"chart": {
|
||||
"size": 800,
|
||||
"blipSize": 12
|
||||
},
|
||||
"social": [
|
||||
{
|
||||
"href": "https://github.com/mcereda",
|
||||
"icon": "github"
|
||||
},
|
||||
{
|
||||
"href": "https://gitlab.com/mckie",
|
||||
"icon": "gitlab"
|
||||
}
|
||||
],
|
||||
"imprint": "",
|
||||
"labels": {
|
||||
"title": "Technology Radar",
|
||||
"imprint": "Legal Information",
|
||||
"quadrant": "Quadrant",
|
||||
"quadrantOverview": "Quadrant Overview",
|
||||
"zoomIn": "Zoom in",
|
||||
"filterByTag": "Filter by Tag",
|
||||
"footer": "The technology radar is using a project by AOE GmbH. Feel free to build your own radar based on their open source project.",
|
||||
"notUpdated": "This item was not updated in last three versions of the Radar. Should it have appeared in one of the more recent editions, there is a good chance it remains pertinent. However, if the item dates back further, its relevance may have diminished and our current evaluation could vary. Regrettably, my capacity to consistently revisit items from past Radar editions is limited.",
|
||||
"notFound": "404 - Page not found",
|
||||
"pageAbout": "About",
|
||||
"pageOverview": "Technologies Overview",
|
||||
"pageSearch": "Search",
|
||||
"searchPlaceholder": "What are you looking for?",
|
||||
"metaDescription": ""
|
||||
}
|
||||
}
|
||||
6
docker compositions/techradar/aoe/custom.css
Normal file
6
docker compositions/techradar/aoe/custom.css
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Use this file to optionally override global css styles and use with caution. */
|
||||
/* See README.md for hints and examples: https://github.com/AOEpeople/aoe_technology_radar/ */
|
||||
|
||||
[class^="Layout_content"] span {
|
||||
font-size: small;
|
||||
}
|
||||
13
docker compositions/techradar/aoe/docker-compose.yml
Normal file
13
docker compositions/techradar/aoe/docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
version: '3'
|
||||
services:
|
||||
radar:
|
||||
container_name: radar
|
||||
image: nginxinc/nginx-unprivileged:1.25.5-bookworm-perl
|
||||
volumes:
|
||||
- ${PWD}/build:/usr/share/nginx/html/techradar:ro
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
NGINX_HOST: localhost
|
||||
NGINX_PORT: '8080'
|
||||
12
docker compositions/techradar/aoe/package.json
Normal file
12
docker compositions/techradar/aoe/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "techradar",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "techradar build",
|
||||
"serve": "techradar serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"aoe_technology_radar": "^4"
|
||||
}
|
||||
}
|
||||
BIN
docker compositions/techradar/aoe/public/favicon.ico
Normal file
BIN
docker compositions/techradar/aoe/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1
docker compositions/techradar/aoe/public/logo.svg
Normal file
1
docker compositions/techradar/aoe/public/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 149.6 64.73"><path d="M25.87,0h-1.77v7.24C10.65,8.15,0,19.35,0,33.02s11.62,25.87,25.87,25.87,24.87-10.65,25.79-24.1h7.24v-1.77C58.89,14.81,44.09,0,25.87,0ZM25.87,55.32c-12.31,0-22.32-10.01-22.32-22.32S12.59,11.67,24.07,10.76v24.01h24.01c-.92,11.48-10.54,20.52-22.24,20.52h0l.03.03ZM51.74,31.22h-24.1V3.63c14.81.89,26.7,12.78,27.59,27.62h-3.52l.03-.03Z" fill="#fff" fill-rule="evenodd" stroke-width="0"/><path d="M78.09,10.41h-6.09v16.5h-1.5V10.41h-6.08v-1.27h13.67v1.27Z" fill="#fff" stroke-width="0"/><path d="M90.78,18.39h-8.31v7.25h9.56v1.27h-11.06V9.14h11v1.27h-9.5v6.71h8.31v1.27Z" fill="#fff" stroke-width="0"/><path d="M107.77,21.37c-.2,1.87-.87,3.3-2.01,4.3-1.13.99-2.65,1.49-4.53,1.49-1.32,0-2.48-.33-3.5-.99-1.01-.66-1.8-1.59-2.35-2.8-.55-1.21-.83-2.59-.84-4.14v-2.31c0-1.58.28-2.98.83-4.2.55-1.22,1.35-2.16,2.39-2.83,1.04-.66,2.23-1,3.58-1,1.9,0,3.41.51,4.51,1.54,1.1,1.03,1.74,2.45,1.92,4.26h-1.51c-.38-3.02-2.01-4.53-4.92-4.53-1.61,0-2.9.6-3.85,1.81s-1.43,2.87-1.43,5v2.17c0,2.05.46,3.69,1.4,4.91.93,1.22,2.19,1.83,3.78,1.83s2.75-.38,3.55-1.13c.8-.75,1.29-1.88,1.48-3.39h1.51Z" fill="#fff" stroke-width="0"/><path d="M124.59,26.91h-1.51v-8.52h-10.16v8.52h-1.5V9.14h1.5v7.98h10.16v-7.98h1.51v17.77Z" fill="#fff" stroke-width="0"/><path d="M71.73,41.62h-2.32v6.29h-4.28v-17.77h6.99c2.11,0,3.76.47,4.94,1.4,1.19.93,1.78,2.26,1.78,3.96,0,1.24-.25,2.26-.75,3.07-.5.81-1.28,1.47-2.35,1.98l3.71,7.18v.18h-4.59l-3.14-6.29ZM69.41,38.33h2.71c.81,0,1.43-.21,1.84-.64.41-.43.62-1.03.62-1.79s-.21-1.37-.62-1.81-1.03-.65-1.83-.65h-2.71v4.9Z" fill="#fff" stroke-width="0"/><path d="M91.53,44.59h-5.87l-1.03,3.32h-4.58l6.52-17.77h4.03l6.57,17.77h-4.6l-1.04-3.32ZM86.69,41.28h3.82l-1.92-6.16-1.9,6.16Z" fill="#fff" stroke-width="0"/><path d="M98.47,47.91v-17.77h5.73c1.57,0,2.98.36,4.24,1.07,1.25.71,2.23,1.72,2.94,3.01s1.06,2.75,1.07,4.36v.82c0,1.63-.34,3.09-1.03,4.38-.69,1.29-1.66,2.3-2.91,3.03-1.25.73-2.64,1.1-4.18,1.1h-5.85ZM102.75,33.44v11.17h1.49c1.23,0,2.17-.44,2.83-1.31.66-.87.99-2.17.99-3.9v-.77c0-1.72-.33-3.01-.99-3.88-.66-.87-1.62-1.31-2.88-1.31h-1.44Z" fill="#fff" stroke-width="0"/><path d="M124.47,44.59h-5.87l-1.03,3.32h-4.58l6.52-17.77h4.03l6.57,17.77h-4.6l-1.04-3.32ZM119.62,41.28h3.82l-1.92-6.16-1.9,6.16Z" fill="#fff" stroke-width="0"/><path d="M138.01,41.62h-2.32v6.29h-4.28v-17.77h7c2.11,0,3.75.47,4.94,1.4,1.19.93,1.78,2.26,1.78,3.96,0,1.24-.25,2.26-.75,3.07-.5.81-1.28,1.47-2.35,1.98l3.71,7.18v.18h-4.59l-3.14-6.29ZM135.69,38.33h2.71c.81,0,1.43-.21,1.84-.64.41-.43.62-1.03.62-1.79s-.21-1.37-.62-1.81c-.41-.44-1.03-.65-1.83-.65h-2.71v4.9Z" fill="#fff" stroke-width="0"/></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "git"
|
||||
quadrant: tools
|
||||
ring: adopt
|
||||
tags: []
|
||||
---
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "gitea"
|
||||
quadrant: tools
|
||||
ring: assess
|
||||
tags: []
|
||||
---
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "node.js"
|
||||
quadrant: languages-and-frameworks
|
||||
ring: hold
|
||||
tags: [iac]
|
||||
---
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "opentofu"
|
||||
quadrant: platforms-and-operations
|
||||
ring: trial
|
||||
tags: [iac]
|
||||
---
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "pulumi"
|
||||
quadrant: platforms-and-operations
|
||||
ring: adopt
|
||||
tags: [iac]
|
||||
---
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "terraform"
|
||||
quadrant: platforms-and-operations
|
||||
ring: adopt
|
||||
tags: [iac]
|
||||
---
|
||||
13
docker compositions/techradar/zalando/README.md
Normal file
13
docker compositions/techradar/zalando/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Tech radar
|
||||
|
||||
It **is** [Zalando's tech radar], just customized.
|
||||
|
||||
Serves a static page.
|
||||
|
||||
There are **4** quadrants.<br/>
|
||||
Quadrants start from the **bottom right** and go clockwise: `0` is _bottom right_, `1` is _bottom left_, `2` is
|
||||
_top left_, `3` is _top right_.
|
||||
|
||||
Moved: `-1` is _down_, `0` is _stationary_, `1` is _up_.
|
||||
|
||||
[zalando's tech radar]: https://github.com/zalando/tech-radar
|
||||
13
docker compositions/techradar/zalando/docker-compose.yml
Normal file
13
docker compositions/techradar/zalando/docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
version: '3'
|
||||
services:
|
||||
radar:
|
||||
container_name: radar
|
||||
image: nginxinc/nginx-unprivileged:1.25.5-bookworm-perl
|
||||
volumes:
|
||||
- ${PWD}:/usr/share/nginx/html:ro
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
NGINX_HOST: localhost
|
||||
NGINX_PORT: '8080'
|
||||
62
docker compositions/techradar/zalando/index.html
Normal file
62
docker compositions/techradar/zalando/index.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="description"
|
||||
content="Tech Radar: a tool to visualize technology choices, inspire and support Engineering teams at Example to pick the best technologies for new projects">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Tech Radar</title>
|
||||
<link rel="shortcut icon"
|
||||
href="view-source:https://images.squarespace-cdn.com/content/v1/6414395791ffc20447907be9/94d4e41d-9d48-4068-89a1-52f0a7e36890/favicon.ico?format=100w">
|
||||
|
||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||
<script src="radar.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="radar.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<svg id="radar"></svg>
|
||||
|
||||
<script>
|
||||
fetch('./radar.json').then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
radar_visualization({
|
||||
svg_id: "radar",
|
||||
width: 1450,
|
||||
height: 950,
|
||||
colors: {
|
||||
background: "#fff",
|
||||
grid: '#dddde0',
|
||||
inactive: "#ddd"
|
||||
},
|
||||
title: "Tech Radar",
|
||||
date: data.date,
|
||||
quadrants: [
|
||||
{ name: "Data Management" }, // BR, #0
|
||||
{ name: "Datastores" }, // BL, #1
|
||||
{ name: "Languages" }, // TR, #2
|
||||
{ name: "Infrastructure" }, // TL, #3
|
||||
],
|
||||
rings: [
|
||||
{ name: "ADOPT", color: "#5ba300" },
|
||||
{ name: "TRIAL", color: "#009eb0" },
|
||||
{ name: "ASSESS", color: "#c7ba00" },
|
||||
{ name: "HOLD", color: "#e09b96" }
|
||||
],
|
||||
print_layout: true,
|
||||
links_in_new_tabs: true,
|
||||
// zoomed_quadrant: 0,
|
||||
entries: data.entries
|
||||
});
|
||||
}).catch(function (err) {
|
||||
console.log('Error loading config.json', err);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
23
docker compositions/techradar/zalando/radar.css
Normal file
23
docker compositions/techradar/zalando/radar.css
Normal file
@@ -0,0 +1,23 @@
|
||||
body {
|
||||
font-family: 'Source Sans Pro', arial, helvetica, sans-serif;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 25px 50px 0 0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 1400px;
|
||||
margin: 0 50px 0 50px;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 50%;
|
||||
vertical-align: top;
|
||||
padding-right: 60px;
|
||||
}
|
||||
474
docker compositions/techradar/zalando/radar.js
Normal file
474
docker compositions/techradar/zalando/radar.js
Normal file
@@ -0,0 +1,474 @@
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2017-2024 Zalando SE
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
function radar_visualization(config) {
|
||||
|
||||
// custom random number generator, to make random sequence reproducible
|
||||
// source: https://stackoverflow.com/questions/521295
|
||||
var seed = 42;
|
||||
function random() {
|
||||
var x = Math.sin(seed++) * 10000;
|
||||
return x - Math.floor(x);
|
||||
}
|
||||
|
||||
function random_between(min, max) {
|
||||
return min + random() * (max - min);
|
||||
}
|
||||
|
||||
function normal_between(min, max) {
|
||||
return min + (random() + random()) * 0.5 * (max - min);
|
||||
}
|
||||
|
||||
// radial_min / radial_max are multiples of PI
|
||||
const quadrants = [
|
||||
{ radial_min: 0, radial_max: 0.5, factor_x: 1, factor_y: 1 },
|
||||
{ radial_min: 0.5, radial_max: 1, factor_x: -1, factor_y: 1 },
|
||||
{ radial_min: -1, radial_max: -0.5, factor_x: -1, factor_y: -1 },
|
||||
{ radial_min: -0.5, radial_max: 0, factor_x: 1, factor_y: -1 }
|
||||
];
|
||||
|
||||
const rings = [
|
||||
{ radius: 130 },
|
||||
{ radius: 220 },
|
||||
{ radius: 310 },
|
||||
{ radius: 400 }
|
||||
];
|
||||
|
||||
const title_offset =
|
||||
{ x: -675, y: -420 };
|
||||
|
||||
const footer_offset =
|
||||
{ x: -675, y: 420 };
|
||||
|
||||
const legend_offset = [
|
||||
{ x: 450, y: 90 },
|
||||
{ x: -675, y: 90 },
|
||||
{ x: -675, y: -310 },
|
||||
{ x: 450, y: -310 }
|
||||
];
|
||||
|
||||
function polar(cartesian) {
|
||||
var x = cartesian.x;
|
||||
var y = cartesian.y;
|
||||
return {
|
||||
t: Math.atan2(y, x),
|
||||
r: Math.sqrt(x * x + y * y)
|
||||
}
|
||||
}
|
||||
|
||||
function cartesian(polar) {
|
||||
return {
|
||||
x: polar.r * Math.cos(polar.t),
|
||||
y: polar.r * Math.sin(polar.t)
|
||||
}
|
||||
}
|
||||
|
||||
function bounded_interval(value, min, max) {
|
||||
var low = Math.min(min, max);
|
||||
var high = Math.max(min, max);
|
||||
return Math.min(Math.max(value, low), high);
|
||||
}
|
||||
|
||||
function bounded_ring(polar, r_min, r_max) {
|
||||
return {
|
||||
t: polar.t,
|
||||
r: bounded_interval(polar.r, r_min, r_max)
|
||||
}
|
||||
}
|
||||
|
||||
function bounded_box(point, min, max) {
|
||||
return {
|
||||
x: bounded_interval(point.x, min.x, max.x),
|
||||
y: bounded_interval(point.y, min.y, max.y)
|
||||
}
|
||||
}
|
||||
|
||||
function segment(quadrant, ring) {
|
||||
var polar_min = {
|
||||
t: quadrants[quadrant].radial_min * Math.PI,
|
||||
r: ring === 0 ? 30 : rings[ring - 1].radius
|
||||
};
|
||||
var polar_max = {
|
||||
t: quadrants[quadrant].radial_max * Math.PI,
|
||||
r: rings[ring].radius
|
||||
};
|
||||
var cartesian_min = {
|
||||
x: 15 * quadrants[quadrant].factor_x,
|
||||
y: 15 * quadrants[quadrant].factor_y
|
||||
};
|
||||
var cartesian_max = {
|
||||
x: rings[3].radius * quadrants[quadrant].factor_x,
|
||||
y: rings[3].radius * quadrants[quadrant].factor_y
|
||||
};
|
||||
return {
|
||||
clipx: function(d) {
|
||||
var c = bounded_box(d, cartesian_min, cartesian_max);
|
||||
var p = bounded_ring(polar(c), polar_min.r + 15, polar_max.r - 15);
|
||||
d.x = cartesian(p).x; // adjust data too!
|
||||
return d.x;
|
||||
},
|
||||
clipy: function(d) {
|
||||
var c = bounded_box(d, cartesian_min, cartesian_max);
|
||||
var p = bounded_ring(polar(c), polar_min.r + 15, polar_max.r - 15);
|
||||
d.y = cartesian(p).y; // adjust data too!
|
||||
return d.y;
|
||||
},
|
||||
random: function() {
|
||||
return cartesian({
|
||||
t: random_between(polar_min.t, polar_max.t),
|
||||
r: normal_between(polar_min.r, polar_max.r)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// position each entry randomly in its segment
|
||||
for (var i = 0; i < config.entries.length; i++) {
|
||||
var entry = config.entries[i];
|
||||
entry.segment = segment(entry.quadrant, entry.ring);
|
||||
var point = entry.segment.random();
|
||||
entry.x = point.x;
|
||||
entry.y = point.y;
|
||||
entry.color = entry.active || config.print_layout ?
|
||||
config.rings[entry.ring].color : config.colors.inactive;
|
||||
}
|
||||
|
||||
// partition entries according to segments
|
||||
var segmented = new Array(4);
|
||||
for (var quadrant = 0; quadrant < 4; quadrant++) {
|
||||
segmented[quadrant] = new Array(4);
|
||||
for (var ring = 0; ring < 4; ring++) {
|
||||
segmented[quadrant][ring] = [];
|
||||
}
|
||||
}
|
||||
for (var i=0; i<config.entries.length; i++) {
|
||||
var entry = config.entries[i];
|
||||
segmented[entry.quadrant][entry.ring].push(entry);
|
||||
}
|
||||
|
||||
// assign unique sequential id to each entry
|
||||
var id = 1;
|
||||
for (var quadrant of [2,3,1,0]) {
|
||||
for (var ring = 0; ring < 4; ring++) {
|
||||
var entries = segmented[quadrant][ring];
|
||||
entries.sort(function(a,b) { return a.label.localeCompare(b.label); })
|
||||
for (var i=0; i<entries.length; i++) {
|
||||
entries[i].id = "" + id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function translate(x, y) {
|
||||
return "translate(" + x + "," + y + ")";
|
||||
}
|
||||
|
||||
function viewbox(quadrant) {
|
||||
return [
|
||||
Math.max(0, quadrants[quadrant].factor_x * 400) - 420,
|
||||
Math.max(0, quadrants[quadrant].factor_y * 400) - 420,
|
||||
440,
|
||||
440
|
||||
].join(" ");
|
||||
}
|
||||
|
||||
// adjust with config.scale.
|
||||
config.scale = config.scale || 1;
|
||||
var scaled_width = config.width * config.scale;
|
||||
var scaled_height = config.height * config.scale;
|
||||
|
||||
var svg = d3.select("svg#" + config.svg_id)
|
||||
.style("background-color", config.colors.background)
|
||||
.attr("width", scaled_width)
|
||||
.attr("height", scaled_height);
|
||||
|
||||
var radar = svg.append("g");
|
||||
if ("zoomed_quadrant" in config) {
|
||||
svg.attr("viewBox", viewbox(config.zoomed_quadrant));
|
||||
} else {
|
||||
radar.attr("transform", translate(scaled_width / 2, scaled_height / 2).concat(`scale(${config.scale})`));
|
||||
}
|
||||
|
||||
var grid = radar.append("g");
|
||||
|
||||
// draw grid lines
|
||||
grid.append("line")
|
||||
.attr("x1", 0).attr("y1", -400)
|
||||
.attr("x2", 0).attr("y2", 400)
|
||||
.style("stroke", config.colors.grid)
|
||||
.style("stroke-width", 1);
|
||||
grid.append("line")
|
||||
.attr("x1", -400).attr("y1", 0)
|
||||
.attr("x2", 400).attr("y2", 0)
|
||||
.style("stroke", config.colors.grid)
|
||||
.style("stroke-width", 1);
|
||||
|
||||
// background color. Usage `.attr("filter", "url(#solid)")`
|
||||
// SOURCE: https://stackoverflow.com/a/31013492/2609980
|
||||
var defs = grid.append("defs");
|
||||
var filter = defs.append("filter")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", 1)
|
||||
.attr("height", 1)
|
||||
.attr("id", "solid");
|
||||
filter.append("feFlood")
|
||||
.attr("flood-color", "rgb(0, 0, 0, 0.8)");
|
||||
filter.append("feComposite")
|
||||
.attr("in", "SourceGraphic");
|
||||
|
||||
// draw rings
|
||||
for (var i = 0; i < rings.length; i++) {
|
||||
grid.append("circle")
|
||||
.attr("cx", 0)
|
||||
.attr("cy", 0)
|
||||
.attr("r", rings[i].radius)
|
||||
.style("fill", "none")
|
||||
.style("stroke", config.colors.grid)
|
||||
.style("stroke-width", 1);
|
||||
if (config.print_layout) {
|
||||
grid.append("text")
|
||||
.text(config.rings[i].name)
|
||||
.attr("y", -rings[i].radius + 62)
|
||||
.attr("text-anchor", "middle")
|
||||
.style("fill", config.rings[i].color)
|
||||
.style("opacity", 0.35)
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "42px")
|
||||
.style("font-weight", "bold")
|
||||
.style("pointer-events", "none")
|
||||
.style("user-select", "none");
|
||||
}
|
||||
}
|
||||
|
||||
function legend_transform(quadrant, ring, index=null) {
|
||||
var dx = ring < 2 ? 0 : 140;
|
||||
var dy = (index == null ? -16 : index * 12);
|
||||
if (ring % 2 === 1) {
|
||||
dy = dy + 36 + segmented[quadrant][ring-1].length * 12;
|
||||
}
|
||||
return translate(
|
||||
legend_offset[quadrant].x + dx,
|
||||
legend_offset[quadrant].y + dy
|
||||
);
|
||||
}
|
||||
|
||||
// draw title and legend (only in print layout)
|
||||
if (config.print_layout) {
|
||||
|
||||
// title
|
||||
radar.append("text")
|
||||
.attr("transform", translate(title_offset.x, title_offset.y))
|
||||
.text(config.title)
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "30")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
// date
|
||||
radar
|
||||
.append("text")
|
||||
.attr("transform", translate(title_offset.x, title_offset.y + 20))
|
||||
.text(config.date || "")
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "14")
|
||||
.style("fill", "#999")
|
||||
|
||||
// footer
|
||||
radar.append("text")
|
||||
.attr("transform", translate(footer_offset.x, footer_offset.y))
|
||||
.text("▲ moved up ▼ moved down")
|
||||
.attr("xml:space", "preserve")
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "10px");
|
||||
|
||||
// legend
|
||||
var legend = radar.append("g");
|
||||
for (var quadrant = 0; quadrant < 4; quadrant++) {
|
||||
legend.append("text")
|
||||
.attr("transform", translate(
|
||||
legend_offset[quadrant].x,
|
||||
legend_offset[quadrant].y - 45
|
||||
))
|
||||
.text(config.quadrants[quadrant].name)
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "18px")
|
||||
.style("font-weight", "bold");
|
||||
for (var ring = 0; ring < 4; ring++) {
|
||||
legend.append("text")
|
||||
.attr("transform", legend_transform(quadrant, ring))
|
||||
.text(config.rings[ring].name)
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "12px")
|
||||
.style("font-weight", "bold")
|
||||
.style("fill", config.rings[ring].color);
|
||||
legend.selectAll(".legend" + quadrant + ring)
|
||||
.data(segmented[quadrant][ring])
|
||||
.enter()
|
||||
.append("a")
|
||||
.attr("href", function (d, i) {
|
||||
return d.link ? d.link : "#"; // stay on same page if no link was provided
|
||||
})
|
||||
// Add a target if (and only if) there is a link and we want new tabs
|
||||
.attr("target", function (d, i) {
|
||||
return (d.link && config.links_in_new_tabs) ? "_blank" : null;
|
||||
})
|
||||
.append("text")
|
||||
.attr("transform", function(d, i) { return legend_transform(quadrant, ring, i); })
|
||||
.attr("class", "legend" + quadrant + ring)
|
||||
.attr("id", function(d, i) { return "legendItem" + d.id; })
|
||||
.text(function(d, i) { return d.id + ". " + d.label; })
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", "11px")
|
||||
.on("mouseover", function(d) { showBubble(d); highlightLegendItem(d); })
|
||||
.on("mouseout", function(d) { hideBubble(d); unhighlightLegendItem(d); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// layer for entries
|
||||
var rink = radar.append("g")
|
||||
.attr("id", "rink");
|
||||
|
||||
// rollover bubble (on top of everything else)
|
||||
var bubble = radar.append("g")
|
||||
.attr("id", "bubble")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.style("opacity", 0)
|
||||
.style("pointer-events", "none")
|
||||
.style("user-select", "none");
|
||||
bubble.append("rect")
|
||||
.attr("rx", 4)
|
||||
.attr("ry", 4)
|
||||
.style("fill", "#333");
|
||||
bubble.append("text")
|
||||
.style("font-family", "sans-serif")
|
||||
.style("font-size", "10px")
|
||||
.style("fill", "#fff");
|
||||
bubble.append("path")
|
||||
.attr("d", "M 0,0 10,0 5,8 z")
|
||||
.style("fill", "#333");
|
||||
|
||||
function showBubble(d) {
|
||||
if (d.active || config.print_layout) {
|
||||
var tooltip = d3.select("#bubble text")
|
||||
.text(d.label);
|
||||
var bbox = tooltip.node().getBBox();
|
||||
d3.select("#bubble")
|
||||
.attr("transform", translate(d.x - bbox.width / 2, d.y - 16))
|
||||
.style("opacity", 0.8);
|
||||
d3.select("#bubble rect")
|
||||
.attr("x", -5)
|
||||
.attr("y", -bbox.height)
|
||||
.attr("width", bbox.width + 10)
|
||||
.attr("height", bbox.height + 4);
|
||||
d3.select("#bubble path")
|
||||
.attr("transform", translate(bbox.width / 2 - 5, 3));
|
||||
}
|
||||
}
|
||||
|
||||
function hideBubble(d) {
|
||||
var bubble = d3.select("#bubble")
|
||||
.attr("transform", translate(0,0))
|
||||
.style("opacity", 0);
|
||||
}
|
||||
|
||||
function highlightLegendItem(d) {
|
||||
var legendItem = document.getElementById("legendItem" + d.id);
|
||||
legendItem.setAttribute("filter", "url(#solid)");
|
||||
legendItem.setAttribute("fill", "white");
|
||||
}
|
||||
|
||||
function unhighlightLegendItem(d) {
|
||||
var legendItem = document.getElementById("legendItem" + d.id);
|
||||
legendItem.removeAttribute("filter");
|
||||
legendItem.removeAttribute("fill");
|
||||
}
|
||||
|
||||
// draw blips on radar
|
||||
var blips = rink.selectAll(".blip")
|
||||
.data(config.entries)
|
||||
.enter()
|
||||
.append("g")
|
||||
.attr("class", "blip")
|
||||
.attr("transform", function(d, i) { return legend_transform(d.quadrant, d.ring, i); })
|
||||
.on("mouseover", function(d) { showBubble(d); highlightLegendItem(d); })
|
||||
.on("mouseout", function(d) { hideBubble(d); unhighlightLegendItem(d); });
|
||||
|
||||
// configure each blip
|
||||
blips.each(function(d) {
|
||||
var blip = d3.select(this);
|
||||
|
||||
// blip link
|
||||
if (d.active && Object.prototype.hasOwnProperty.call(d, "link") && d.link) {
|
||||
blip = blip.append("a")
|
||||
.attr("xlink:href", d.link);
|
||||
|
||||
if (config.links_in_new_tabs) {
|
||||
blip.attr("target", "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
// blip shape
|
||||
if (d.moved > 0) {
|
||||
blip.append("path")
|
||||
.attr("d", "M -11,5 11,5 0,-13 z") // triangle pointing up
|
||||
.style("fill", d.color);
|
||||
} else if (d.moved < 0) {
|
||||
blip.append("path")
|
||||
.attr("d", "M -11,-5 11,-5 0,13 z") // triangle pointing down
|
||||
.style("fill", d.color);
|
||||
} else {
|
||||
blip.append("circle")
|
||||
.attr("r", 9)
|
||||
.attr("fill", d.color);
|
||||
}
|
||||
|
||||
// blip text
|
||||
if (d.active || config.print_layout) {
|
||||
var blip_text = config.print_layout ? d.id : d.label.match(/[a-z]/i);
|
||||
blip.append("text")
|
||||
.text(blip_text)
|
||||
.attr("y", 3)
|
||||
.attr("text-anchor", "middle")
|
||||
.style("fill", "#fff")
|
||||
.style("font-family", "Arial, Helvetica")
|
||||
.style("font-size", function(d) { return blip_text.length > 2 ? "8px" : "9px"; })
|
||||
.style("pointer-events", "none")
|
||||
.style("user-select", "none");
|
||||
}
|
||||
});
|
||||
|
||||
// make sure that blips stay inside their segment
|
||||
function ticked() {
|
||||
blips.attr("transform", function(d) {
|
||||
return translate(d.segment.clipx(d), d.segment.clipy(d));
|
||||
})
|
||||
}
|
||||
|
||||
// distribute blips, while avoiding collisions
|
||||
d3.forceSimulation()
|
||||
.nodes(config.entries)
|
||||
.velocityDecay(0.19) // magic number (found by experimentation)
|
||||
.force("collision", d3.forceCollide().radius(12).strength(0.85))
|
||||
.on("tick", ticked);
|
||||
}
|
||||
41
docker compositions/techradar/zalando/radar.json
Normal file
41
docker compositions/techradar/zalando/radar.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"date": "2024.04.25",
|
||||
"entries": [
|
||||
{
|
||||
"quadrant": 2,
|
||||
"ring": 0,
|
||||
"label": "node.js",
|
||||
"active": true,
|
||||
"moved": 0
|
||||
},
|
||||
{
|
||||
"quadrant": 3,
|
||||
"ring": 0,
|
||||
"label": "pulumi",
|
||||
"link": "https://www.pulumi.com/",
|
||||
"active": true,
|
||||
"moved": 0
|
||||
},
|
||||
{
|
||||
"quadrant": 2,
|
||||
"ring": 1,
|
||||
"label": "python",
|
||||
"active": true,
|
||||
"moved": 0
|
||||
},
|
||||
{
|
||||
"quadrant": 2,
|
||||
"ring": 2,
|
||||
"label": "golang",
|
||||
"active": true,
|
||||
"moved": -1
|
||||
},
|
||||
{
|
||||
"quadrant": 1,
|
||||
"ring": 3,
|
||||
"label": "gitea",
|
||||
"active": false,
|
||||
"moved": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user