* Error theme Based on Design * Update src/common/utils.js Co-authored-by: Alexandr Garbuzov <qwerty541zxc@gmail.com> * Update src/common/utils.js Co-authored-by: Alexandr Garbuzov <qwerty541zxc@gmail.com> --------- Co-authored-by: Alexandr Garbuzov <qwerty541zxc@gmail.com>
This commit is contained in:
1 parent
db921818be
commit
9c6eb22862
6 files changed
+183
-67
No files matched your search
+18
-2
@@ -27,7 +27,15 @@ export default async (req, res) => {
|
|||||||
res.setHeader("Content-Type", "image/svg+xml");
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
|
||||||
if (locale && !isLocaleAvailable(locale)) {
|
if (locale && !isLocaleAvailable(locale)) {
|
||||||
return res.send(renderError("Something went wrong", "Language not found"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "Language not found", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -83,6 +91,14 @@ export default async (req, res) => {
|
|||||||
CONSTANTS.ERROR_CACHE_SECONDS
|
CONSTANTS.ERROR_CACHE_SECONDS
|
||||||
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||||
); // Use lower cache period for errors.
|
); // Use lower cache period for errors.
|
||||||
return res.send(renderError(err.message, err.secondaryMessage));
|
return res.send(
|
||||||
|
renderError(err.message, err.secondaryMessage, {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+27
-3
@@ -42,11 +42,27 @@ export default async (req, res) => {
|
|||||||
res.setHeader("Content-Type", "image/svg+xml");
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
|
||||||
if (blacklist.includes(username)) {
|
if (blacklist.includes(username)) {
|
||||||
return res.send(renderError("Something went wrong"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locale && !isLocaleAvailable(locale)) {
|
if (locale && !isLocaleAvailable(locale)) {
|
||||||
return res.send(renderError("Something went wrong", "Language not found"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "Language not found", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -111,6 +127,14 @@ export default async (req, res) => {
|
|||||||
CONSTANTS.ERROR_CACHE_SECONDS
|
CONSTANTS.ERROR_CACHE_SECONDS
|
||||||
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||||
); // Use lower cache period for errors.
|
); // Use lower cache period for errors.
|
||||||
return res.send(renderError(err.message, err.secondaryMessage));
|
return res.send(
|
||||||
|
renderError(err.message, err.secondaryMessage, {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+27
-3
@@ -29,11 +29,27 @@ export default async (req, res) => {
|
|||||||
res.setHeader("Content-Type", "image/svg+xml");
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
|
||||||
if (blacklist.includes(username)) {
|
if (blacklist.includes(username)) {
|
||||||
return res.send(renderError("Something went wrong"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locale && !isLocaleAvailable(locale)) {
|
if (locale && !isLocaleAvailable(locale)) {
|
||||||
return res.send(renderError("Something went wrong", "Language not found"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "Language not found", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -89,6 +105,14 @@ export default async (req, res) => {
|
|||||||
CONSTANTS.ERROR_CACHE_SECONDS
|
CONSTANTS.ERROR_CACHE_SECONDS
|
||||||
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||||
); // Use lower cache period for errors.
|
); // Use lower cache period for errors.
|
||||||
return res.send(renderError(err.message, err.secondaryMessage));
|
return res.send(
|
||||||
|
renderError(err.message, err.secondaryMessage, {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+18
-2
@@ -37,7 +37,15 @@ export default async (req, res) => {
|
|||||||
res.setHeader("Content-Type", "image/svg+xml");
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
|
||||||
if (blacklist.includes(username)) {
|
if (blacklist.includes(username)) {
|
||||||
return res.send(renderError("Something went wrong"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locale && !isLocaleAvailable(locale)) {
|
if (locale && !isLocaleAvailable(locale)) {
|
||||||
@@ -105,6 +113,14 @@ export default async (req, res) => {
|
|||||||
CONSTANTS.ERROR_CACHE_SECONDS
|
CONSTANTS.ERROR_CACHE_SECONDS
|
||||||
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||||
); // Use lower cache period for errors.
|
); // Use lower cache period for errors.
|
||||||
return res.send(renderError(err.message, err.secondaryMessage));
|
return res.send(
|
||||||
|
renderError(err.message, err.secondaryMessage, {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+18
-2
@@ -35,7 +35,15 @@ export default async (req, res) => {
|
|||||||
res.setHeader("Content-Type", "image/svg+xml");
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
|
||||||
if (locale && !isLocaleAvailable(locale)) {
|
if (locale && !isLocaleAvailable(locale)) {
|
||||||
return res.send(renderError("Something went wrong", "Language not found"));
|
return res.send(
|
||||||
|
renderError("Something went wrong", "Language not found", {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -84,6 +92,14 @@ export default async (req, res) => {
|
|||||||
CONSTANTS.ERROR_CACHE_SECONDS
|
CONSTANTS.ERROR_CACHE_SECONDS
|
||||||
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||||
); // Use lower cache period for errors.
|
); // Use lower cache period for errors.
|
||||||
return res.send(renderError(err.message, err.secondaryMessage));
|
return res.send(
|
||||||
|
renderError(err.message, err.secondaryMessage, {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+75
-55
@@ -39,61 +39,6 @@ class CustomError extends Error {
|
|||||||
static WAKATIME_ERROR = "WAKATIME_ERROR";
|
static WAKATIME_ERROR = "WAKATIME_ERROR";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Script parameters.
|
|
||||||
const ERROR_CARD_LENGTH = 576.5;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode string as HTML.
|
|
||||||
*
|
|
||||||
* @see https://stackoverflow.com/a/48073476/10629172
|
|
||||||
*
|
|
||||||
* @param {string} str String to encode.
|
|
||||||
* @returns {string} Encoded string.
|
|
||||||
*/
|
|
||||||
const encodeHTML = (str) => {
|
|
||||||
return str
|
|
||||||
.replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
|
|
||||||
return "&#" + i.charCodeAt(0) + ";";
|
|
||||||
})
|
|
||||||
.replace(/\u0008/gim, "");
|
|
||||||
};
|
|
||||||
|
|
||||||
const UPSTREAM_API_ERRORS = [
|
|
||||||
TRY_AGAIN_LATER,
|
|
||||||
SECONDARY_ERROR_MESSAGES.MAX_RETRY,
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders error message on the card.
|
|
||||||
*
|
|
||||||
* @param {string} message Main error message.
|
|
||||||
* @param {string} secondaryMessage The secondary error message.
|
|
||||||
* @returns {string} The SVG markup.
|
|
||||||
*/
|
|
||||||
const renderError = (message, secondaryMessage = "") => {
|
|
||||||
return `
|
|
||||||
<svg width="${ERROR_CARD_LENGTH}" height="120" viewBox="0 0 ${ERROR_CARD_LENGTH} 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<style>
|
|
||||||
.text { font: 600 16px 'Segoe UI', Ubuntu, Sans-Serif; fill: #2F80ED }
|
|
||||||
.small { font: 600 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: #252525 }
|
|
||||||
.gray { fill: #858585 }
|
|
||||||
</style>
|
|
||||||
<rect x="0.5" y="0.5" width="${
|
|
||||||
ERROR_CARD_LENGTH - 1
|
|
||||||
}" height="99%" rx="4.5" fill="#FFFEFE" stroke="#E4E2E2"/>
|
|
||||||
<text x="25" y="45" class="text">Something went wrong!${
|
|
||||||
UPSTREAM_API_ERRORS.includes(secondaryMessage)
|
|
||||||
? ""
|
|
||||||
: " file an issue at https://tiny.one/readme-stats"
|
|
||||||
}</text>
|
|
||||||
<text data-testid="message" x="25" y="55" class="text small">
|
|
||||||
<tspan x="25" dy="18">${encodeHTML(message)}</tspan>
|
|
||||||
<tspan x="25" dy="18" class="gray">${secondaryMessage}</tspan>
|
|
||||||
</text>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto layout utility, allows us to layout things vertically or horizontally with
|
* Auto layout utility, allows us to layout things vertically or horizontally with
|
||||||
* proper gaping.
|
* proper gaping.
|
||||||
@@ -380,6 +325,81 @@ const getCardColors = ({
|
|||||||
return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor };
|
return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Script parameters.
|
||||||
|
const ERROR_CARD_LENGTH = 576.5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode string as HTML.
|
||||||
|
*
|
||||||
|
* @see https://stackoverflow.com/a/48073476/10629172
|
||||||
|
*
|
||||||
|
* @param {string} str String to encode.
|
||||||
|
* @returns {string} Encoded string.
|
||||||
|
*/
|
||||||
|
const encodeHTML = (str) => {
|
||||||
|
return str
|
||||||
|
.replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
|
||||||
|
return "&#" + i.charCodeAt(0) + ";";
|
||||||
|
})
|
||||||
|
.replace(/\u0008/gim, "");
|
||||||
|
};
|
||||||
|
|
||||||
|
const UPSTREAM_API_ERRORS = [
|
||||||
|
TRY_AGAIN_LATER,
|
||||||
|
SECONDARY_ERROR_MESSAGES.MAX_RETRY,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders error message on the card.
|
||||||
|
*
|
||||||
|
* @param {string} message Main error message.
|
||||||
|
* @param {string} secondaryMessage The secondary error message.
|
||||||
|
* @param {object} options Function options.
|
||||||
|
* @returns {string} The SVG markup.
|
||||||
|
*/
|
||||||
|
const renderError = (message, secondaryMessage = "", options = {}) => {
|
||||||
|
const {
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme = "default",
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
// returns theme based colors with proper overrides and defaults
|
||||||
|
const { titleColor, textColor, bgColor, borderColor } = getCardColors({
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
icon_color: "",
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
ring_color: "",
|
||||||
|
theme,
|
||||||
|
});
|
||||||
|
|
||||||
|
return `
|
||||||
|
<svg width="${ERROR_CARD_LENGTH}" height="120" viewBox="0 0 ${ERROR_CARD_LENGTH} 120" fill="${bgColor}" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<style>
|
||||||
|
.text { font: 600 16px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${titleColor} }
|
||||||
|
.small { font: 600 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||||
|
.gray { fill: #858585 }
|
||||||
|
</style>
|
||||||
|
<rect x="0.5" y="0.5" width="${
|
||||||
|
ERROR_CARD_LENGTH - 1
|
||||||
|
}" height="99%" rx="4.5" fill="${bgColor}" stroke="${borderColor}"/>
|
||||||
|
<text x="25" y="45" class="text">Something went wrong!${
|
||||||
|
UPSTREAM_API_ERRORS.includes(secondaryMessage)
|
||||||
|
? ""
|
||||||
|
: " file an issue at https://tiny.one/readme-stats"
|
||||||
|
}</text>
|
||||||
|
<text data-testid="message" x="25" y="55" class="text small">
|
||||||
|
<tspan x="25" dy="18">${encodeHTML(message)}</tspan>
|
||||||
|
<tspan x="25" dy="18" class="gray">${secondaryMessage}</tspan>
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split text over multiple lines based on the card width.
|
* Split text over multiple lines based on the card width.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in new issue
Block a user