feat: add configurable edit link next to revision
This commit is contained in:
committed by
Mathias Schopmans
parent
25a714e9f6
commit
b7efe8060f
23
README.md
23
README.md
@@ -59,17 +59,18 @@ The ideal logo is 150px x 60px. For reference have a look at [public/logo.svg](.
|
|||||||
|
|
||||||
Copy the [`config.json`](./data/config.json) next to the `package.json` and adapt it to your needs.
|
Copy the [`config.json`](./data/config.json) next to the `package.json` and adapt it to your needs.
|
||||||
|
|
||||||
| Attribute | Description |
|
| Attribute | Description |
|
||||||
| --------- | --------------------------------------------------------------------------------- |
|
| --------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| basePath | Set if hosting under a sub-path, otherwise set it to `/`. Default is `/techradar` |
|
| basePath | Set if hosting under a sub-path, otherwise set it to `/`. Default is `/techradar` |
|
||||||
| colors | A map of colors for the radar. Can be any valid CSS color value |
|
| colors | A map of colors for the radar. Can be any valid CSS color value |
|
||||||
| quadrants | Config of the 4 quadrants of the radar. See config below. |
|
| quadrants | Config of the 4 quadrants of the radar. See config below. |
|
||||||
| rings | Config of the rings of the radar. See config below. |
|
| rings | Config of the rings of the radar. See config below. |
|
||||||
| flags | Config of the flags of the radar. See config below |
|
| flags | Config of the flags of the radar. See config below |
|
||||||
| chart | If you hava a lot of items, you can increase the `size` to scale down the radar |
|
| chart | If you hava a lot of items, you can increase the `size` to scale down the radar |
|
||||||
| social | Social links in the footer. See config below |
|
| social | Social links in the footer. See config below |
|
||||||
| imprint | URL to the legal information |
|
| imprint | URL to the legal information |
|
||||||
| labels | Configure the labels to change the texts and labels of the radar |
|
| labels | Configure the labels to change the texts and labels of the radar |
|
||||||
|
| editUrl | (optional) If set, an edit button will be shown next to the revision.<br/> You can use placeholders for `{id}` and `{release}` |
|
||||||
|
|
||||||
#### `config.quadrants`
|
#### `config.quadrants`
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"basePath": "/techradar",
|
"basePath": "/techradar",
|
||||||
|
"editUrl": "https://github.dev/AOEpeople/techradar/blob/main/radar/{release}/{id}.md",
|
||||||
"colors": {
|
"colors": {
|
||||||
"foreground": "#fcf2e6",
|
"foreground": "#fcf2e6",
|
||||||
"background": "#113521",
|
"background": "#113521",
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "aoe_technology_radar",
|
"name": "aoe_technology_radar",
|
||||||
"version": "4.0.0-alpha.2",
|
"version": "4.0.0-alpha.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "aoe_technology_radar",
|
"name": "aoe_technology_radar",
|
||||||
"version": "4.0.0-alpha.2",
|
"version": "4.0.0-alpha.5",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"techradar": "bin/techradar.sh"
|
"techradar": "bin/techradar.sh"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aoe_technology_radar",
|
"name": "aoe_technology_radar",
|
||||||
"version": "4.0.0-alpha.4",
|
"version": "4.0.0-alpha.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"techradar": "./bin/techradar.sh"
|
"techradar": "./bin/techradar.sh"
|
||||||
|
|||||||
@@ -9,10 +9,27 @@
|
|||||||
margin: 0 30px 0 0;
|
margin: 0 30px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editLink {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
display: block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
.revision {
|
.revision {
|
||||||
padding: 30px 0 15px 35px;
|
padding: 30px 0 15px 35px;
|
||||||
margin-left: 5px;
|
margin-left: 20px;
|
||||||
border-left: 1px solid var(--border);
|
border-left: 1px solid var(--border);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.editLink {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.release {
|
.release {
|
||||||
@@ -31,7 +48,7 @@
|
|||||||
margin: -15px 0 0 -60px;
|
margin: -15px 0 0 -60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.notMaintainedIcon {
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
@@ -44,6 +61,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
position: relative;
|
||||||
background: var(--content);
|
background: var(--content);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import styles from "./ItemDetail.module.css";
|
import styles from "./ItemDetail.module.css";
|
||||||
|
|
||||||
import { RingBadge } from "@/components/Badge/Badge";
|
import { RingBadge } from "@/components/Badge/Badge";
|
||||||
import Attention from "@/components/Icons/Attention";
|
import { Attention, Edit } from "@/components/Icons";
|
||||||
import { Tag } from "@/components/Tags/Tags";
|
import { Tag } from "@/components/Tags/Tags";
|
||||||
import { getLabel, getReleases } from "@/lib/data";
|
import { getEditUrl, getLabel, getReleases } from "@/lib/data";
|
||||||
import { Item } from "@/lib/types";
|
import { Item } from "@/lib/types";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
@@ -31,14 +31,19 @@ export function ItemDetail({ item }: ItemProps) {
|
|||||||
{notMaintainedText && isNotMaintained(item.release) && (
|
{notMaintainedText && isNotMaintained(item.release) && (
|
||||||
<div className={cn(styles.revision, styles.hint)}>
|
<div className={cn(styles.revision, styles.hint)}>
|
||||||
<span className={styles.release}>
|
<span className={styles.release}>
|
||||||
<Attention className={styles.icon} />
|
<Attention className={styles.notMaintainedIcon} />
|
||||||
</span>
|
</span>
|
||||||
<div className={styles.content}>{notMaintainedText}</div>
|
<div className={styles.content}>{notMaintainedText}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Revision release={item.release} ring={item.ring} body={item.body} />
|
<Revision
|
||||||
|
id={item.id}
|
||||||
|
release={item.release}
|
||||||
|
ring={item.ring}
|
||||||
|
body={item.body}
|
||||||
|
/>
|
||||||
{item.revisions?.map((revision, index) => (
|
{item.revisions?.map((revision, index) => (
|
||||||
<Revision key={index} {...revision} />
|
<Revision key={index} id={item.id} {...revision} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -46,13 +51,15 @@ export function ItemDetail({ item }: ItemProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RevisionProps {
|
interface RevisionProps {
|
||||||
|
id: string;
|
||||||
release: string;
|
release: string;
|
||||||
ring: string;
|
ring: string;
|
||||||
body?: string;
|
body?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Revision({ release, ring, body }: RevisionProps) {
|
function Revision({ id, release, ring, body }: RevisionProps) {
|
||||||
const date = new Date(release);
|
const date = new Date(release);
|
||||||
|
const editLink = getEditUrl({ id, release });
|
||||||
const formattedDate = date.toLocaleDateString("en-US", {
|
const formattedDate = date.toLocaleDateString("en-US", {
|
||||||
month: "short",
|
month: "short",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
@@ -65,6 +72,11 @@ function Revision({ release, ring, body }: RevisionProps) {
|
|||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<RingBadge className={styles.ring} ring={ring} size="large" />
|
<RingBadge className={styles.ring} ring={ring} size="large" />
|
||||||
{body ? <div dangerouslySetInnerHTML={{ __html: body }} /> : null}
|
{body ? <div dangerouslySetInnerHTML={{ __html: body }} /> : null}
|
||||||
|
{editLink && (
|
||||||
|
<a href={editLink} target="_blank" className={styles.editLink}>
|
||||||
|
<Edit />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
6
src/icons/edit.svg
Normal file
6
src/icons/edit.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m18.988 2.012 3 3L19.701 7.3l-3-3zM8 16h3l7.287-7.287-3-3L8 13z"/>
|
||||||
|
<path
|
||||||
|
d="M19 19H8.158c-.026 0-.053.01-.079.01-.033 0-.066-.009-.1-.01H5V5h6.847l2-2H5c-1.103 0-2 .896-2 2v14c0 1.104.897 2 2 2h14a2 2 0 0 0 2-2v-8.668l-2 2V19z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 360 B |
@@ -1,6 +1,7 @@
|
|||||||
import config from "../../data/config.json";
|
import config from "../../data/config.json";
|
||||||
import data from "../../data/data.json";
|
import data from "../../data/data.json";
|
||||||
|
|
||||||
|
import { format } from "@/lib/format";
|
||||||
import { Flag, Item, Quadrant, Ring } from "@/lib/types";
|
import { Flag, Item, Quadrant, Ring } from "@/lib/types";
|
||||||
|
|
||||||
export function getLabel(key: keyof typeof config.labels) {
|
export function getLabel(key: keyof typeof config.labels) {
|
||||||
@@ -47,6 +48,11 @@ export function getTags(): string[] {
|
|||||||
return data.tags;
|
return data.tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getEditUrl(props: { id: string; release: string }) {
|
||||||
|
if (!config.editUrl) return "";
|
||||||
|
return format(config.editUrl, props);
|
||||||
|
}
|
||||||
|
|
||||||
export function getQuadrants(): Quadrant[] {
|
export function getQuadrants(): Quadrant[] {
|
||||||
return config.quadrants.map((q, i) => ({ ...q, position: i + 1 }));
|
return config.quadrants.map((q, i) => ({ ...q, position: i + 1 }));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import { getAppName } from "@/lib/data";
|
import { getAppName } from "@/lib/data";
|
||||||
|
|
||||||
|
// Replaces placeholders in a string with values from a context object
|
||||||
|
// e.g. format("Hello {name}.", {name: "World"}) => "Hello World."
|
||||||
|
export function format(text: string, context: Record<string, any>): string {
|
||||||
|
return text.replace(/{(\w+)}/g, (match, key) => {
|
||||||
|
return context[key] || match;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Format the title of the page
|
// Format the title of the page
|
||||||
export function formatTitle(...title: string[]): string {
|
export function formatTitle(...title: string[]): string {
|
||||||
return [...title, getAppName()].join(" | ");
|
return [...title, getAppName()].join(" | ");
|
||||||
|
|||||||
Reference in New Issue
Block a user