diff --git a/frontend/package.json b/frontend/package.json index bf0aed9e..19db2035 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,47 +18,47 @@ "dependencies": { "@tabler/core": "^1.4.0", "@tabler/icons-react": "^3.35.0", - "@tanstack/react-query": "^5.89.0", + "@tanstack/react-query": "^5.90.3", "@tanstack/react-table": "^8.21.3", "@uiw/react-textarea-code-editor": "^3.1.1", "classnames": "^2.5.1", - "country-flag-icons": "^1.5.20", + "country-flag-icons": "^1.5.21", "date-fns": "^4.1.0", "ez-modal-react": "^1.0.5", "formik": "^2.4.6", "generate-password-browser": "^1.1.0", "humps": "^2.0.1", "query-string": "^9.3.1", - "react": "^19.1.1", + "react": "^19.2.0", "react-bootstrap": "^2.10.10", - "react-dom": "^19.1.1", - "react-intl": "^7.1.11", - "react-router-dom": "^7.9.1", + "react-dom": "^19.2.0", + "react-intl": "^7.1.14", + "react-router-dom": "^7.9.4", "react-select": "^5.10.2", "react-toastify": "^11.0.5", "rooks": "^9.3.0" }, "devDependencies": { - "@biomejs/biome": "^2.2.4", - "@formatjs/cli": "^6.7.2", - "@tanstack/react-query-devtools": "^5.89.0", + "@biomejs/biome": "^2.2.6", + "@formatjs/cli": "^6.7.4", + "@tanstack/react-query-devtools": "^5.90.2", "@testing-library/dom": "^10.4.1", - "@testing-library/jest-dom": "^6.8.0", + "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.0", "@types/country-flag-icons": "^1.2.2", "@types/humps": "^2.0.6", - "@types/react": "^19.1.13", - "@types/react-dom": "^19.1.9", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", "@types/react-table": "^7.7.20", - "@vitejs/plugin-react": "^5.0.3", - "happy-dom": "^18.0.1", + "@vitejs/plugin-react": "^5.0.4", + "happy-dom": "^20.0.2", "postcss": "^8.5.6", "postcss-simple-vars": "^7.0.1", - "sass": "^1.93.0", + "sass": "^1.93.2", "tmp": "^0.2.5", - "typescript": "5.9.2", - "vite": "^7.1.6", - "vite-plugin-checker": "^0.10.3", + "typescript": "5.9.3", + "vite": "^7.1.10", + "vite-plugin-checker": "^0.11.0", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" } diff --git a/frontend/src/api/backend/models.ts b/frontend/src/api/backend/models.ts index 34894688..3ba1cd36 100644 --- a/frontend/src/api/backend/models.ts +++ b/frontend/src/api/backend/models.ts @@ -97,6 +97,14 @@ export interface Certificate { redirectionHosts?: RedirectionHost[]; } +export interface ProxyLocation { + path: string; + advancedConfig: string; + forwardScheme: string; + forwardHost: string; + forwardPort: number; +} + export interface ProxyHost { id: number; createdOn: string; @@ -116,7 +124,7 @@ export interface ProxyHost { allowWebsocketUpgrade: boolean; http2Support: boolean; enabled: boolean; - locations?: string[]; // todo: string or object? + locations?: ProxyLocation[]; hstsEnabled: boolean; hstsSubdomains: boolean; // Expansions: diff --git a/frontend/src/pages/Access/Empty.tsx b/frontend/src/components/EmptyData.tsx similarity index 52% rename from frontend/src/pages/Access/Empty.tsx rename to frontend/src/components/EmptyData.tsx index 729a443d..d79b4a5a 100644 --- a/frontend/src/pages/Access/Empty.tsx +++ b/frontend/src/components/EmptyData.tsx @@ -1,4 +1,6 @@ import type { Table as ReactTable } from "@tanstack/react-table"; +import cn from "classnames"; +import type { ReactNode } from "react"; import { Button } from "src/components"; import { T } from "src/locale"; @@ -6,8 +8,12 @@ interface Props { tableInstance: ReactTable; onNew?: () => void; isFiltered?: boolean; + object: string; + objects: string; + color?: string; + customAddBtn?: ReactNode; } -export default function Empty({ tableInstance, onNew, isFiltered }: Props) { +function EmptyData({ tableInstance, onNew, isFiltered, object, objects, color = "primary", customAddBtn }: Props) { return ( @@ -19,14 +25,18 @@ export default function Empty({ tableInstance, onNew, isFiltered }: Props) { ) : ( <>

- +

- + {customAddBtn ? ( + customAddBtn + ) : ( + + )} )} @@ -34,3 +44,5 @@ export default function Empty({ tableInstance, onNew, isFiltered }: Props) { ); } + +export { EmptyData }; diff --git a/frontend/src/components/ErrorNotFound.tsx b/frontend/src/components/ErrorNotFound.tsx index 8cdf816d..a162d1cd 100644 --- a/frontend/src/components/ErrorNotFound.tsx +++ b/frontend/src/components/ErrorNotFound.tsx @@ -12,7 +12,7 @@ export function ErrorNotFound() {

- +

+
+ ); + } + + return ( + <> + {values.map((item: ProxyLocation, idx: number) => ( +
+
+
+
+
+ Location + handleChange(idx, "path", e.target.value)} + /> +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+ + handleChange(idx, "forwardHost", e.target.value)} + /> +
+
+
+
+ + handleChange(idx, "forwardPort", e.target.value)} + /> +
+
+
+ {advVisible.includes(idx) && ( +
+ handleChange(idx, "advancedConfig", e.target.value)} + style={{ + fontFamily: + "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace", + borderRadius: "0.3rem", + minHeight: "170px", + }} + /> +
+ )} +
+ { + e.preventDefault(); + handleRemove(idx); + }} + > + + +
+
+
+ ))} +
+ +
+ + ); +} diff --git a/frontend/src/components/Form/index.ts b/frontend/src/components/Form/index.ts index fc2eb00b..f218b2e3 100644 --- a/frontend/src/components/Form/index.ts +++ b/frontend/src/components/Form/index.ts @@ -3,6 +3,7 @@ export * from "./AccessField"; export * from "./BasicAuthFields"; export * from "./DNSProviderFields"; export * from "./DomainNamesField"; +export * from "./LocationsFields"; export * from "./NginxConfigField"; export * from "./SSLCertificateField"; export * from "./SSLOptionsFields"; diff --git a/frontend/src/components/SiteMenu.tsx b/frontend/src/components/SiteMenu.tsx index 63e12738..e38de683 100644 --- a/frontend/src/components/SiteMenu.tsx +++ b/frontend/src/components/SiteMenu.tsx @@ -25,33 +25,33 @@ const menuItems: MenuItem[] = [ { to: "/", icon: IconHome, - label: "dashboard.title", + label: "dashboard", }, { icon: IconDeviceDesktop, - label: "hosts.title", + label: "hosts", items: [ { to: "/nginx/proxy", - label: "proxy-hosts.title", + label: "proxy-hosts", permission: "proxyHosts", permissionType: "view", }, { to: "/nginx/redirection", - label: "redirection-hosts.title", + label: "redirection-hosts", permission: "redirectionHosts", permissionType: "view", }, { to: "/nginx/stream", - label: "streams.title", + label: "streams", permission: "streams", permissionType: "view", }, { to: "/nginx/404", - label: "dead-hosts.title", + label: "dead-hosts", permission: "deadHosts", permissionType: "view", }, @@ -60,33 +60,33 @@ const menuItems: MenuItem[] = [ { to: "/access", icon: IconLock, - label: "access.title", + label: "access-lists", permission: "accessLists", permissionType: "view", }, { to: "/certificates", icon: IconShield, - label: "certificates.title", + label: "certificates", permission: "certificates", permissionType: "view", }, { to: "/users", icon: IconUser, - label: "users.title", + label: "users", permission: "admin", }, { to: "/audit-log", icon: IconBook, - label: "auditlog.title", + label: "auditlogs", permission: "admin", }, { to: "/settings", icon: IconSettings, - label: "settings.title", + label: "settings", permission: "admin", }, ]; diff --git a/frontend/src/components/Table/Formatter/AccessListformatter.tsx b/frontend/src/components/Table/Formatter/AccessListformatter.tsx new file mode 100644 index 00000000..b5830fd9 --- /dev/null +++ b/frontend/src/components/Table/Formatter/AccessListformatter.tsx @@ -0,0 +1,24 @@ +import type { AccessList } from "src/api/backend"; +import { T } from "src/locale"; +import { showAccessListModal } from "src/modals"; + +interface Props { + access?: AccessList; +} +export function AccessListFormatter({ access }: Props) { + if (!access) { + return ; + } + return ( + + ); +} diff --git a/frontend/src/components/Table/Formatter/index.ts b/frontend/src/components/Table/Formatter/index.ts index 1b423179..7af50356 100644 --- a/frontend/src/components/Table/Formatter/index.ts +++ b/frontend/src/components/Table/Formatter/index.ts @@ -1,3 +1,4 @@ +export * from "./AccessListformatter"; export * from "./CertificateFormatter"; export * from "./DomainsFormatter"; export * from "./EmailFormatter"; diff --git a/frontend/src/components/index.ts b/frontend/src/components/index.ts index c8ab1762..861f637e 100644 --- a/frontend/src/components/index.ts +++ b/frontend/src/components/index.ts @@ -1,4 +1,5 @@ export * from "./Button"; +export * from "./EmptyData"; export * from "./ErrorNotFound"; export * from "./Flag"; export * from "./Form"; diff --git a/frontend/src/hooks/useAccessList.ts b/frontend/src/hooks/useAccessList.ts index b497428e..1f663858 100644 --- a/frontend/src/hooks/useAccessList.ts +++ b/frontend/src/hooks/useAccessList.ts @@ -52,6 +52,7 @@ const useSetAccessList = () => { queryClient.invalidateQueries({ queryKey: ["access-list", id] }); queryClient.invalidateQueries({ queryKey: ["access-lists"] }); queryClient.invalidateQueries({ queryKey: ["audit-logs"] }); + queryClient.invalidateQueries({ queryKey: ["proxy-hosts"] }); }, }); }; diff --git a/frontend/src/locale/IntlProvider.tsx b/frontend/src/locale/IntlProvider.tsx index a6160b2a..683a8e48 100644 --- a/frontend/src/locale/IntlProvider.tsx +++ b/frontend/src/locale/IntlProvider.tsx @@ -63,8 +63,33 @@ const changeLocale = (locale: string): void => { // This is a translation component that wraps the translation in a span with a data // attribute so devs can inspect the element to see the translation ID -const T = ({ id, data }: { id: string; data?: any }) => { - return {intl.formatMessage({ id }, data)}; +const T = ({ + id, + data, + tData, +}: { + id: string; + data?: Record; + tData?: Record; +}) => { + const translatedData: Record = {}; + if (tData) { + // iterate over tData and translate each value + Object.entries(tData).forEach(([key, value]) => { + translatedData[key] = intl.formatMessage({ id: value }); + }); + } + return ( + + {intl.formatMessage( + { id }, + { + ...data, + ...translatedData, + }, + )} + + ); }; export { localeOptions, getFlagCodeForLocale, getLocale, createIntl, changeLocale, intl, T }; diff --git a/frontend/src/locale/lang/de.json b/frontend/src/locale/lang/de.json index bb89fd18..809e5291 100644 --- a/frontend/src/locale/lang/de.json +++ b/frontend/src/locale/lang/de.json @@ -1,3 +1,3 @@ { - "dashboard.title": "Armaturenbrett" + "dashboard": "Armaturenbrett" } \ No newline at end of file diff --git a/frontend/src/locale/lang/en.json b/frontend/src/locale/lang/en.json index d94a9427..f80d0c98 100644 --- a/frontend/src/locale/lang/en.json +++ b/frontend/src/locale/lang/en.json @@ -1,33 +1,28 @@ { - "access.access-count": "{count} {count, plural, one {Rule} other {Rules}}", - "access.actions-title": "Access List #{id}", - "access.add": "Add Access List", - "access.auth-count": "{count} {count, plural, one {User} other {Users}}", - "access.edit": "Edit Access", - "access.empty": "There are no Access Lists", - "access.help-rules-last": "When at least 1 rule exists, this deny all rule will be added last", - "access.help.rules-order": "Note that the allow and deny directives will be applied in the order they are defined.", - "access.new": "New Access", - "access.pass-auth": "Pass Auth to Upstream", - "access.public": "Publicly Accessible", - "access.satisfy-any": "Satisfy Any", - "access.subtitle": "{users} {users, plural, one {User} other {Users}}, {rules} {rules, plural, one {Rule} other {Rules}} - Created: {date}", - "access.title": "Access", + "access-list": "Access List", + "access-list.access-count": "{count} {count, plural, one {Rule} other {Rules}}", + "access-list.auth-count": "{count} {count, plural, one {User} other {Users}}", + "access-list.help-rules-last": "When at least 1 rule exists, this deny all rule will be added last", + "access-list.help.rules-order": "Note that the allow and deny directives will be applied in the order they are defined.", + "access-list.pass-auth": "Pass Auth to Upstream", + "access-list.public": "Publicly Accessible", + "access-list.satisfy-any": "Satisfy Any", + "access-list.subtitle": "{users} {users, plural, one {User} other {Users}}, {rules} {rules, plural, one {Rule} other {Rules}} - Created: {date}", + "access-lists": "Access Lists", "action.add": "Add", + "action.add-location": "Add Location", + "action.close": "Close", "action.delete": "Delete", "action.disable": "Disable", "action.edit": "Edit", "action.enable": "Enable", "action.permissions": "Permissions", "action.view-details": "View Details", - "auditlog.title": "Audit Log", + "auditlogs": "Audit Logs", "cancel": "Cancel", - "certificates.actions-title": "Certificate #{id}", - "certificates.add": "Add Certificate", + "certificate": "Certificate", + "certificates": "Certificates", "certificates.custom": "Custom Certificate", - "certificates.empty": "There are no Certificates", - "certificates.title": "SSL Certificates", - "close": "Close", "column.access": "Access", "column.authorization": "Authorization", "column.authorizations": "Authorizations", @@ -52,16 +47,10 @@ "column.ssl": "SSL", "column.status": "Status", "created-on": "Created: {date}", - "dashboard.title": "Dashboard", - "dead-host.delete.content": "Are you sure you want to delete this 404 host?", - "dead-host.delete.title": "Delete 404 Host", - "dead-host.edit": "Edit 404 Host", - "dead-host.new": "New 404 Host", - "dead-hosts.actions-title": "404 Host #{id}", - "dead-hosts.add": "Add 404 Host", + "dashboard": "Dashboard", + "dead-host": "404 Host", + "dead-hosts": "404 Hosts", "dead-hosts.count": "{count} {count, plural, one {404 Host} other {404 Hosts}}", - "dead-hosts.empty": "There are no 404 Hosts", - "dead-hosts.title": "404 Hosts", "disabled": "Disabled", "domain-names": "Domain Names", "domain-names.max": "{count} domain names maximum", @@ -102,7 +91,6 @@ "event.updated-redirection-host": "Updated Redirection Host", "event.updated-user": "Updated User", "footer.github-fork": "Fork me on Github", - "generic.flags.title": "Options", "host.flags.block-exploits": "Block Common Exploits", "host.flags.cache-assets": "Cache Assets", "host.flags.preserve-path": "Preserve Path", @@ -110,7 +98,7 @@ "host.flags.websockets-upgrade": "Websockets Support", "host.forward-port": "Forward Port", "host.forward-scheme": "Scheme", - "hosts.title": "Hosts", + "hosts": "Hosts", "http-only": "HTTP Only", "lets-encrypt": "Let's Encrypt", "loading": "Loading…", @@ -119,27 +107,23 @@ "nginx-config.placeholder": "# Enter your custom Nginx configuration here at your own risk!", "no-permission-error": "You do not have access to view this.", "notfound.action": "Take me home", - "notfound.text": "We are sorry but the page you are looking for was not found", + "notfound.content": "We are sorry but the page you are looking for was not found", "notfound.title": "Oops… You just found an error page", - "notification.access-deleted": "Access has been deleted", - "notification.access-saved": "Access has been saved", - "notification.dead-host-saved": "404 Host has been saved", "notification.error": "Error", - "notification.host-deleted": "Host has been deleted", - "notification.host-disabled": "Host has been disabled", - "notification.host-enabled": "Host has been enabled", - "notification.proxy-host-saved": "Proxy Host has been saved", - "notification.redirection-host-saved": "Redirection Host has been saved", - "notification.stream-deleted": "Stream has been deleted", - "notification.stream-disabled": "Stream has been disabled", - "notification.stream-enabled": "Stream has been enabled", + "notification.object-deleted": "{object} has been deleted", + "notification.object-disabled": "{object} has been disabled", + "notification.object-enabled": "{object} has been enabled", + "notification.object-saved": "{object} has been saved", "notification.success": "Success", - "notification.user-deleted": "User has been deleted", - "notification.user-disabled": "User has been disabled", - "notification.user-enabled": "User has been enabled", - "notification.user-saved": "User has been saved", + "object.actions-title": "{object} #{id}", + "object.add": "Add {object}", + "object.delete": "Delete {object}", + "object.delete.content": "Are you sure you want to delete this {object}?", + "object.edit": "Edit {object}", + "object.empty": "There are no {objects}", "offline": "Offline", "online": "Online", + "options": "Options", "password": "Password", "password.generate": "Generate random password", "password.hide": "Hide Password", @@ -150,55 +134,37 @@ "permissions.visibility.all": "All Items", "permissions.visibility.title": "Item Visibility", "permissions.visibility.user": "Created Items Only", - "proxy-host.edit": "Edit Proxy Host", + "proxy-host": "Proxy Host", "proxy-host.forward-host": "Forward Hostname / IP", - "proxy-host.new": "New Proxy Host", - "proxy-hosts.actions-title": "Proxy Host #{id}", - "proxy-hosts.add": "Add Proxy Host", + "proxy-hosts": "Proxy Hosts", "proxy-hosts.count": "{count} {count, plural, one {Proxy Host} other {Proxy Hosts}}", - "proxy-hosts.empty": "There are no Proxy Hosts", - "proxy-hosts.title": "Proxy Hosts", - "redirection-host.delete.content": "Are you sure you want to delete this Redirection host?", - "redirection-host.delete.title": "Delete Redirection Host", + "public": "Public", + "redirection-host": "Redirection Host", "redirection-host.forward-domain": "Forward Domain", - "redirection-host.new": "New Redirection Host", - "redirection-hosts.actions-title": "Redirection Host #{id}", - "redirection-hosts.add": "Add Redirection Host", + "redirection-hosts": "Redirection Hosts", "redirection-hosts.count": "{count} {count, plural, one {Redirection Host} other {Redirection Hosts}}", - "redirection-hosts.empty": "There are no Redirection Hosts", - "redirection-hosts.title": "Redirection Hosts", "role.admin": "Administrator", "role.standard-user": "Standard User", "save": "Save", - "settings.title": "Settings", + "settings": "Settings", "setup.preamble": "Get started by creating your admin account.", "setup.title": "Welcome!", "sign-in": "Sign in", "ssl-certificate": "SSL Certificate", - "stream.delete.content": "Are you sure you want to delete this Stream?", - "stream.delete.title": "Delete Stream", - "stream.edit": "Edit Stream", + "stream": "Stream", "stream.forward-host": "Forward Host", "stream.incoming-port": "Incoming Port", - "stream.new": "New Stream", - "streams.actions-title": "Stream #{id}", - "streams.add": "Add Stream", + "streams": "Streams", "streams.count": "{count} {count, plural, one {Stream} other {Streams}}", - "streams.empty": "There are no Streams", "streams.tcp": "TCP", - "streams.title": "Streams", "streams.udp": "UDP", + "user": "User", "user.change-password": "Change Password", "user.confirm-password": "Confirm Password", "user.current-password": "Current Password", - "user.delete.content": "Are you sure you want to delete this user?", - "user.delete.title": "Delete User", - "user.edit": "Edit User", "user.edit-profile": "Edit Profile", - "user.flags.title": "Properties", "user.full-name": "Full Name", "user.logout": "Logout", - "user.new": "New User", "user.new-password": "New Password", "user.nickname": "Nickname", "user.set-password": "Set Password", @@ -206,8 +172,5 @@ "user.switch-dark": "Switch to Dark mode", "user.switch-light": "Switch to Light mode", "username": "Username", - "users.actions-title": "User #{id}", - "users.add": "Add User", - "users.empty": "There are no Users", - "users.title": "Users" + "users": "Users" } \ No newline at end of file diff --git a/frontend/src/locale/lang/fa.json b/frontend/src/locale/lang/fa.json index 77cecfad..8f002c11 100644 --- a/frontend/src/locale/lang/fa.json +++ b/frontend/src/locale/lang/fa.json @@ -1,3 +1,3 @@ { - "dashboard.title": "داشبورد" + "dashboard": "داشبورد" } \ No newline at end of file diff --git a/frontend/src/locale/src/de.json b/frontend/src/locale/src/de.json index 2b2ab546..f6fcf1fd 100644 --- a/frontend/src/locale/src/de.json +++ b/frontend/src/locale/src/de.json @@ -1,5 +1,5 @@ { - "dashboard.title": { + "dashboard": { "defaultMessage": "Armaturenbrett" } } diff --git a/frontend/src/locale/src/en.json b/frontend/src/locale/src/en.json index ebf66ecf..d3ab6c98 100644 --- a/frontend/src/locale/src/en.json +++ b/frontend/src/locale/src/en.json @@ -1,49 +1,43 @@ { - "access.access-count": { + "access-list": { + "defaultMessage": "Access List" + }, + "access-list.access-count": { "defaultMessage": "{count} {count, plural, one {Rule} other {Rules}}" }, - "access.actions-title": { - "defaultMessage": "Access List #{id}" - }, - "access.add": { - "defaultMessage": "Add Access List" - }, - "access.auth-count": { + "access-list.auth-count": { "defaultMessage": "{count} {count, plural, one {User} other {Users}}" }, - "access.edit": { - "defaultMessage": "Edit Access" - }, - "access.empty": { - "defaultMessage": "There are no Access Lists" - }, - "access.help-rules-last": { + "access-list.help-rules-last": { "defaultMessage": "When at least 1 rule exists, this deny all rule will be added last" }, - "access.help.rules-order": { + "access-list.help.rules-order": { "defaultMessage": "Note that the allow and deny directives will be applied in the order they are defined." }, - "access.new": { - "defaultMessage": "New Access" - }, - "access.pass-auth": { + "access-list.pass-auth": { "defaultMessage": "Pass Auth to Upstream" }, - "access.public": { + "access-list.public": { "defaultMessage": "Publicly Accessible" }, - "access.satisfy-any": { + "access-list.satisfy-any": { "defaultMessage": "Satisfy Any" }, - "access.subtitle": { + "access-list.subtitle": { "defaultMessage": "{users} {users, plural, one {User} other {Users}}, {rules} {rules, plural, one {Rule} other {Rules}} - Created: {date}" }, - "access.title": { - "defaultMessage": "Access" + "access-lists": { + "defaultMessage": "Access Lists" }, "action.add": { "defaultMessage": "Add" }, + "action.add-location": { + "defaultMessage": "Add Location" + }, + "action.close": { + "defaultMessage": "Close" + }, "action.delete": { "defaultMessage": "Delete" }, @@ -62,30 +56,21 @@ "action.view-details": { "defaultMessage": "View Details" }, - "auditlog.title": { - "defaultMessage": "Audit Log" + "auditlogs": { + "defaultMessage": "Audit Logs" }, "cancel": { "defaultMessage": "Cancel" }, - "certificates.actions-title": { - "defaultMessage": "Certificate #{id}" + "certificate": { + "defaultMessage": "Certificate" }, - "certificates.add": { - "defaultMessage": "Add Certificate" + "certificates": { + "defaultMessage": "Certificates" }, "certificates.custom": { "defaultMessage": "Custom Certificate" }, - "certificates.empty": { - "defaultMessage": "There are no Certificates" - }, - "certificates.title": { - "defaultMessage": "SSL Certificates" - }, - "close": { - "defaultMessage": "Close" - }, "column.access": { "defaultMessage": "Access" }, @@ -158,36 +143,18 @@ "created-on": { "defaultMessage": "Created: {date}" }, - "dashboard.title": { + "dashboard": { "defaultMessage": "Dashboard" }, - "dead-host.delete.content": { - "defaultMessage": "Are you sure you want to delete this 404 host?" + "dead-host": { + "defaultMessage": "404 Host" }, - "dead-host.delete.title": { - "defaultMessage": "Delete 404 Host" - }, - "dead-host.edit": { - "defaultMessage": "Edit 404 Host" - }, - "dead-host.new": { - "defaultMessage": "New 404 Host" - }, - "dead-hosts.actions-title": { - "defaultMessage": "404 Host #{id}" - }, - "dead-hosts.add": { - "defaultMessage": "Add 404 Host" + "dead-hosts": { + "defaultMessage": "404 Hosts" }, "dead-hosts.count": { "defaultMessage": "{count} {count, plural, one {404 Host} other {404 Hosts}}" }, - "dead-hosts.empty": { - "defaultMessage": "There are no 404 Hosts" - }, - "dead-hosts.title": { - "defaultMessage": "404 Hosts" - }, "disabled": { "defaultMessage": "Disabled" }, @@ -308,9 +275,6 @@ "footer.github-fork": { "defaultMessage": "Fork me on Github" }, - "generic.flags.title": { - "defaultMessage": "Options" - }, "host.flags.block-exploits": { "defaultMessage": "Block Common Exploits" }, @@ -332,7 +296,7 @@ "host.forward-scheme": { "defaultMessage": "Scheme" }, - "hosts.title": { + "hosts": { "defaultMessage": "Hosts" }, "http-only": { @@ -359,62 +323,47 @@ "notfound.action": { "defaultMessage": "Take me home" }, - "notfound.text": { + "notfound.content": { "defaultMessage": "We are sorry but the page you are looking for was not found" }, "notfound.title": { "defaultMessage": "Oops… You just found an error page" }, - "notification.access-deleted": { - "defaultMessage": "Access has been deleted" - }, - "notification.access-saved": { - "defaultMessage": "Access has been saved" - }, - "notification.dead-host-saved": { - "defaultMessage": "404 Host has been saved" - }, "notification.error": { "defaultMessage": "Error" }, - "notification.host-deleted": { - "defaultMessage": "Host has been deleted" + "notification.object-deleted": { + "defaultMessage": "{object} has been deleted" }, - "notification.host-disabled": { - "defaultMessage": "Host has been disabled" + "notification.object-disabled": { + "defaultMessage": "{object} has been disabled" }, - "notification.host-enabled": { - "defaultMessage": "Host has been enabled" + "notification.object-enabled": { + "defaultMessage": "{object} has been enabled" }, - "notification.proxy-host-saved": { - "defaultMessage": "Proxy Host has been saved" - }, - "notification.redirection-host-saved": { - "defaultMessage": "Redirection Host has been saved" - }, - "notification.stream-deleted": { - "defaultMessage": "Stream has been deleted" - }, - "notification.stream-disabled": { - "defaultMessage": "Stream has been disabled" - }, - "notification.stream-enabled": { - "defaultMessage": "Stream has been enabled" + "notification.object-saved": { + "defaultMessage": "{object} has been saved" }, "notification.success": { "defaultMessage": "Success" }, - "notification.user-deleted": { - "defaultMessage": "User has been deleted" + "object.actions-title": { + "defaultMessage": "{object} #{id}" }, - "notification.user-disabled": { - "defaultMessage": "User has been disabled" + "object.add": { + "defaultMessage": "Add {object}" }, - "notification.user-enabled": { - "defaultMessage": "User has been enabled" + "object.delete": { + "defaultMessage": "Delete {object}" }, - "notification.user-saved": { - "defaultMessage": "User has been saved" + "object.delete.content": { + "defaultMessage": "Are you sure you want to delete this {object}?" + }, + "object.edit": { + "defaultMessage": "Edit {object}" + }, + "object.empty": { + "defaultMessage": "There are no {objects}" }, "offline": { "defaultMessage": "Offline" @@ -422,6 +371,9 @@ "online": { "defaultMessage": "Online" }, + "options": { + "defaultMessage": "Options" + }, "password": { "defaultMessage": "Password" }, @@ -452,57 +404,33 @@ "permissions.visibility.user": { "defaultMessage": "Created Items Only" }, - "proxy-host.edit": { - "defaultMessage": "Edit Proxy Host" + "proxy-host": { + "defaultMessage": "Proxy Host" }, "proxy-host.forward-host": { "defaultMessage": "Forward Hostname / IP" }, - "proxy-host.new": { - "defaultMessage": "New Proxy Host" - }, - "proxy-hosts.actions-title": { - "defaultMessage": "Proxy Host #{id}" - }, - "proxy-hosts.add": { - "defaultMessage": "Add Proxy Host" + "proxy-hosts": { + "defaultMessage": "Proxy Hosts" }, "proxy-hosts.count": { "defaultMessage": "{count} {count, plural, one {Proxy Host} other {Proxy Hosts}}" }, - "proxy-hosts.empty": { - "defaultMessage": "There are no Proxy Hosts" + "public": { + "defaultMessage": "Public" }, - "proxy-hosts.title": { - "defaultMessage": "Proxy Hosts" - }, - "redirection-host.delete.content": { - "defaultMessage": "Are you sure you want to delete this Redirection host?" - }, - "redirection-host.delete.title": { - "defaultMessage": "Delete Redirection Host" + "redirection-host": { + "defaultMessage": "Redirection Host" }, "redirection-host.forward-domain": { "defaultMessage": "Forward Domain" }, - "redirection-host.new": { - "defaultMessage": "New Redirection Host" - }, - "redirection-hosts.actions-title": { - "defaultMessage": "Redirection Host #{id}" - }, - "redirection-hosts.add": { - "defaultMessage": "Add Redirection Host" + "redirection-hosts": { + "defaultMessage": "Redirection Hosts" }, "redirection-hosts.count": { "defaultMessage": "{count} {count, plural, one {Redirection Host} other {Redirection Hosts}}" }, - "redirection-hosts.empty": { - "defaultMessage": "There are no Redirection Hosts" - }, - "redirection-hosts.title": { - "defaultMessage": "Redirection Hosts" - }, "role.admin": { "defaultMessage": "Administrator" }, @@ -512,7 +440,7 @@ "save": { "defaultMessage": "Save" }, - "settings.title": { + "settings": { "defaultMessage": "Settings" }, "setup.preamble": { @@ -527,14 +455,8 @@ "ssl-certificate": { "defaultMessage": "SSL Certificate" }, - "stream.delete.content": { - "defaultMessage": "Are you sure you want to delete this Stream?" - }, - "stream.delete.title": { - "defaultMessage": "Delete Stream" - }, - "stream.edit": { - "defaultMessage": "Edit Stream" + "stream": { + "defaultMessage": "Stream" }, "stream.forward-host": { "defaultMessage": "Forward Host" @@ -542,30 +464,21 @@ "stream.incoming-port": { "defaultMessage": "Incoming Port" }, - "stream.new": { - "defaultMessage": "New Stream" - }, - "streams.actions-title": { - "defaultMessage": "Stream #{id}" - }, - "streams.add": { - "defaultMessage": "Add Stream" + "streams": { + "defaultMessage": "Streams" }, "streams.count": { "defaultMessage": "{count} {count, plural, one {Stream} other {Streams}}" }, - "streams.empty": { - "defaultMessage": "There are no Streams" - }, "streams.tcp": { "defaultMessage": "TCP" }, - "streams.title": { - "defaultMessage": "Streams" - }, "streams.udp": { "defaultMessage": "UDP" }, + "user": { + "defaultMessage": "User" + }, "user.change-password": { "defaultMessage": "Change Password" }, @@ -575,30 +488,15 @@ "user.current-password": { "defaultMessage": "Current Password" }, - "user.delete.content": { - "defaultMessage": "Are you sure you want to delete this user?" - }, - "user.delete.title": { - "defaultMessage": "Delete User" - }, - "user.edit": { - "defaultMessage": "Edit User" - }, "user.edit-profile": { "defaultMessage": "Edit Profile" }, - "user.flags.title": { - "defaultMessage": "Properties" - }, "user.full-name": { "defaultMessage": "Full Name" }, "user.logout": { "defaultMessage": "Logout" }, - "user.new": { - "defaultMessage": "New User" - }, "user.new-password": { "defaultMessage": "New Password" }, @@ -620,16 +518,7 @@ "username": { "defaultMessage": "Username" }, - "users.actions-title": { - "defaultMessage": "User #{id}" - }, - "users.add": { - "defaultMessage": "Add User" - }, - "users.empty": { - "defaultMessage": "There are no Users" - }, - "users.title": { + "users": { "defaultMessage": "Users" } } diff --git a/frontend/src/locale/src/fa.json b/frontend/src/locale/src/fa.json index 03679a36..84f5de46 100644 --- a/frontend/src/locale/src/fa.json +++ b/frontend/src/locale/src/fa.json @@ -1,5 +1,5 @@ { - "dashboard.title": { + "dashboard": { "defaultMessage": "داشبورد" } } diff --git a/frontend/src/modals/AccessListModal.tsx b/frontend/src/modals/AccessListModal.tsx index b229ef62..79537f5c 100644 --- a/frontend/src/modals/AccessListModal.tsx +++ b/frontend/src/modals/AccessListModal.tsx @@ -9,7 +9,7 @@ import { AccessClientFields, BasicAuthFields, Button, Loading } from "src/compon import { useAccessList, useSetAccessList } from "src/hooks"; import { intl, T } from "src/locale"; import { validateString } from "src/modules/Validations"; -import { showSuccess } from "src/notifications"; +import { showObjectSuccess } from "src/notifications"; const showAccessListModal = (id: number | "new") => { EasyModal.show(AccessListModal, { id }); @@ -72,7 +72,7 @@ const AccessListModal = EasyModal.create(({ id, visible, remove }: Props) => { setAccessList(payload, { onError: (err: any) => setErrorMsg(), onSuccess: () => { - showSuccess(intl.formatMessage({ id: "notification.access-saved" })); + showObjectSuccess("access-list", "saved"); remove(); }, onSettled: () => { @@ -110,7 +110,7 @@ const AccessListModal = EasyModal.create(({ id, visible, remove }: Props) => {
- + @@ -186,13 +186,13 @@ const AccessListModal = EasyModal.create(({ id, visible, remove }: Props) => {

- +