Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
a3c26d9
Merge pull request #46 from feedzai/main
DiogoRDuarte Dec 13, 2024
48249e6
fix: Series names can now have spaces between them
Dec 13, 2024
7af9842
fix: Updates changelog
Dec 13, 2024
845a75a
removed unintended console logs
Dec 13, 2024
1526248
fix: the manual descriptions repeated the title and chart type
Dec 13, 2024
1bb8819
Merge pull request #47 from feedzai/fix-dd-series-classnames
DiogoRDuarte Jan 6, 2025
86c05e9
Merge pull request #48 from feedzai/develop
DiogoRDuarte Jan 6, 2025
5f0db44
chore: release v2.0.4
DiogoRDuarte Jan 6, 2025
b92a21a
Added i18n to the tool
May 12, 2025
b88a91e
Updated even more places in the code with i18n effort
May 13, 2025
ca547d0
Included i18n in the Readme and Changelog
May 13, 2025
a2ca137
Changed registry
May 13, 2025
6a85c53
Deleted .npmrc
May 13, 2025
ddd27f7
Added back .npmrc
DiogoRDuarte May 13, 2025
654d3c8
Fixed package-lock.json
DiogoRDuarte May 13, 2025
36ca3d1
Added i18n to the remaining alerts (en and pt)
Jun 3, 2025
2ec5cbb
Fixed the tests not running after i18n
Jun 4, 2025
6452022
Tried to fix github pipeline stopping at the tests step
Jun 4, 2025
7e281fc
Added i18n to the automatic descriptions
Jun 4, 2025
55a1cb0
Adapted i18n to easily support new languages and modify existing ones
Jun 5, 2025
faede21
Changed GuideData -> CustomGuideData in the CustomShortcutGuide
Jun 5, 2025
aa9b703
Adapted the ShortcutGuide to vary between Alt and option depending on…
Jun 5, 2025
8f22284
Converted country language keys to correct locale codes
DiogoRDuarte Jun 6, 2025
fc7f1f8
Updated README french strings
DiogoRDuarte Jun 6, 2025
86b5a83
Adressed minor comments by Rita on PR#50
DiogoRDuarte Jun 16, 2025
7fbf0bd
Merge pull request #59 from feedzai/develop
DiogoRDuarte Sep 5, 2025
7bfa47f
Add support for OpenAI-compatible API endpoint
joaopalmeiro Sep 5, 2025
4d6bd21
Update docs
joaopalmeiro Sep 5, 2025
8b719e8
Add Model ID field to the examples
joaopalmeiro Sep 6, 2025
c74560e
Add base URL, update error messages, and remove unused params from co…
joaopalmeiro Sep 6, 2025
4053863
Format constant file
joaopalmeiro Sep 6, 2025
1200565
Add new props to chart examples
joaopalmeiro Sep 8, 2025
9ba1ec5
Fix form field names
joaopalmeiro Sep 8, 2025
4486121
Format components
joaopalmeiro Sep 8, 2025
c98da6e
Update base URL defaults
joaopalmeiro Sep 8, 2025
8d66172
Revert package-lock.json changes
joaopalmeiro Sep 8, 2025
2b60d7d
Merge branch 'develop' into feat-jp-57-add-support-open-ai-compatible…
joaopalmeiro Sep 8, 2025
affc7ea
Standardize Markdown tables
joaopalmeiro Sep 8, 2025
e76fc4d
Update CHANGELOG.md
joaopalmeiro Sep 8, 2025
bf0ce87
Update OpenAI API key validation
joaopalmeiro Sep 8, 2025
17def94
Merge pull request #60 from joaopalmeiro/feat-jp-57-add-support-open-…
DiogoRDuarte Sep 8, 2025
a27eb34
Fixed i18n bug where the entire page would be affected by a single la…
DiogoRDuarte Sep 8, 2025
789177d
Added cypress i18n test
DiogoRDuarte Sep 8, 2025
6777d4c
Updated changelog
DiogoRDuarte Sep 8, 2025
78f8d66
Removed unused file and function
DiogoRDuarte Sep 8, 2025
84eec4f
Replaced en-BR with en-GB
DiogoRDuarte Sep 8, 2025
ff0871d
Replaced TranslationObject with native Record<string, string>
DiogoRDuarte Sep 8, 2025
7ccebb1
Merge pull request #61 from feedzai/i18n-tests
DiogoRDuarte Sep 9, 2025
47aca31
Moved the context prop to inside autoDescriptions
DiogoRDuarte Sep 8, 2025
5a8f7d1
Updated Changelog
DiogoRDuarte Sep 8, 2025
73eeaf1
Added arrow navigation inside of the shortcut guide. Fixed wrong Cust…
DiogoRDuarte Sep 10, 2025
6253be8
Updated changelog
DiogoRDuarte Sep 10, 2025
962d23d
Added the role="application" to the chart wrapper
DiogoRDuarte Sep 11, 2025
ba67908
Replaced arrow icons with text strings
DiogoRDuarte Sep 11, 2025
1225b53
Re-did description list (<dl>) structure of Shortcut Guide
DiogoRDuarte Sep 11, 2025
0f55a4d
Updated CHANGELOG
DiogoRDuarte Sep 11, 2025
4e083d6
Adressed Joao Palmeiro´s comments
DiogoRDuarte Sep 12, 2025
8532c80
Merge pull request #62 from feedzai/dd-general-fixing
DiogoRDuarte Sep 12, 2025
eb14634
Merge pull request #65 from feedzai/develop
DiogoRDuarte Sep 15, 2025
d17764c
chore: release v3.0.0
DiogoRDuarte Sep 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ dist-ssr
cypress/results
cypress/screenshots
cypress/downloads

