refactor(ui): changed frontend to normal i18n without SSR

This commit is contained in:
akhilmhdh
2023-05-09 23:28:23 +05:30
parent 420d71d923
commit 3561c589b1
198 changed files with 5008 additions and 5253 deletions
+33 -36
View File
@@ -1,11 +1,10 @@
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Head from 'next/head';
import { useTranslation } from 'next-i18next';
import { plans as plansConstant } from 'public/data/frequentConstants';
import Plan from '@app/components/billing/Plan';
import NavHeader from '@app/components/navigation/NavHeader';
import { getTranslatedServerSideProps } from '@app/components/utilities/withTranslateProps';
import getOrganizationSubscriptions from '../../api/organization/GetOrgSubscription';
import getOrganizationUsers from '../../api/organization/GetOrgUsers';
@@ -19,43 +18,43 @@ export default function SettingsBilling() {
const plans = [
{
key: 1,
name: t('billing:starter.name')!,
price: t('billing:free')!,
priceExplanation: t('billing:starter.price-explanation')!,
text: t('billing:starter.text')!,
subtext: t('billing:starter.subtext')!,
buttonTextMain: t('billing:downgrade')!,
buttonTextSecondary: t('billing:learn-more')!,
name: t('billing.starter.name')!,
price: t('billing.free')!,
priceExplanation: t('billing.starter.price-explanation')!,
text: t('billing.starter.text')!,
subtext: t('billing.starter.subtext')!,
buttonTextMain: t('billing.downgrade')!,
buttonTextSecondary: t('billing.learn-more')!,
current: currentPlan === plansConstant.starter
},
{
key: 2,
name: 'Team',
price: '$8',
priceExplanation: t('billing:professional.price-explanation')!,
priceExplanation: t('billing.professional.price-explanation')!,
text: 'For teams that want to improve their efficiency and security.',
buttonTextMain: t('billing:upgrade')!,
buttonTextSecondary: t('billing:learn-more')!,
buttonTextMain: t('billing.upgrade')!,
buttonTextSecondary: t('billing.learn-more')!,
current: currentPlan === plansConstant.team
},
{
key: 3,
name: t('billing:professional.name')!,
name: t('billing.professional.name')!,
price: '$18',
priceExplanation: t('billing:professional.price-explanation')!,
text: t('billing:enterprise.text')!,
subtext: t('billing:professional.subtext')!,
buttonTextMain: t('billing:upgrade')!,
buttonTextSecondary: t('billing:learn-more')!,
priceExplanation: t('billing.professional.price-explanation')!,
text: t('billing.enterprise.text')!,
subtext: t('billing.professional.subtext')!,
buttonTextMain: t('billing.upgrade')!,
buttonTextSecondary: t('billing.learn-more')!,
current: currentPlan === plansConstant.professional
},
{
key: 4,
name: t('billing:enterprise.name')!,
price: t('billing:custom-pricing')!,
name: t('billing.enterprise.name')!,
price: t('billing.custom-pricing')!,
text: 'Boost the security and efficiency of your engineering teams.',
buttonTextMain: t('billing:schedule-demo')!,
buttonTextSecondary: t('billing:learn-more')!,
buttonTextMain: t('billing.schedule-demo')!,
buttonTextSecondary: t('billing.learn-more')!,
current: false
}
];
@@ -77,30 +76,30 @@ export default function SettingsBilling() {
}, []);
return (
<div className="bg-bunker-800 pb-4 flex flex-col justify-between text-white">
<div className="flex flex-col justify-between bg-bunker-800 pb-4 text-white">
<Head>
<title>{t('common:head-title', { title: t('billing:title') })}</title>
<title>{t('common.head-title', { title: t('billing.title') })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<div className="flex flex-row">
<div className="w-full pb-2">
<NavHeader pageName={t('billing:title')} />
<div className="flex flex-row justify-between items-center ml-6 my-8 text-xl max-w-5xl">
<div className="flex flex-col justify-start items-start text-3xl">
<p className="font-semibold mr-4 text-gray-200">{t('billing:title')}</p>
<p className="font-normal mr-4 text-gray-400 text-base">{t('billing:description')}</p>
<NavHeader pageName={t('billing.title')} />
<div className="my-8 ml-6 flex max-w-5xl flex-row items-center justify-between text-xl">
<div className="flex flex-col items-start justify-start text-3xl">
<p className="mr-4 font-semibold text-gray-200">{t('billing.title')}</p>
<p className="mr-4 text-base font-normal text-gray-400">{t('billing.description')}</p>
</div>
</div>
<div className="flex flex-col ml-6 text-mineshaft-50 w-max">
<p className="text-xl font-semibold">{t('billing:subscription')}</p>
<div className="grid grid-cols-2 grid-rows-2 gap-y-6 gap-x-3 mt-4 overflow-x-auto">
<div className="ml-6 flex w-max flex-col text-mineshaft-50">
<p className="text-xl font-semibold">{t('billing.subscription')}</p>
<div className="mt-4 grid grid-cols-2 grid-rows-2 gap-y-6 gap-x-3 overflow-x-auto">
{plans.map((plan) => (
<Plan key={plan.name} plan={plan} />
))}
</div>
<p className="text-xl font-bold mt-12">{t('billing:current-usage')}</p>
<p className="mt-12 text-xl font-bold">{t('billing.current-usage')}</p>
<div className="flex flex-row">
<div className="mr-4 mt-8 text-gray-300 w-60 pt-6 pb-10 rounded-md bg-white/5 justify-center items-center flex flex-col">
<div className="mr-4 mt-8 flex w-60 flex-col items-center justify-center rounded-md bg-white/5 pt-6 pb-10 text-gray-300">
<p className="text-6xl font-bold">{numUsers}</p>
<p className="text-gray-300">
{numUsers > 1 ? 'Organization members' : 'Organization member'}
@@ -119,5 +118,3 @@ export default function SettingsBilling() {
}
SettingsBilling.requireAuth = true;
export const getServerSideProps = getTranslatedServerSideProps(['settings', 'billing']);
+2 -10
View File
@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useTranslation } from 'react-i18next';
import Head from 'next/head';
import { useTranslation } from 'next-i18next';
import { getTranslatedServerSideProps } from '@app/components/utilities/withTranslateProps';
import { OrgSettingsPage } from '@app/views/Settings/OrgSettingsPage';
export default function SettingsOrg() {
@@ -11,7 +10,7 @@ export default function SettingsOrg() {
return (
<>
<Head>
<title>{t('common:head-title', { title: t('settings-org:title') })}</title>
<title>{t('common.head-title', { title: t('settings.org.title') })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<OrgSettingsPage />
@@ -20,10 +19,3 @@ export default function SettingsOrg() {
}
SettingsOrg.requireAuth = true;
export const getServerSideProps = getTranslatedServerSideProps([
'settings',
'settings-org',
'section-incident',
'section-members'
]);
@@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import Head from 'next/head';
import { useTranslation } from 'next-i18next';
import { getTranslatedServerSideProps } from '@app/components/utilities/withTranslateProps';
import { CreateServiceAccountPage } from '@app/views/Settings/CreateServiceAccountPage';
export default function ServiceAccountPage() {
@@ -18,10 +16,3 @@ export default function ServiceAccountPage() {
}
ServiceAccountPage.requireAuth = true;
export const getServerSideProps = getTranslatedServerSideProps([
'settings',
'settings-org',
'section-incident',
'section-members'
]);
+70 -77
View File
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { faCheck, faPlus, faX } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -13,7 +13,6 @@ import NavHeader from '@app/components/navigation/NavHeader';
import passwordCheck from '@app/components/utilities/checks/PasswordCheck';
import changePassword from '@app/components/utilities/cryptography/changePassword';
import issueBackupKey from '@app/components/utilities/cryptography/issueBackupKey';
import { getTranslatedServerSideProps } from '@app/components/utilities/withTranslateProps';
import { SecuritySection } from '@app/views/Settings/PersonalSettingsPage/SecuritySection/SecuritySection';
import AddApiKeyDialog from '../../../components/basic/dialog/AddApiKeyDialog';
@@ -36,13 +35,14 @@ export default function PersonalSettings() {
const [isAddApiKeyDialogOpen, setIsAddApiKeyDialogOpen] = useState(false);
const [apiKeys, setApiKeys] = useState<any[]>([]);
const { t } = useTranslation();
const { t, i18n } = useTranslation();
const router = useRouter();
const lang = router.locale ?? 'en';
const setLanguage = async (to: string) => {
router.push(router.asPath, router.asPath, { locale: to });
localStorage.setItem('lang', to);
i18n.changeLanguage(to);
};
useEffect(() => {
@@ -65,9 +65,9 @@ export default function PersonalSettings() {
};
return (
<div className="bg-bunker-800 max-h-screen flex flex-col justify-between text-white">
<div className="flex max-h-screen flex-col justify-between bg-bunker-800 text-white">
<Head>
<title>{t('common:head-title', { title: t('settings-personal:title') })}</title>
<title>{t('common.head-title', { title: t('settings.personal.title') })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<AddApiKeyDialog
@@ -77,44 +77,44 @@ export default function PersonalSettings() {
setApiKeys={setApiKeys}
/>
<div className="flex flex-row">
<div className="w-full max-h-screen pb-2">
<NavHeader pageName={t('settings-personal:title')} isProjectRelated={false} />
<div className="flex flex-row justify-between items-center ml-6 mt-8 mb-6 text-xl max-w-5xl">
<div className="flex flex-col justify-start items-start text-3xl">
<p className="font-semibold mr-4 text-gray-200">{t('settings-personal:title')}</p>
<p className="font-normal mr-4 text-gray-400 text-base">
{t('settings-personal:description')}
<div className="max-h-screen w-full pb-2">
<NavHeader pageName={t('settings.personal.title')} isProjectRelated={false} />
<div className="ml-6 mt-8 mb-6 flex max-w-5xl flex-row items-center justify-between text-xl">
<div className="flex flex-col items-start justify-start text-3xl">
<p className="mr-4 font-semibold text-gray-200">{t('settings.personal.title')}</p>
<p className="mr-4 text-base font-normal text-gray-400">
{t('settings.personal.description')}
</p>
</div>
</div>
<div className="flex flex-col ml-6 text-mineshaft-50 mr-6 max-w-5xl">
<div className="bg-white/5 rounded-md px-6 pt-6 pb-6 flex flex-col items-start w-full mb-6 mt-4">
<p className="text-xl font-semibold self-start">
{t('settings-personal:change-language')}
<div className="ml-6 mr-6 flex max-w-5xl flex-col text-mineshaft-50">
<div className="mb-6 mt-4 flex w-full flex-col items-start rounded-md bg-white/5 px-6 pt-6 pb-6">
<p className="self-start text-xl font-semibold">
{t('settings.personal.change-language')}
</p>
<div className="max-h-28 w-ful mt-4">
<div className="w-ful mt-4 max-h-28">
<ListBox
isSelected={lang}
onChange={setLanguage}
data={['en', 'ko', 'fr', 'es']}
text={`${t('common:language')}: `}
text={`${t('common.language')}: `}
/>
</div>
</div>
<SecuritySection />
<div className="bg-white/5 rounded-md px-6 flex flex-col items-start w-full mt-2 mb-8 pt-4">
<div className="flex flex-row justify-between w-full">
<div className="flex flex-col w-full">
<p className="text-xl font-semibold mb-3">
{t('settings-personal:api-keys.title')}
<div className="mt-2 mb-8 flex w-full flex-col items-start rounded-md bg-white/5 px-6 pt-4">
<div className="flex w-full flex-row justify-between">
<div className="flex w-full flex-col">
<p className="mb-3 text-xl font-semibold">
{t('settings.personal.api-keys.title')}
</p>
<p className="text-sm text-gray-400">
{t('settings-personal:api-keys.description')}
{t('settings.personal.api-keys.description')}
</p>
</div>
<div className="w-40 mt-2">
<div className="mt-2 w-40">
<Button
text={String(t('settings-personal:api-keys.add-new'))}
text={String(t('settings.personal.api-keys.add-new'))}
onButtonPressed={() => {
setIsAddApiKeyDialogOpen(true);
}}
@@ -127,17 +127,17 @@ export default function PersonalSettings() {
<ApiKeyTable data={apiKeys} setApiKeys={setApiKeys as any} />
</div>
<div className="bg-white/5 rounded-md px-6 pt-5 pb-6 flex flex-col items-start w-full mb-6">
<div className="flex flex-row max-w-5xl justify-between items-center w-full">
<div className="flex flex-col justify-between w-full max-w-3xl">
<p className="text-xl font-semibold mb-3 min-w-max">
{t('section-password:change')}
<div className="mb-6 flex w-full flex-col items-start rounded-md bg-white/5 px-6 pt-5 pb-6">
<div className="flex w-full max-w-5xl flex-row items-center justify-between">
<div className="flex w-full max-w-3xl flex-col justify-between">
<p className="mb-3 min-w-max text-xl font-semibold">
{t('section.password.change')}
</p>
</div>
</div>
<div className="max-w-xl w-full">
<div className="w-full max-w-xl">
<InputField
label={t('section-password:current') as string}
label={t('section.password.current') as string}
onChangeHandler={(password) => {
setCurrentPassword(password);
}}
@@ -145,13 +145,13 @@ export default function PersonalSettings() {
value={currentPassword}
isRequired
error={currentPasswordError}
errorText={t('section-password:current-wrong') as string}
errorText={t('section.password.current-wrong') as string}
autoComplete="current-password"
id="current-password"
/>
<div className="py-2" />
<InputField
label={t('section-password:new') as string}
label={t('section.password.new') as string}
onChangeHandler={(password) => {
setNewPassword(password);
passwordCheck({
@@ -171,59 +171,59 @@ export default function PersonalSettings() {
/>
</div>
{passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? (
<div className="w-full mt-3 bg-white/5 px-2 flex flex-col items-start py-2 rounded-md max-w-xl mb-2">
<div className="text-gray-400 text-sm mb-1">
{t('section-password:validate-base')}
<div className="mt-3 mb-2 flex w-full max-w-xl flex-col items-start rounded-md bg-white/5 px-2 py-2">
<div className="mb-1 text-sm text-gray-400">
{t('section.password.validate-base')}
</div>
<div className="flex flex-row justify-start items-center ml-1">
<div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorLength ? (
<FontAwesomeIcon icon={faX} className="text-md text-red mr-2.5" />
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : (
<FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" />
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)}
<div
className={`${
passwordErrorLength ? 'text-gray-400' : 'text-gray-600'
} text-sm`}
>
{t('section-password:validate-length')}
{t('section.password.validate-length')}
</div>
</div>
<div className="flex flex-row justify-start items-center ml-1">
<div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorLowerCase ? (
<FontAwesomeIcon icon={faX} className="text-md text-red mr-2.5" />
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : (
<FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" />
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)}
<div
className={`${
passwordErrorLowerCase ? 'text-gray-400' : 'text-gray-600'
} text-sm`}
>
{t('section-password:validate-case')}
{t('section.password.validate-case')}
</div>
</div>
<div className="flex flex-row justify-start items-center ml-1">
<div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorNumber ? (
<FontAwesomeIcon icon={faX} className="text-md text-red mr-2.5" />
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : (
<FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" />
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)}
<div
className={`${
passwordErrorNumber ? 'text-gray-400' : 'text-gray-600'
} text-sm`}
>
{t('section-password:validate-number')}
{t('section.password.validate-number')}
</div>
</div>
</div>
) : (
<div className="py-2" />
)}
<div className="flex flex-row items-center mt-3 w-52 pr-3">
<div className="mt-3 flex w-52 flex-row items-center pr-3">
<Button
text={t('section-password:change') as string}
text={t('section.password.change') as string}
onButtonPressed={() => {
if (!passwordErrorLength && !passwordErrorLowerCase && !passwordErrorNumber) {
changePassword(
@@ -244,47 +244,47 @@ export default function PersonalSettings() {
currentPassword !== '' &&
!(passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber)
}
textDisabled={t('section-password:change') as string}
textDisabled={t('section.password.change') as string}
/>
<FontAwesomeIcon
icon={faCheck}
className={`ml-4 text-primary text-3xl ${
className={`ml-4 text-3xl text-primary ${
passwordChanged ? 'opacity-100' : 'opacity-0'
} duration-300`}
/>
</div>
</div>
<div className="bg-white/5 rounded-md px-6 pt-5 pb-6 mt-2 flex flex-col items-start w-full mb-6">
<div className="flex flex-row max-w-5xl justify-between items-center w-full">
<div className="flex flex-col justify-between w-full max-w-3xl">
<p className="text-xl font-semibold mb-3 min-w-max">
{t('settings-personal:emergency.name')}
<div className="mt-2 mb-6 flex w-full flex-col items-start rounded-md bg-white/5 px-6 pt-5 pb-6">
<div className="flex w-full max-w-5xl flex-row items-center justify-between">
<div className="flex w-full max-w-3xl flex-col justify-between">
<p className="mb-3 min-w-max text-xl font-semibold">
{t('settings.personal.emergency.name')}
</p>
<p className="text-sm text-mineshaft-300 min-w-max">
{t('settings-personal:emergency.text1')}
<p className="min-w-max text-sm text-mineshaft-300">
{t('settings.personal.emergency.text1')}
</p>
<p className="text-sm text-mineshaft-300 mb-5 min-w-max">
{t('settings-personal:emergency.text2')}
<p className="mb-5 min-w-max text-sm text-mineshaft-300">
{t('settings.personal.emergency.text2')}
</p>
</div>
</div>
<div className="w-full max-w-xl mb-4">
<div className="mb-4 w-full max-w-xl">
<InputField
label={t('section-password:current') as string}
label={t('section.password.current') as string}
onChangeHandler={setBackupPassword}
type="password"
value={backupPassword}
isRequired
error={backupKeyError}
errorText={t('section-password:current-wrong') as string}
errorText={t('section.password.current-wrong') as string}
autoComplete="current-password"
id="current-password"
/>
</div>
<div className="flex flex-row items-center mt-3 w-60">
<div className="mt-3 flex w-60 flex-row items-center">
<Button
text={t('settings-personal:emergency.download') as string}
text={t('settings.personal.emergency.download') as string}
onButtonPressed={() => {
issueBackupKey({
email: personalEmail,
@@ -297,11 +297,11 @@ export default function PersonalSettings() {
color="mineshaft"
size="md"
active={backupPassword !== ''}
textDisabled={t('settings-personal:emergency.download') as string}
textDisabled={t('settings.personal.emergency.download') as string}
/>
<FontAwesomeIcon
icon={faCheck}
className={`ml-4 text-primary text-3xl ${
className={`ml-4 text-3xl text-primary ${
backupKeyIssued ? 'opacity-100' : 'opacity-0'
} duration-300`}
/>
@@ -315,10 +315,3 @@ export default function PersonalSettings() {
}
PersonalSettings.requireAuth = true;
export const getServerSideProps = getTranslatedServerSideProps([
'settings',
'settings-personal',
'section-password',
'section-api-key'
]);
+1 -9
View File
@@ -1,7 +1,6 @@
import { useTranslation } from 'react-i18next';
import Head from 'next/head';
import { getTranslatedStaticProps } from '@app/components/utilities/withTranslateProps';
import { ProjectSettingsPage } from '@app/views/Settings/ProjectSettingsPage';
const ProjectSettings = () => {
@@ -10,10 +9,9 @@ const ProjectSettings = () => {
return (
<>
<Head>
<title>{t('common:head-title', { title: t('settings-project:title') })}</title>
<title>{t('common.head-title', { title: t('settings.project.title') })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<ProjectSettingsPage />
</>
);
@@ -22,9 +20,3 @@ const ProjectSettings = () => {
export default ProjectSettings;
ProjectSettings.requireAuth = true;
export const getServerSideProps = getTranslatedStaticProps([
'settings',
'settings-project',
'section-token'
]);