diff --git a/frontend/src/components/Button/Button.tsx b/frontend/src/components/Button/Button.tsx index 900d141a..1ed14cd7 100644 --- a/frontend/src/components/Button/Button.tsx +++ b/frontend/src/components/Button/Button.tsx @@ -2,7 +2,7 @@ import React, { ReactNode } from "react"; import cn from "classnames"; -export interface ButtonProps { +export interface ButtonProps extends React.ButtonHTMLAttributes { /** * Child elements within */ @@ -60,6 +60,7 @@ export const Button: React.FC = ({ href, target, onClick, + ...rest }) => { const classes = [ "btn", @@ -99,7 +100,8 @@ export const Button: React.FC = ({ ); diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx index e409f971..b49b00f9 100644 --- a/frontend/src/components/Footer.tsx +++ b/frontend/src/components/Footer.tsx @@ -1,7 +1,7 @@ import React from "react"; import { useHealthState } from "context"; -import { FormattedMessage } from "react-intl"; +import { intl } from "locale"; import styled from "styled-components"; const FixedFooterWrapper = styled.div` @@ -29,10 +29,10 @@ function Footer({ fixed }: Props) { target="_blank" rel="noreferrer" className="link-secondary"> - + {intl.formatMessage({ + id: "footer.userguide", + defaultMessage: "User Guide", + })}
  • @@ -41,10 +41,10 @@ function Footer({ fixed }: Props) { target="_blank" rel="noreferrer" className="link-secondary"> - + {intl.formatMessage({ + id: "footer.changelog", + defaultMessage: "Change Log", + })}
  • @@ -53,10 +53,10 @@ function Footer({ fixed }: Props) { target="_blank" rel="noreferrer" className="link-secondary"> - + {intl.formatMessage({ + id: "footer.github", + defaultMessage: "Github", + })}
  • @@ -64,20 +64,22 @@ function Footer({ fixed }: Props) {
    • - {" "} + {intl.formatMessage( + { + id: "footer.copyright", + defaultMessage: "Copyright © {year} jc21.com", + }, + { year: new Date().getFullYear() }, + )}{" "} - + {intl.formatMessage({ + id: "footer.theme", + defaultMessage: "Theme by Tabler", + })}
    • diff --git a/frontend/src/components/LocalePicker.tsx b/frontend/src/components/LocalePicker.tsx index 30d44d54..d079b19d 100644 --- a/frontend/src/components/LocalePicker.tsx +++ b/frontend/src/components/LocalePicker.tsx @@ -1,8 +1,8 @@ -import React, { useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { Button, Dropdown, Flag } from "components"; import { useLocaleState } from "context"; -import { changeLocale, getFlagCodeForLocale, getLocale, intl } from "locale"; +import { changeLocale, getFlagCodeForLocale, intl } from "locale"; export interface LocalPickerProps { /** @@ -15,11 +15,16 @@ export const LocalePicker: React.FC = ({ onChange, ...rest }) => { + const dropRef = useRef(null); const { locale, setLocale } = useLocaleState(); - - // const [locale, setLocale] = useState(getLocale()); const [localeShown, setLocaleShown] = useState(false); + const options = [ + ["us", "en-US"], + ["de", "de-DE"], + ["ir", "fa-IR"], + ]; + const handleOnChange = (e: any) => { changeLocale(e.currentTarget.rel); setLocale(e.currentTarget.rel); @@ -27,15 +32,25 @@ export const LocalePicker: React.FC = ({ onChange && onChange(locale); }; - const options = [ - ["us", "en-US"], - ["de", "de-DE"], - ["ir", "fa-IR"], - ]; + const handleClickOutside = (event: any) => { + if ( + dropRef.current && + // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. + !dropRef.current.contains(event.target) + ) { + setLocaleShown(false); + } + }; + + useEffect(() => { + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); return ( -
      +
      diff --git a/frontend/src/pages/Settings/index.tsx b/frontend/src/pages/Settings/index.tsx index 9ab1c83c..2c51a9b0 100644 --- a/frontend/src/pages/Settings/index.tsx +++ b/frontend/src/pages/Settings/index.tsx @@ -4,7 +4,6 @@ import { SettingsResponse, requestSettings } from "api/npm"; import { Table } from "components"; import { SuspenseLoader } from "components"; import { intl } from "locale"; -import { FormattedMessage } from "react-intl"; import { useInterval } from "rooks"; import styled from "styled-components"; @@ -59,7 +58,10 @@ function Settings() {

      - + {intl.formatMessage({ + id: "settings.title", + defaultMessage: "Settings", + })}

      - { - setRenderCount(renderCount + 1); - }} - /> +
      diff --git a/frontend/src/pages/Users/index.tsx b/frontend/src/pages/Users/index.tsx index b6be3f16..3abf5f7e 100644 --- a/frontend/src/pages/Users/index.tsx +++ b/frontend/src/pages/Users/index.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { FormattedMessage } from "react-intl"; +import { intl } from "locale"; import styled from "styled-components"; const Root = styled.div` @@ -15,7 +15,10 @@ function Users() {

      - + {intl.formatMessage({ + id: "users.title", + defaultMessage: "Users", + })}

      diff --git a/test/cypress/integration/ui/SetupLogin.spec.js b/test/cypress/integration/ui/SetupLogin.spec.js index e1652b0f..4d57dffd 100644 --- a/test/cypress/integration/ui/SetupLogin.spec.js +++ b/test/cypress/integration/ui/SetupLogin.spec.js @@ -13,7 +13,7 @@ describe('UI Setup and Login', () => { cy.get('input[name="nickname"]').type('Cypress'); cy.get('input[name="email"]').type('cypress@example.com'); cy.get('input[name="password"]').type('changeme'); - cy.get('form button:first').click(); + cy.get('form button:last').click(); cy.get('.navbar-nav .avatar').should('be.visible'); // logout: cy.clearLocalStorage(); @@ -23,7 +23,7 @@ describe('UI Setup and Login', () => { cy.visit('/'); cy.get('input[name="email"]').type('cypress@example.com'); cy.get('input[name="password"]').type('changeme'); - cy.get('form button:first').click(); + cy.get('form button:last').click(); cy.get('.navbar-nav .avatar').should('be.visible'); // logout: cy.clearLocalStorage();