# Test coverage
.nyc_output
coverage
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
registry=https://registry.npmjs.org
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## 3.0.0 - 2025-09-15
### Added
- Implemented i18n alternatives as the new "internationalization" property
- Fixed tests / github pipeline errors
- Adapted the ShortcutGuide to vary between "Alt" and "option" depending on the OS
- Added support for OpenAI API-compatible providers via the new `baseUrl` prop
- Added new i18n Cypress tests
- Added Arrow Navigation to the ShortcutGuide

### Changed
- Replaced arrow symbols with text on the ShortcutGuide
- Re-did ShortcutGuide `<dl>` structure
- Moved the context prop to inside autoDescriptions

## 2.0.4 - 2025-01-06
### Added
- Fixed an issue where series values having spaces would invalidate class names

## 2.0.3 - 2024-11-04
### Added
- Adds missing types
Expand Down
67 changes: 52 additions & 15 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineConfig } from "cypress";
import codeCoverageTask from "@cypress/code-coverage/task";
import codeCoverageTask from "@cypress/code-coverage/task.js";

export default defineConfig({
e2e: {
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/compare-to-chart.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("(Alt + Z) Compare to Rest of the Chart Test", () => {
.should("have.text", "This shortcut only works inside a chart");
cy.get("@chartDescription").type("{downArrow}");
cy.findAllByTestId("a11y-chart-element").first().type("{alt}z");
cy.get("@chartAlert").should("have.text", "This is the highest value.");
cy.get("@chartAlert").should("have.text", "This is the highest value");
cy.checkA11y();
});
});
2 changes: 1 addition & 1 deletion cypress/e2e/compare-to-maximum.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("(Alt + Shift + L) Compare to Maximum of the Chart Test", () => {
cy.findAllByTestId("a11y-chart-element").first().type("{alt}{shift}l");
cy.findAllByTestId("a11y-chart-alert")
.first()
.should("have.text", "The value is the same as the maximum value");
.should("have.text", "The value is the same as the Maximum value");
cy.checkA11y();
});
});
43 changes: 43 additions & 0 deletions cypress/e2e/internationalization.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable no-undef */
describe("Internationalization Tests", () => {
it("should use default English (en-GB) language when internationalization property is empty", () => {
cy.visit("/");
cy.injectAxe();
cy.findByTestId("manual-descriptions-option").click();
cy.wait(500);
cy.findAllByTestId("a11y_desc").first().focus();
cy.focused().type("{alt}k");
cy.findAllByTestId("a11y-chart-alert").first().should("contain.text", "The average is");
cy.focused().type("?");
cy.get("dialog").should("be.visible");
cy.get("dialog h2").should("contain.text", "Shortcut guide");
cy.focused().type("{esc}");
cy.checkA11y();
});

it("should use default Portuguese (pt-PT) language when language property is pt-PT", () => {
cy.visit("/");
cy.injectAxe();
cy.findByTestId("manual-descriptions-option").click();
cy.wait(500);
cy.findAllByTestId("a11y_desc").first().focus().tab().tab();
cy.focused().type("{alt}k");
cy.findAllByTestId("a11y-chart-alert").eq(2).should("contain.text", "A média é");
cy.focused().type("?");
cy.get("dialog").should("be.visible");
cy.get("dialog h2").should("contain.text", "Guia de atalhos");
cy.checkA11y();
});

it("should use an overriten en-GB string", () => {
cy.visit("/");
cy.injectAxe();
cy.findByTestId("manual-descriptions-option").click();
cy.wait(500);
cy.findAllByTestId("a11y_desc").first().focus().tab().tab();
cy.focused().type("?");
cy.get("dialog").should("be.visible");
cy.get("dialog h2").should("contain.text", "Overwritten Shortcut guide title");
cy.checkA11y();
});
});
3 changes: 2 additions & 1 deletion cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
// Import commands.js using ES2015 syntax:
import "./commands";
import "cypress-axe";
require("cypress-plugin-tab");
import "cypress-plugin-tab";
import "@cypress/code-coverage/support";

// Alternatively you can use CommonJS syntax:
// require('./commands')
19 changes: 8 additions & 11 deletions examples/src/Homepage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import CardGridManual from "./components/manual/ChartGridManual";

function Homepage() {
const [apiKey, setApiKey] = useState("");
const [model, setModel] = useState("gpt-3.5-turbo");
const [baseUrl, setBaseUrl] = useState("https://api.openai.com/v1/");
const [isValid, setIsValid] = useState(false);
const [automatic, setAutomatic] = useState(false);
const [manual, setManual] = useState(false);
Expand Down Expand Up @@ -38,7 +40,7 @@ function Homepage() {
{isValid && apiKey !== "" ? (
<>
<div style={{ marginTop: 20 }}>
<CardGrid apiKey={apiKey} setHome={setHome} />
<CardGrid apiKey={apiKey} model={model} baseUrl={baseUrl} setHome={setHome} />
</div>
<p>
Data from{" "}
Expand All @@ -64,6 +66,10 @@ function Homepage() {
<KeyRequest
apiKey={apiKey}
setApiKey={setApiKey}
model={model}
setModel={setModel}
baseUrl={baseUrl}
setBaseUrl={setBaseUrl}
isValid={isValid}
setIsValid={setIsValid}
home={home}
Expand All @@ -72,16 +78,7 @@ function Homepage() {
/>
</div>
) : home ? (
<Options
apiKey={apiKey}
setApiKey={setApiKey}
isValid={isValid}
setIsValid={setIsValid}
automatic={automatic}
setAutomatic={setAutomatic}
manual={manual}
setManual={setManual}
/>
<Options setAutomatic={setAutomatic} setManual={setManual} />
) : (
<p></p>
)}
Expand Down
84 changes: 63 additions & 21 deletions examples/src/KeyRequest.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,55 @@ import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography";
import "./assets/style/Options.css";

const KeyRequest = ({ apiKey, setApiKey, setIsValid, setHome }) => {
const KeyRequest = ({
apiKey,
setApiKey,
model,
setModel,
baseUrl,
setBaseUrl,
setIsValid,
setHome,
}) => {
setHome(false);

const handleChanges = (e) => {
const isValidOpenAiApiKey = (key) => {
return key.startsWith("sk-proj-");
};

const isOpenAiApi = (baseUrl) => {
const parsedBaseUrl = URL.parse(baseUrl);

if (parsedBaseUrl) {
return parsedBaseUrl.host === "api.openai.com";
}

return false;
};

const handleApiKeyChange = (e) => {
setApiKey(e.target.value);
};

const handleModelChange = (e) => {
setModel(e.target.value);
};

const handleBaseUrl = (e) => {
setBaseUrl(e.target.value);
};

const handleSubmit = (e) => {
e.preventDefault();
if (isValidApiKey(apiKey)) {
setIsValid(true);
} else {
alert(
"The API key should start with 'sk-' and be followed by a string of exactly 48 alphanumeric characters.",
);

if (isOpenAiApi(baseUrl) && !isValidOpenAiApiKey(apiKey)) {
alert("The OpenAI API key should start with 'sk-proj-'.");
setIsValid(false);
} else {
setIsValid(true);
}
};

const isValidApiKey = (key) => {
const apiKeyPattern = /^sk-(proj-)?[a-zA-Z0-9]{48}$/;
return apiKeyPattern.test(key);
};

return (
<>
<div id="cardContainer">
Expand All @@ -38,28 +63,45 @@ const KeyRequest = ({ apiKey, setApiKey, setIsValid, setHome }) => {
<Typography variant="body2" color="text.secondary" style={{ whiteSpace: "pre-wrap" }}>
Please provide an{" "}
<a href="https://platform.openai.com/account/api-keys" target="_blank">
OpenAI API key
OpenAI
</a>{" "}
(the key is not saved). <br></br>The API key should start with 'sk-' and be followed
by a string of exactly 48 alphanumeric characters.
or OpenAI-compatible API key (the key is not saved). <br></br>The OpenAI API key
should start with 'sk-proj-'.
</Typography>
<br />
<label>
API Key:{" "}
API key:{" "}
<input
type="text"
placeholder="sk-... OR sk-proj-..."
required
placeholder="sk-proj-... OR ..."
value={apiKey}
onChange={handleChanges}
onChange={handleApiKeyChange}
/>
</label>
<br />
<label>
Model: <input type="text" required value={model} onChange={handleModelChange} />
</label>
<br />
<label>
Base URL:{" "}
<input
type="url"
required
pattern="^https://.*|^http://localhost:\d+.*"
value={baseUrl}
onChange={handleBaseUrl}
/>
</label>
<br />
<button type="submit" tabIndex={0}>
Submit
</button>
</form>
{apiKey.length > 0 && !isValidApiKey(apiKey) && (
{apiKey.length > 0 && !isValidOpenAiApiKey(apiKey) && isOpenAiApi(baseUrl) && (
<p style={{ color: "red" }} role="alert">
Invalid API key format.
Invalid OpenAI API key format.
</p>
)}
</CardContent>
Expand Down
10 changes: 6 additions & 4 deletions examples/src/Options.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ const Options = ({ setAutomatic, setManual }) => {
<CardContent>
<h2>Option A</h2> <h3>Automatic Descriptions</h3>
<Typography variant="body2" color="text.secondary" style={{ whiteSpace: "pre-wrap" }}>
The descriptions for each chart are generated in the moment using a GPT model.
Because of that, <b> an OpenAI API key is needed.</b>
The descriptions for each chart are generated by an OpenAI model or one accessible
via an OpenAI-compatible API. Because of that,{" "}
<b>an OpenAI or OpenAI-compatible API key is needed.</b>
</Typography>
</CardContent>
</CardActionArea>
Expand All @@ -32,8 +33,9 @@ const Options = ({ setAutomatic, setManual }) => {
<h2>Option B</h2>
<h3>Manual Descriptions</h3>
<Typography variant="body2" color="text.secondary" style={{ whiteSpace: "pre-wrap" }}>
The descriptions for each chart were previously generated using a GPT model. They
were then manually added to each chart. <b>No OpenAI API key is needed.</b>
The descriptions for each chart were previously generated using an OpenAI model.
They were then manually added to each chart.{" "}
<b>No OpenAI or OpenAI-compatible API key is needed.</b>
</Typography>
</CardContent>
</CardActionArea>
Expand Down
5 changes: 3 additions & 2 deletions examples/src/components/automatic/BarChartAutomatic.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { chartDimensions } from "./chart.constants.js";
import { AutoVizuA11y } from "@feedzai/autovizua11y";
import transformJSON from "../../data/transformJSON.js";

function BarChart({ apiKey }) {
function BarChart({ apiKey, model, baseUrl }) {
const intValuesCountryData = countryData.map((country) => {
return {
...country, //copies all countrys first...
Expand Down Expand Up @@ -110,7 +110,8 @@ function BarChart({ apiKey }) {
autoDescriptions={{
dynamicDescriptions: false,
apiKey: apiKey,
model: "gpt-3.5-turbo",
model: model,
baseUrl: baseUrl,
temperature: 0.1,
}}
>
Expand Down
Loading