├── .editorconfig
├── .eslintrc
├── .github
└── ISSUE_TEMPLATE
│ ├── bug-report-for-new-version.md
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── buildUtils
├── webpack.development.js
└── webpack.production.js
├── openapi.config.json
├── openapitools.json
├── package-lock.json
├── package.json
├── prettier.config.js
├── public
├── favicon
│ ├── android-icon-144x144.png
│ ├── android-icon-192x192.png
│ ├── android-icon-36x36.png
│ ├── android-icon-48x48.png
│ ├── android-icon-72x72.png
│ ├── android-icon-96x96.png
│ ├── apple-icon-114x114.png
│ ├── apple-icon-120x120.png
│ ├── apple-icon-144x144.png
│ ├── apple-icon-152x152.png
│ ├── apple-icon-180x180.png
│ ├── apple-icon-57x57.png
│ ├── apple-icon-60x60.png
│ ├── apple-icon-72x72.png
│ ├── apple-icon-76x76.png
│ ├── apple-icon-precomposed.png
│ ├── apple-icon.png
│ ├── browserconfig.xml
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── favicon.ico
│ ├── manifest.json
│ ├── ms-icon-144x144.png
│ ├── ms-icon-150x150.png
│ ├── ms-icon-310x310.png
│ └── ms-icon-70x70.png
├── index.html
├── manifest.json
├── robots.txt
├── style.css
└── svg
│ ├── loading.svg
│ └── wildduck.png
├── src
├── assets
│ └── icons
│ │ ├── DkimIcon.tsx
│ │ ├── DomainAccessIcon.tsx
│ │ ├── DomainAliasIcon.tsx
│ │ ├── ForwardedAddressesIcon.tsx
│ │ ├── RecalculateQuotaIcon.tsx
│ │ ├── ResetPasswordIcon.tsx
│ │ ├── WildDuckIcon.tsx
│ │ └── wildduck.png
├── client
│ ├── AxiosClient.ts
│ ├── RequestClient.ts
│ └── wildduck-api
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── .openapi-generator-ignore
│ │ ├── .openapi-generator
│ │ ├── FILES
│ │ └── VERSION
│ │ ├── api.ts
│ │ ├── base.ts
│ │ ├── common.ts
│ │ ├── configuration.ts
│ │ ├── git_push.sh
│ │ └── index.ts
├── components
│ ├── AccessToken
│ │ ├── AccessToken.tsx
│ │ └── index.ts
│ ├── Address
│ │ ├── Address.tsx
│ │ ├── AddressInformation.tsx
│ │ ├── AddressInformationForm.tsx
│ │ ├── AddressTable.tsx
│ │ ├── Columns.tsx
│ │ └── index.ts
│ ├── App
│ │ ├── App.tsx
│ │ └── index.tsx
│ ├── Archive
│ │ ├── Archive.tsx
│ │ ├── ArchiveTable.tsx
│ │ ├── Columns.tsx
│ │ ├── RestoreAllMessagesModal.tsx
│ │ └── index.ts
│ ├── Authentication
│ │ ├── Authentication.tsx
│ │ ├── AuthenticationTable.tsx
│ │ ├── Columns.tsx
│ │ └── index.ts
│ ├── Autoreplies
│ │ ├── Autoreplies.tsx
│ │ ├── AutorepliesForm.tsx
│ │ └── index.ts
│ ├── ContentArea
│ │ ├── ContentArea.tsx
│ │ └── index.ts
│ ├── CreateDkim
│ │ ├── CreateDkim.tsx
│ │ └── index.ts
│ ├── CreateNewAddress
│ │ ├── CreateNewAddress.tsx
│ │ ├── CreateNewAddressForm.tsx
│ │ └── index.ts
│ ├── CreateNewDomainAlias
│ │ ├── CreateNewDomainAlias.tsx
│ │ ├── CreateNewDomainAliasForm.tsx
│ │ └── index.ts
│ ├── CreateNewForwardedAddress
│ │ ├── CreateNewForwardedAddress.tsx
│ │ ├── CreateNewForwardedAddressForm.tsx
│ │ └── index.ts
│ ├── CreateNewUser
│ │ ├── CreateNewUser.tsx
│ │ ├── CreateNewUserForm.tsx
│ │ └── index.ts
│ ├── CustomLink
│ │ └── index.tsx
│ ├── Dkim
│ │ ├── Dkim.tsx
│ │ ├── DkimColumns.tsx
│ │ ├── DkimTable.tsx
│ │ └── index.ts
│ ├── DkimDetails
│ │ ├── DkimDetails.tsx
│ │ └── index.ts
│ ├── DomainAccess
│ │ ├── DomainAccess.tsx
│ │ └── index.ts
│ ├── DomainAliases
│ │ ├── Columns.tsx
│ │ ├── DomainAliases.tsx
│ │ ├── DomainAliasesTable.tsx
│ │ ├── SearchAlias.tsx
│ │ └── index.ts
│ ├── ErrorBoundary
│ │ ├── ErrorBoundary.tsx
│ │ ├── ErrorPage.tsx
│ │ └── index.ts
│ ├── Filters
│ │ ├── AddFiltersForm.tsx
│ │ ├── Filters.tsx
│ │ ├── FiltersTable.tsx
│ │ └── index.ts
│ ├── FloatingButton.tsx
│ ├── FormLayout.ts
│ ├── ForwardedAddress
│ │ ├── Columns.tsx
│ │ ├── ForwardedAddress.tsx
│ │ ├── ForwardedAddressTable.tsx
│ │ ├── RenameDomain.tsx
│ │ └── index.ts
│ ├── ForwardedAddressInformation
│ │ ├── ForwardedAddressInformation.tsx
│ │ ├── ForwardedAddressInformationForm.tsx
│ │ ├── ListTarget.tsx
│ │ └── index.ts
│ ├── Header
│ │ ├── Header.tsx
│ │ └── index.ts
│ ├── HtmlRenderer
│ │ ├── HtmlRenderer.tsx
│ │ └── index.ts
│ ├── LoaderBoundary
│ │ ├── LoaderBoundary.tsx
│ │ └── index.ts
│ ├── LoadingPage
│ │ ├── LoadingPage.tsx
│ │ └── index.ts
│ ├── Mailboxes
│ │ ├── Columns.tsx
│ │ ├── MailboxEditForm.tsx
│ │ ├── MailboxSearch.tsx
│ │ ├── Mailboxes.tsx
│ │ ├── MailboxesTable.tsx
│ │ └── index.ts
│ ├── Messages
│ │ ├── MailboxMessages.tsx
│ │ ├── MessageActions.tsx
│ │ ├── MessageDetails.tsx
│ │ ├── MessageSource.tsx
│ │ ├── Messages.tsx
│ │ ├── MessagesList.tsx
│ │ ├── MessagesSearch.tsx
│ │ └── index.ts
│ ├── NavigationBar
│ │ ├── NavigationBar.tsx
│ │ └── index.ts
│ ├── Page
│ │ ├── Page.tsx
│ │ └── index.ts
│ ├── ResolveId
│ │ ├── ResolveId.tsx
│ │ └── index.ts
│ ├── User
│ │ ├── User.tsx
│ │ ├── UserDetailsForm.tsx
│ │ └── index.ts
│ ├── Users
│ │ ├── Columns.tsx
│ │ ├── FilterSearch.tsx
│ │ ├── ManageActions.tsx
│ │ ├── ResetPassword.tsx
│ │ ├── Users.tsx
│ │ ├── UsersTable.tsx
│ │ └── index.ts
│ ├── Widgets
│ │ └── Link.tsx
│ └── index.tsx
├── config
│ └── menuConfig.ts
├── hooks
│ ├── useAddress.ts
│ ├── useAddressInformation.ts
│ ├── useAllowedList.ts
│ ├── useArchive.ts
│ ├── useAuthentication.ts
│ ├── useAutoreplyDetails.ts
│ ├── useBlockedList.ts
│ ├── useCreateAddress.ts
│ ├── useCreateAllowedDomain.ts
│ ├── useCreateBlockedDomain.ts
│ ├── useCreateDkim.ts
│ ├── useCreateDomainAliases.ts
│ ├── useCreateFilter.ts
│ ├── useCreateForwardedAddress.ts
│ ├── useCreateUser.ts
│ ├── useDeleteAddress.ts
│ ├── useDeleteAutoreply.ts
│ ├── useDeleteDkim.ts
│ ├── useDeleteDomain.ts
│ ├── useDeleteDomainAliases.ts
│ ├── useDeleteFilter.ts
│ ├── useDeleteForwardedAddress.ts
│ ├── useDeleteMessage.ts
│ ├── useDeleteMessagesInMailbox.ts
│ ├── useDeleteUser.ts
│ ├── useDkim.ts
│ ├── useDkimDetails.ts
│ ├── useDomainAliases.ts
│ ├── useDownloadAttachment.ts
│ ├── useFIlterDetails.ts
│ ├── useFilters.ts
│ ├── useForwardedAddress.ts
│ ├── useForwardedAddressInformation.ts
│ ├── useLogoutUser.ts
│ ├── useMailboxes.ts
│ ├── useMessageDetails.ts
│ ├── useMessageSource.ts
│ ├── useMessages.ts
│ ├── useRecalculateQuota.ts
│ ├── useRecalculateQuotaForAll.ts
│ ├── useRenameDomain.ts
│ ├── useResetPassword.ts
│ ├── useRestoreArchiveMessage.ts
│ ├── useRestoreArchiveMessages.ts
│ ├── useUpdateAddress.ts
│ ├── useUpdateAutoreply.ts
│ ├── useUpdateFilter.ts
│ ├── useUpdateForwardedAddress.ts
│ ├── useUpdateMailbox.ts
│ ├── useUpdateUserDetails.ts
│ ├── useUserDetails.ts
│ └── useUsers.ts
├── lib
│ ├── axios
│ │ └── AxiosInterceptors.ts
│ └── constants
│ │ ├── Formatter.ts
│ │ └── constant.ts
├── logic
│ ├── addressLogic.ts
│ ├── appLogic.ts
│ ├── archiveLogic.ts
│ ├── authenticationLogic.ts
│ ├── dkimLogic.ts
│ ├── domainAccessLogic.ts
│ ├── domainAliasesLogic.ts
│ ├── filtersLogic.ts
│ ├── mailboxesLogic.ts
│ ├── messagesLogic.ts
│ ├── navigationLogic.ts
│ └── usersLogic.ts
├── react-query.config.ts
├── store
│ └── index.ts
├── styles
│ ├── antd.less
│ └── style.css
├── types
│ ├── address.d.ts
│ ├── axios.d.ts
│ ├── dkim.d.ts
│ ├── domainAliases.d.ts
│ ├── navigationBar.d.ts
│ ├── storage.d.ts
│ └── users.d.ts
└── utils
│ ├── AppEvents.ts
│ ├── FilterDropDown.tsx
│ ├── FilterDropdownStyle.css
│ ├── Pagination.tsx
│ ├── constants.ts
│ ├── getColumnsWithFilterAndSort.tsx
│ ├── getUniqValuesBy.ts
│ ├── handleError.ts
│ ├── logicUtils.ts
│ └── showConfirm.ts
├── tsconfig.json
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | indent_size = 4
6 | tab_size = 4
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = true
14 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "ignorePatterns": ["src/assets/icons/*"],
4 | "settings": {
5 | "react": {
6 | "version": "detect"
7 | }
8 | },
9 | "env": {
10 | "browser": true,
11 | "node": true,
12 | "commonjs": true,
13 | "es6": true
14 | },
15 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react/recommended"],
16 | "parser": "@typescript-eslint/parser",
17 | "parserOptions": {
18 | "ecmaFeatures": {
19 | "jsx": true
20 | },
21 | "ecmaVersion": 2018,
22 | "sourceType": "module"
23 | },
24 | "plugins": ["eslint-plugin-react", "@typescript-eslint", "react"],
25 | "rules": {
26 | "no-console": 0,
27 | "@typescript-eslint/no-explicit-any": 0,
28 | "react/display-name": 0,
29 | "@typescript-eslint/interface-name-prefix": 0,
30 | "@typescript-eslint/explicit-member-accessibility": 0,
31 | "@typescript-eslint/array-type": 0,
32 | "@typescript-eslint/no-var-requires": 0,
33 | "@typescript-eslint/explicit-function-return-type": 0,
34 | "@typescript-eslint/no-unused-vars": 0,
35 | "@typescript-eslint/indent": [
36 | "error",
37 | "tab",
38 | {
39 | "SwitchCase": 1
40 | }
41 | ],
42 | "quotes": [
43 | "error",
44 | "single",
45 | {
46 | "allowTemplateLiterals": true
47 | }
48 | ],
49 | "semi": ["error", "always"],
50 | "max-len": [
51 | "error",
52 | {
53 | "code": 120,
54 | "tabWidth": 4
55 | }
56 | ]
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report-for-new-version.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report For New Version
3 | about: Describe this issue template's purpose here.
4 | title: "[NEW-VERSION-BUG]"
5 | labels: new-version-bug
6 | assignees: Lakkanna
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See an error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **What device are you on?**
27 |
28 | **Which node version are you using?**
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: Lakkanna
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See an error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **What device are you on?**
27 |
28 | **Which Node version are you using?**
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE]"
5 | labels: enhancement
6 | assignees: Lakkanna
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/.gitmodules
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## [Unreleased]
4 |
5 | - Making project open source
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Kesav Kolla
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Administrative UI for WildDuck IMAP server
7 |
8 |
9 |
16 |
17 | ## Setup
18 |
19 | ```js
20 | git clone https://github.com/softwareartistry/wildduck-ui.git
21 |
22 | cd wildduck-ui
23 | npm install --legacy-peer-deps
24 | npm run dev
25 |
26 | ```
27 |
28 | \* Note Currently project supports node version below or v14.16.0
29 |
30 | ### Dev Server
31 |
32 | `npm run dev`
33 |
34 |
35 |
36 | ### Pre-requisite
37 |
38 | - Need IMAP Server endpoint to make API calls
39 | - Access Token
40 |
41 | - You can find accessToken that is setup in your server, which locates in `/opt/wildduck/config/api.toml`
42 | - If accessToken is commentend please uncomment and set secure accessToken, example
43 |
44 | ```toml
45 | # If set requires all API calls to have accessToken query argument with that value
46 |
47 | #accessToken="somesecretvalue"
48 |
49 | accessToken="somesecretvalue"
50 | ```
51 |
52 | ### Tech Stack
53 |
54 | - [React](https://reactjs.org/)
55 | - [Typescript](https://www.typescriptlang.org/)
56 | - [React Query](https://react-query.tanstack.com/)
57 | - [KeaJS](https://kea.js.org/)
58 | - [Ant Design](https://ant.design/)
59 | - Open Api ( [_@openapitools/openapi-generator-cli_](https://github.com/OpenAPITools/openapi-generator-cli) to
60 | generate API's from https://docs.wildduck.email/api/openapi.yml)
61 |
62 | wildduck-ui
63 |
64 | ```shell
65 | git add [files]
66 | git commit -m 'your commit message'
67 | git push
68 | ```
69 |
70 | ## Contributions
71 |
72 | Project is open to contributions, but I recommend creating an issue or replying in a comment to let me know what you are
73 | working on first that way we don't overwrite each other.
74 |
75 | Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on this project.
76 |
77 | ## Code of Conduct
78 |
79 | Please read [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) for details on our code of conduct.
80 |
--------------------------------------------------------------------------------
/buildUtils/webpack.development.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 |
4 | module.exports = {
5 | mode: 'development',
6 | devtool: 'inline-source-map',
7 | output: {
8 | publicPath: '/',
9 | filename: 'bundle.js',
10 | chunkFilename: 'bundle.[name].js',
11 | },
12 | module: {
13 | rules: [
14 | {
15 | test: /\.less$/,
16 | include: /(src)/,
17 | use: [
18 | { loader: 'style-loader' },
19 | { loader: 'css-loader' },
20 | {
21 | loader: 'less-loader',
22 | options: {
23 | lessOptions: {
24 | javascriptEnabled: true,
25 | },
26 | },
27 | },
28 | ],
29 | },
30 | {
31 | test: /\.css$/,
32 | use: ['style-loader', 'css-loader'],
33 | },
34 | ],
35 | },
36 | plugins: [new webpack.HotModuleReplacementPlugin()],
37 | devServer: {
38 | compress: true,
39 | contentBase: path.join(__dirname, 'dist'),
40 | historyApiFallback: true,
41 | host: '0.0.0.0',
42 | hot: true,
43 | port: 3000,
44 | progress: true,
45 | watchContentBase: true,
46 | clientLogLevel: 'error',
47 | },
48 | };
49 |
--------------------------------------------------------------------------------
/buildUtils/webpack.production.js:
--------------------------------------------------------------------------------
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
2 |
3 | module.exports = {
4 | mode: 'production',
5 | output: {
6 | filename: 'bundle.main.[contenthash:8].js',
7 | chunkFilename: 'bundle.[name].[contenthash:8].js',
8 | },
9 | module: {
10 | rules: [
11 | {
12 | test: /\.less$/,
13 | include: /(src)/,
14 | use: [
15 | { loader: MiniCssExtractPlugin.loader },
16 | { loader: 'css-loader' },
17 | {
18 | loader: 'less-loader',
19 | options: {
20 | lessOptions: {
21 | javascriptEnabled: true,
22 | },
23 | },
24 | },
25 | ],
26 | },
27 | {
28 | test: /\.css$/,
29 | use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader'],
30 | },
31 | ],
32 | },
33 | plugins: [
34 | new MiniCssExtractPlugin({
35 | filename: '[name].[hash].css',
36 | chunkFilename: '[id].[hash].css',
37 | }),
38 | ],
39 | };
40 |
--------------------------------------------------------------------------------
/openapi.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "supportsES6": true,
3 | "withoutPrefixEnums": true,
4 | "withInterfaces": true
5 | }
6 |
--------------------------------------------------------------------------------
/openapitools.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json",
3 | "spaces": 2,
4 | "generator-cli": {
5 | "version": "5.1.0"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | arrowParens: 'always',
3 | bracketSpacing: true,
4 | htmlWhitespaceSensitivity: 'css',
5 | insertPragma: false,
6 | jsxBracketSameLine: false,
7 | jsxSingleQuote: true,
8 | proseWrap: 'always',
9 | quoteProps: 'as-needed',
10 | requirePragma: false,
11 | semi: true,
12 | singleQuote: true,
13 | tabWidth: 4,
14 | trailingComma: 'all',
15 | useTabs: true,
16 | vueIndentScriptAndStyle: false,
17 | printWidth: 120,
18 | };
19 |
--------------------------------------------------------------------------------
/public/favicon/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/android-icon-144x144.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/android-icon-192x192.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/android-icon-36x36.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/android-icon-48x48.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/android-icon-72x72.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/android-icon-96x96.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-114x114.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-120x120.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-144x144.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-152x152.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-180x180.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-57x57.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-60x60.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-72x72.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-76x76.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/apple-icon.png
--------------------------------------------------------------------------------
/public/favicon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
--------------------------------------------------------------------------------
/public/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/public/favicon/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/favicon-96x96.png
--------------------------------------------------------------------------------
/public/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/favicon.ico
--------------------------------------------------------------------------------
/public/favicon/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "App",
3 | "icons": [
4 | {
5 | "src": "\/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": "0.75"
9 | },
10 | {
11 | "src": "\/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": "1.0"
15 | },
16 | {
17 | "src": "\/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": "1.5"
21 | },
22 | {
23 | "src": "\/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": "2.0"
27 | },
28 | {
29 | "src": "\/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": "3.0"
33 | },
34 | {
35 | "src": "\/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": "4.0"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/public/favicon/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/ms-icon-144x144.png
--------------------------------------------------------------------------------
/public/favicon/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/ms-icon-150x150.png
--------------------------------------------------------------------------------
/public/favicon/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/ms-icon-310x310.png
--------------------------------------------------------------------------------
/public/favicon/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/favicon/ms-icon-70x70.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "WildDuck UI",
3 | "short_name": "WildDuck UI",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "theme_color": "#00152a",
7 | "background_color": "#fff",
8 | "description": "Administrative UI for WildDuck IMAP server",
9 | "icons": [
10 | {
11 | "src": "favicon/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "favicon/android-icon-72x72.png",
17 | "sizes": "72x72",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "favicon/android-icon-96x96.png",
22 | "sizes": "96x96",
23 | "type": "image/png"
24 | },
25 | {
26 | "src": "favicon/android-icon-144x144.png",
27 | "sizes": "144x144",
28 | "type": "image/png"
29 | },
30 | {
31 | "src": "favicon/android-icon-152x152.png",
32 | "sizes": "152x152",
33 | "type": "image/png"
34 | },
35 | {
36 | "src": "favicon/android-icon-192x192.png",
37 | "sizes": "192x192",
38 | "type": "image/png",
39 | "purpose": "maskable"
40 | }
41 | ],
42 | "splash_pages": null
43 | }
44 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | position: relative;
3 | margin: 0px;
4 | padding: 0px;
5 | font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
6 | }
7 |
8 | #splash-screen {
9 | background: linear-gradient(to right, #fff, #fff);
10 | position: absolute;
11 | width: 100vw;
12 | height: 100vh;
13 | top: 0px;
14 | left: 0px;
15 | z-index: 9999;
16 | display: flex;
17 | flex-direction: column;
18 | justify-content: center;
19 | align-items: center;
20 | }
21 |
22 | #logo {
23 | width: auto;
24 | height: 250px;
25 | }
26 |
27 | #splash-screen .loading-animation {
28 | color: #bf360c;
29 | font-size: 0.8rem;
30 | font-weight: 400;
31 | line-height: 4rem;
32 | }
33 |
34 | #splash-screen .loading-animation img {
35 | transform: scale(0.6);
36 | }
37 |
--------------------------------------------------------------------------------
/public/svg/loading.svg:
--------------------------------------------------------------------------------
1 |
33 |
--------------------------------------------------------------------------------
/public/svg/wildduck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/public/svg/wildduck.png
--------------------------------------------------------------------------------
/src/assets/icons/DkimIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const DkimIcon: React.FC = () => (
4 |
28 | );
29 |
30 | export default DkimIcon;
31 |
--------------------------------------------------------------------------------
/src/assets/icons/DomainAccessIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const DomainAccessIcon: React.FC = () => (
4 |
14 | );
15 |
16 | export default DomainAccessIcon;
17 |
--------------------------------------------------------------------------------
/src/assets/icons/DomainAliasIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const DomainAliasIcon: React.FC = () => {
4 | return (
5 |
27 | );
28 | };
29 |
30 | export default DomainAliasIcon;
31 |
--------------------------------------------------------------------------------
/src/assets/icons/RecalculateQuotaIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const RecalculateQuotaIcon: React.FC = () => (
4 |
26 | );
27 |
28 | export default RecalculateQuotaIcon;
29 |
--------------------------------------------------------------------------------
/src/assets/icons/WildDuckIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const WildDuckIcon: React.FC = () => {
4 | return (
5 |
6 | );
7 | };
8 |
9 | export default WildDuckIcon;
10 |
--------------------------------------------------------------------------------
/src/assets/icons/wildduck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/314e/wildduck-ui/ca14b2291e64ceab07da2af2e8fd80ce0693821e/src/assets/icons/wildduck.png
--------------------------------------------------------------------------------
/src/client/RequestClient.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | * @description Request client to make api requests
4 | * @exports {Api} api, Client, axiosInstance
5 | */
6 |
7 | import { AxiosRequestConfig } from 'axios';
8 | import AxiosClient, { IApi } from './AxiosClient';
9 | import _ from 'lodash';
10 |
11 | /**
12 | * Class to get axios instance, Client to make api request and generated api's
13 | *
14 | * axiosInstance - instance of axios with interceptor config and base
15 | * Client - instance to make request
16 | * api - generated api
17 | */
18 | class RequestClient extends AxiosClient {
19 | constructor() {
20 | super();
21 | }
22 |
23 | /**
24 | * method to get axios request with configuration
25 | *
26 | * can make request's to api using this method
27 | * @param {AxiosRequestConfig} config - configuration to make api request,
28 | * @example
29 | * url, method, headers
30 | *
31 | * @returns {Promise>} response after making api request with configuration
32 | */
33 | public request = async (config: AxiosRequestConfig) => {
34 | return await this.getAxiosInstance().request(config);
35 | };
36 |
37 | /**
38 | * method to get request method to make api requests
39 | * @returns {request} request method
40 | */
41 | public getClient = () => {
42 | return this.request;
43 | };
44 | }
45 |
46 | /**
47 | * instance of RequestClient
48 | * @type {RequestClient}
49 | */
50 | const requestClient = new RequestClient();
51 |
52 | /**
53 | * reference to request method in RequestClient
54 | *
55 | * make api calls by passing config
56 | * @example
57 | * Client({url: 'example.com', method: 'get'})
58 | * @returns {Promise>} response from requested api
59 | */
60 | const client = requestClient.getClient();
61 |
62 | /**
63 | * instance of Axios
64 | */
65 | const axiosInstance = requestClient.getAxiosInstance();
66 |
67 | /**
68 | * generated open-api
69 | *
70 | * reference to getApi in RequestClient
71 | * contains list of api generated from open-api
72 | * @example
73 | * result = await api.salesMetricsApi.getRevenueForecastApiV1GetRevenueForecastGet(startDate, endDate);
74 | * @exports
75 | */
76 | const api: IApi = new Proxy(({} as unknown) as IApi, {
77 | get: (__, props) => {
78 | return _.get(requestClient.getApi(), props);
79 | },
80 | });
81 |
82 | export { client as Client, axiosInstance, api };
83 | export default api;
84 |
--------------------------------------------------------------------------------
/src/client/wildduck-api/.gitignore:
--------------------------------------------------------------------------------
1 | wwwroot/*.js
2 | node_modules
3 | typings
4 | dist
5 |
--------------------------------------------------------------------------------
/src/client/wildduck-api/.npmignore:
--------------------------------------------------------------------------------
1 | # empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm
--------------------------------------------------------------------------------
/src/client/wildduck-api/.openapi-generator-ignore:
--------------------------------------------------------------------------------
1 | # OpenAPI Generator Ignore
2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator
3 |
4 | # Use this file to prevent files from being overwritten by the generator.
5 | # The patterns follow closely to .gitignore or .dockerignore.
6 |
7 | # As an example, the C# client generator defines ApiClient.cs.
8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9 | #ApiClient.cs
10 |
11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*):
12 | #foo/*/qux
13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14 |
15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16 | #foo/**/qux
17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18 |
19 | # You can also negate patterns with an exclamation (!).
20 | # For example, you can ignore all files in a docs folder with the file extension .md:
21 | #docs/*.md
22 | # Then explicitly reverse the ignore rule for a single file:
23 | #!docs/README.md
24 |
--------------------------------------------------------------------------------
/src/client/wildduck-api/.openapi-generator/FILES:
--------------------------------------------------------------------------------
1 | .gitignore
2 | .npmignore
3 | api.ts
4 | base.ts
5 | common.ts
6 | configuration.ts
7 | git_push.sh
8 | index.ts
9 |
--------------------------------------------------------------------------------
/src/client/wildduck-api/.openapi-generator/VERSION:
--------------------------------------------------------------------------------
1 | 5.1.0
--------------------------------------------------------------------------------
/src/client/wildduck-api/base.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable */
2 | /* eslint-disable */
3 | /**
4 | * WildDuck API
5 | * WildDuck API docs
6 | *
7 | * The version of the OpenAPI document: 1.0.0
8 | *
9 | *
10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
11 | * https://openapi-generator.tech
12 | * Do not edit the class manually.
13 | */
14 |
15 |
16 | import { Configuration } from "./configuration";
17 | // Some imports not used depending on template conditions
18 | // @ts-ignore
19 | import globalAxios, { AxiosPromise, AxiosInstance } from 'axios';
20 |
21 | export const BASE_PATH = "https://api.wildduck.email".replace(/\/+$/, "");
22 |
23 | /**
24 | *
25 | * @export
26 | */
27 | export const COLLECTION_FORMATS = {
28 | csv: ",",
29 | ssv: " ",
30 | tsv: "\t",
31 | pipes: "|",
32 | };
33 |
34 | /**
35 | *
36 | * @export
37 | * @interface RequestArgs
38 | */
39 | export interface RequestArgs {
40 | url: string;
41 | options: any;
42 | }
43 |
44 | /**
45 | *
46 | * @export
47 | * @class BaseAPI
48 | */
49 | export class BaseAPI {
50 | protected configuration: Configuration | undefined;
51 |
52 | constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
53 | if (configuration) {
54 | this.configuration = configuration;
55 | this.basePath = configuration.basePath || this.basePath;
56 | }
57 | }
58 | };
59 |
60 | /**
61 | *
62 | * @export
63 | * @class RequiredError
64 | * @extends {Error}
65 | */
66 | export class RequiredError extends Error {
67 | name: "RequiredError" = "RequiredError";
68 | constructor(public field: string, msg?: string) {
69 | super(msg);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/client/wildduck-api/git_push.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
3 | #
4 | # Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com"
5 |
6 | git_user_id=$1
7 | git_repo_id=$2
8 | release_note=$3
9 | git_host=$4
10 |
11 | if [ "$git_host" = "" ]; then
12 | git_host="github.com"
13 | echo "[INFO] No command line input provided. Set \$git_host to $git_host"
14 | fi
15 |
16 | if [ "$git_user_id" = "" ]; then
17 | git_user_id="GIT_USER_ID"
18 | echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
19 | fi
20 |
21 | if [ "$git_repo_id" = "" ]; then
22 | git_repo_id="GIT_REPO_ID"
23 | echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
24 | fi
25 |
26 | if [ "$release_note" = "" ]; then
27 | release_note="Minor update"
28 | echo "[INFO] No command line input provided. Set \$release_note to $release_note"
29 | fi
30 |
31 | # Initialize the local directory as a Git repository
32 | git init
33 |
34 | # Adds the files in the local repository and stages them for commit.
35 | git add .
36 |
37 | # Commits the tracked changes and prepares them to be pushed to a remote repository.
38 | git commit -m "$release_note"
39 |
40 | # Sets the new remote
41 | git_remote=`git remote`
42 | if [ "$git_remote" = "" ]; then # git remote not defined
43 |
44 | if [ "$GIT_TOKEN" = "" ]; then
45 | echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
46 | git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
47 | else
48 | git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git
49 | fi
50 |
51 | fi
52 |
53 | git pull origin master
54 |
55 | # Pushes (Forces) the changes in the local repository up to the remote repository
56 | echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
57 | git push origin master 2>&1 | grep -v 'To https'
58 |
59 |
--------------------------------------------------------------------------------
/src/client/wildduck-api/index.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable */
2 | /* eslint-disable */
3 | /**
4 | * WildDuck API
5 | * WildDuck API docs
6 | *
7 | * The version of the OpenAPI document: 1.0.0
8 | *
9 | *
10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
11 | * https://openapi-generator.tech
12 | * Do not edit the class manually.
13 | */
14 |
15 |
16 | export * from "./api";
17 | export * from "./configuration";
18 |
19 |
--------------------------------------------------------------------------------
/src/components/AccessToken/AccessToken.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description access token screen
4 | */
5 |
6 | import React from 'react';
7 | import { Input, Form, Button } from 'antd';
8 | import { useActions } from 'kea';
9 |
10 | import Page from '../Page';
11 | import { accessTokenString, apiString } from '../../lib/constants/constant';
12 | import AxiosInterceptor from 'app-ui/lib/axios/AxiosInterceptors';
13 |
14 | import appLogic from 'app-ui/logic/appLogic';
15 |
16 | /**
17 | * access token component
18 | */
19 | const AccessToken: React.FC = () => {
20 | const { setAccessToken } = useActions(appLogic);
21 |
22 | const onFinish = (values: { accessToken: string; api: string }) => {
23 | sessionStorage.setItem(apiString, values.api);
24 | sessionStorage.setItem(accessTokenString, values.accessToken);
25 | setAccessToken(values.accessToken);
26 |
27 | new AxiosInterceptor().inject({
28 | baseURL: values.api,
29 | headers: { 'Content-Type': 'application/json' },
30 | });
31 | };
32 |
33 | return (
34 |
35 |
46 |
47 |
48 |
58 |
59 |
60 |
61 |
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default AccessToken;
71 |
--------------------------------------------------------------------------------
/src/components/AccessToken/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description resolve id screen container
4 | */
5 |
6 | import AccessToken from './AccessToken';
7 |
8 | export default AccessToken;
9 |
--------------------------------------------------------------------------------
/src/components/Address/Address.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Address Component
4 | */
5 |
6 | import React from 'react';
7 | import { useValues } from 'kea';
8 |
9 | import CreateNewAddress from '../CreateNewAddress';
10 | import AddressTable from './AddressTable';
11 | import AddressInformation from './AddressInformation';
12 |
13 | import addressLogic from 'app-ui/logic/addressLogic';
14 |
15 | /**
16 | * Address Component
17 | */
18 | const Address: React.FC = () => {
19 | const { creatNewAddressToggle, addressInformationToggle } = useValues(addressLogic);
20 |
21 | if (creatNewAddressToggle) return ;
22 | else if (addressInformationToggle) return ;
23 | else return ;
24 | };
25 |
26 | export default Address;
27 |
--------------------------------------------------------------------------------
/src/components/Address/AddressInformation.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description AddressInformation Component
4 | */
5 |
6 | import React from 'react';
7 | import { Breadcrumb } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 | import { useParams } from 'react-router-dom';
10 |
11 | import Page from '../Page';
12 | import AddressInformationForm from './AddressInformationForm';
13 |
14 | import useAddressInformation from 'app-ui/hooks/useAddressInformation';
15 |
16 | import addressLogic from 'app-ui/logic/addressLogic';
17 |
18 | /**
19 | * AddressInformation Component
20 | */
21 | const AddressInformation: React.FC = () => {
22 | const { addressId } = useValues(addressLogic);
23 |
24 | const { id }: any = useParams();
25 |
26 | const { data, isLoading, isError } = useAddressInformation(id, addressId);
27 | const { setAddressInformationToggle } = useActions(addressLogic);
28 |
29 | const pageBreadcrumb = (
30 |
31 |
32 | {
34 | event.stopPropagation();
35 | setAddressInformationToggle(false);
36 | }}
37 | >
38 | Address Info
39 |
40 |
41 | Edit Address
42 |
43 | );
44 |
45 | return (
46 |
47 |
48 |
49 | );
50 | };
51 |
52 | export default AddressInformation;
53 |
--------------------------------------------------------------------------------
/src/components/Address/AddressTable.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Table, Tooltip } from 'antd';
3 | import { useActions } from 'kea';
4 | import _ from 'lodash';
5 | import { useParams } from 'react-router-dom';
6 |
7 | import { DiffOutlined } from '@ant-design/icons';
8 | import FloatingButton from '../FloatingButton';
9 | import { getAddressColumns } from './Columns';
10 |
11 | import useAddress from 'app-ui/hooks/useAddress';
12 | import useDeleteAddress from 'app-ui/hooks/useDeleteAddress';
13 |
14 | import addressLogic from 'app-ui/logic/addressLogic';
15 |
16 | const AddressTable: React.FC = () => {
17 | const { setAddressInformationToggle, setCreatNewAddressToggle, setAddressId } = useActions(addressLogic);
18 |
19 | const { id }: any = useParams();
20 |
21 | const { data, isLoading } = useAddress(id);
22 |
23 | const { mutate } = useDeleteAddress();
24 |
25 | const columns = React.useMemo(
26 | () =>
27 | getAddressColumns({
28 | dataSource: data,
29 | edit: (addressId: string) => {
30 | setAddressId(addressId);
31 | setAddressInformationToggle(true);
32 | },
33 | deleteAddress: (addressId: string) => mutate({ userId: id, addressId: addressId }),
34 | }),
35 | [data],
36 | );
37 |
38 | return (
39 | <>
40 | 10 ? null : false}
46 | />
47 |
48 |
49 | {
51 | setCreatNewAddressToggle(true);
52 | }}
53 | />
54 |
55 |
56 | >
57 | );
58 | };
59 |
60 | export default AddressTable;
61 |
--------------------------------------------------------------------------------
/src/components/Address/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Address Component
4 | */
5 |
6 | import Address from './Address';
7 |
8 | export default Address;
9 |
--------------------------------------------------------------------------------
/src/components/App/index.tsx:
--------------------------------------------------------------------------------
1 | import App from './App';
2 |
3 | export default App;
4 |
--------------------------------------------------------------------------------
/src/components/Archive/Archive.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Archive Component
4 | */
5 |
6 | import React from 'react';
7 |
8 | import ArchiveTable from './ArchiveTable';
9 | import RestoreAllMessagesModal from './RestoreAllMessagesModal';
10 |
11 | /**
12 | * Archive Component
13 | */
14 | const Archive: React.FC = () => {
15 | return (
16 | <>
17 |
18 |
19 | >
20 | );
21 | };
22 |
23 | export default Archive;
24 |
--------------------------------------------------------------------------------
/src/components/Archive/RestoreAllMessagesModal.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description RestoreAllMessagesModal Component
4 | */
5 |
6 | import React from 'react';
7 | import { Modal, Typography, DatePicker } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 | import _ from 'lodash';
10 | import moment from 'moment';
11 | import { useParams } from 'react-router-dom';
12 |
13 | import { ExclamationCircleOutlined } from '@ant-design/icons';
14 | import { DATE_TIME_FORMAT } from 'app-ui/utils/constants';
15 | import useRestoreArchiveMessages from 'app-ui/hooks/useRestoreArchiveMessages';
16 |
17 | import archiveLogic from 'app-ui/logic/archiveLogic';
18 |
19 | const { Title } = Typography;
20 |
21 | const { RangePicker } = DatePicker;
22 |
23 | const RestoreAllMessagesModal = () => {
24 | const { setDateData, setIsModalVisible } = useActions(archiveLogic);
25 | const { dateData, isModalVisible } = useValues(archiveLogic);
26 |
27 | const { id }: any = useParams();
28 |
29 | const { mutate } = useRestoreArchiveMessages();
30 |
31 | const handleOk = () => {
32 | mutate({
33 | userId: id,
34 | params: {
35 | start: _.get(dateData, '0', moment('2000-01-01 00:00:00')).format(DATE_TIME_FORMAT),
36 | end: _.get(dateData, '1', moment()).format(DATE_TIME_FORMAT),
37 | },
38 | });
39 | setIsModalVisible(false);
40 | };
41 |
42 | const handleCancel = () => {
43 | setIsModalVisible(false);
44 | setDateData([]);
45 | };
46 |
47 | return (
48 |
49 |
50 |
51 | Are you sure you want to Restore all messages ?
52 |
53 | Select the start and end date (by default it will restores all the mails).
54 | current && current > moment().endOf('day')}
56 | onChange={(value) => setDateData(value)}
57 | showTime
58 | defaultValue={
59 | _.isEmpty(dateData) ? ('' as any) : [moment(_.get(dateData, '0')), moment(_.get(dateData, '1'))]
60 | }
61 | />
62 |
63 | );
64 | };
65 |
66 | export default RestoreAllMessagesModal;
67 |
--------------------------------------------------------------------------------
/src/components/Archive/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Archive Component
4 | */
5 |
6 | import Archive from './Archive';
7 |
8 | export default Archive;
9 |
--------------------------------------------------------------------------------
/src/components/Authentication/Authentication.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Authentication Component
4 | */
5 |
6 | import React from 'react';
7 |
8 | import AuthenticationTable from './AuthenticationTable';
9 |
10 | /**
11 | * Authentication Component
12 | */
13 | const Authentication: React.FC = () => {
14 | return ;
15 | };
16 |
17 | export default Authentication;
18 |
--------------------------------------------------------------------------------
/src/components/Authentication/AuthenticationTable.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description AuthenticationTable Component
4 | */
5 |
6 | import React from 'react';
7 | import { Table } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 | import _ from 'lodash';
10 | import { useParams } from 'react-router-dom';
11 |
12 | import { getAuthenticatonColumns } from './Columns';
13 | import useAuthentication from 'app-ui/hooks/useAuthentication';
14 | import { Pagination } from 'app-ui/utils/Pagination';
15 |
16 | import authenticationLogic from 'app-ui/logic/authenticationLogic';
17 |
18 | const AuthenticationTable: React.FC = () => {
19 | const { page, limit, previous, next } = useValues(authenticationLogic);
20 | const { setLimit, setPage, setNext, setPrevious } = useActions(authenticationLogic);
21 |
22 | const { id }: any = useParams();
23 |
24 | const { data: results, isLoading } = useAuthentication(id, {
25 | page: page,
26 | next: page === 1 ? undefined : next || undefined,
27 | previous: previous || undefined,
28 | limit: limit,
29 | });
30 |
31 | const { data, nextCursor, previousCursor } = _.isUndefined(results)
32 | ? { data: [], nextCursor: undefined, previousCursor: undefined }
33 | : results;
34 | setNext(nextCursor);
35 | setPrevious(previousCursor);
36 |
37 | const columns = React.useMemo(() => getAuthenticatonColumns({ dataSource: data }), [data]);
38 | return (
39 | <>
40 |
50 |
58 | >
59 | );
60 | };
61 |
62 | export default AuthenticationTable;
63 |
--------------------------------------------------------------------------------
/src/components/Authentication/Columns.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description ForwardedAddress Table
4 | */
5 |
6 | import _ from 'lodash';
7 | import moment from 'moment';
8 |
9 | import getColumnsWithFilterAndSort from 'app-ui/utils/getColumnsWithFilterAndSort';
10 | import { DATE_TIME_FORMAT_AP } from 'app-ui/utils/constants';
11 |
12 | export const getAuthenticatonColumns = ({ dataSource }: { dataSource: any }): any => {
13 | const columns = [
14 | {
15 | title: 'Action',
16 | dataIndex: 'action',
17 | key: 'action',
18 | filter: true,
19 | },
20 | {
21 | title: 'Events',
22 | dataIndex: 'events',
23 | key: 'events',
24 | sortable: 'number',
25 | },
26 | {
27 | title: 'Result',
28 | dataIndex: 'result',
29 | key: 'result',
30 | align: 'center',
31 | filter: true,
32 | },
33 | {
34 | title: 'Protocol',
35 | dataIndex: 'protocol',
36 | key: 'protocol',
37 | filter: true,
38 | },
39 | {
40 | title: 'Source',
41 | dataIndex: 'source',
42 | key: 'source',
43 | align: 'center' as const,
44 | },
45 | {
46 | title: 'Required Scope',
47 | dataIndex: 'requiredScope',
48 | key: 'requiredScope',
49 | align: 'center' as const,
50 | filter: true,
51 | },
52 | {
53 | title: 'Session id',
54 | dataIndex: 'sess',
55 | key: 'sess',
56 | },
57 | {
58 | title: 'ip address',
59 | dataIndex: 'ip',
60 | key: 'ip',
61 | align: 'center' as const,
62 | filter: true,
63 | },
64 | {
65 | title: 'Session created',
66 | dataIndex: 'created',
67 | key: 'created',
68 | align: 'center' as const,
69 | sortable: 'date',
70 | render: (date: string) => moment(date).format(DATE_TIME_FORMAT_AP),
71 | },
72 | {
73 | title: 'Session expires',
74 | dataIndex: 'expires',
75 | key: 'expires',
76 | align: 'center' as const,
77 | sortable: 'date',
78 | render: (date: string) => moment(date).format(DATE_TIME_FORMAT_AP),
79 | },
80 | {
81 | title: 'Last activity',
82 | dataIndex: 'last',
83 | key: 'last',
84 | align: 'center' as const,
85 | sortable: 'date',
86 | render: (date: string) => moment(date).format(DATE_TIME_FORMAT_AP),
87 | },
88 | ];
89 |
90 | return getColumnsWithFilterAndSort(columns, dataSource);
91 | };
92 |
--------------------------------------------------------------------------------
/src/components/Authentication/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Authentication Component
4 | */
5 |
6 | import Authentication from './Authentication';
7 |
8 | export default Authentication;
9 |
--------------------------------------------------------------------------------
/src/components/Autoreplies/Autoreplies.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Autoreplies Component
4 | */
5 |
6 | import React from 'react';
7 | import { Tooltip } from 'antd';
8 | import { useParams } from 'react-router-dom';
9 |
10 | import { DeleteOutlined } from '@ant-design/icons';
11 | import showConfirm from 'app-ui/utils/showConfirm';
12 | import FloatingButton from '../FloatingButton';
13 | import Page from '../Page';
14 | import AutorepliesForm from './AutorepliesForm';
15 |
16 | import useDeleteAutoreply from 'app-ui/hooks/useDeleteAutoreply';
17 | import useAutoreplyDetails from 'app-ui/hooks/useAutoreplyDetails';
18 |
19 | /**
20 | * Autoreplies Component
21 | */
22 | const Autoreplies: React.FC = () => {
23 | const { id }: any = useParams();
24 |
25 | const { data, isLoading, isError } = useAutoreplyDetails(id);
26 |
27 | const { mutate: deleteAutoreply } = useDeleteAutoreply();
28 |
29 | return (
30 |
31 |
32 |
33 |
34 |
36 | showConfirm(() => {
37 | deleteAutoreply(id);
38 | }, 'Are you sure you want to delete?')
39 | }
40 | />
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | export default Autoreplies;
48 |
--------------------------------------------------------------------------------
/src/components/Autoreplies/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Autoreplies Component
4 | */
5 |
6 | import Autoreplies from './Autoreplies';
7 |
8 | export default Autoreplies;
9 |
--------------------------------------------------------------------------------
/src/components/ContentArea/index.ts:
--------------------------------------------------------------------------------
1 | import ContentArea from './ContentArea';
2 |
3 | export default ContentArea;
4 |
--------------------------------------------------------------------------------
/src/components/CreateDkim/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description create dkim screen container
4 | */
5 |
6 | import CreateDkim from './CreateDkim';
7 |
8 | export default CreateDkim;
9 |
--------------------------------------------------------------------------------
/src/components/CreateNewAddress/CreateNewAddress.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description CreateNewAddress Component
4 | */
5 |
6 | import React from 'react';
7 | import { Breadcrumb } from 'antd';
8 | import { useActions } from 'kea';
9 |
10 | import Page from '../Page';
11 | import CreateNewAddressForm from './CreateNewAddressForm';
12 |
13 | import addressLogic from 'app-ui/logic/addressLogic';
14 |
15 | /**
16 | * CreateNewAddress Component
17 | */
18 | const CreateNewAddress: React.FC = () => {
19 | const { setCreatNewAddressToggle } = useActions(addressLogic);
20 |
21 | const pageBreadcrumb = (
22 |
23 |
24 | {
26 | event.stopPropagation();
27 | setCreatNewAddressToggle(false);
28 | }}
29 | >
30 | Address Info
31 |
32 |
33 | Create New Address
34 |
35 | );
36 |
37 | return (
38 |
39 |
40 |
41 | );
42 | };
43 |
44 | export default CreateNewAddress;
45 |
--------------------------------------------------------------------------------
/src/components/CreateNewAddress/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for CreateNewAddress Component
4 | */
5 |
6 | import CreateNewAddress from './CreateNewAddress';
7 |
8 | export default CreateNewAddress;
9 |
--------------------------------------------------------------------------------
/src/components/CreateNewDomainAlias/CreateNewDomainAlias.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description CreateNewDomainAlias Component
4 | */
5 |
6 | import React from 'react';
7 | import { Breadcrumb } from 'antd';
8 |
9 | import Link from 'app-ui/components/CustomLink';
10 | import Page from '../Page';
11 | import CreateNewDomainAliasForm from './CreateNewDomainAliasForm';
12 |
13 | /**
14 | * CreateNewDomainAlias Component
15 | */
16 | const CreateNewDomainAlias: React.FC = () => {
17 | const breadcrum = (
18 |
19 |
20 | Domain Aliases
21 |
22 | Create New Address
23 |
24 | );
25 |
26 | return (
27 |
28 |
29 |
30 | );
31 | };
32 |
33 | export default CreateNewDomainAlias;
34 |
--------------------------------------------------------------------------------
/src/components/CreateNewDomainAlias/CreateNewDomainAliasForm.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description CreateNewDomainAliasForm Component
4 | */
5 |
6 | import React from 'react';
7 | import { Form, Input, Button } from 'antd';
8 | import _ from 'lodash';
9 | import { useHistory } from 'react-router-dom';
10 |
11 | import { tailLayout, layout } from '../FormLayout';
12 | import { getBasePath } from '../CustomLink';
13 |
14 | import useCreateDomainAliases from 'app-ui/hooks/useCreateDomainAliases';
15 |
16 | /**
17 | * CreateNewDomainAliasForm Component
18 | */
19 | const CreateNewDomainAliasForm = (): JSX.Element => {
20 | const { mutate, isSuccess, data } = useCreateDomainAliases();
21 |
22 | const history = useHistory();
23 |
24 | if (isSuccess && !_.get(data, 'data.error')) {
25 | history.push(`${getBasePath()}/domain-aliases`);
26 | }
27 |
28 | const [form] = Form.useForm();
29 |
30 | const onFinish = (values: any) => {
31 | mutate(values);
32 | };
33 |
34 | const onReset = () => {
35 | form.resetFields();
36 | };
37 |
38 | return (
39 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
50 |
53 |
54 |
55 | );
56 | };
57 |
58 | export default CreateNewDomainAliasForm;
59 |
--------------------------------------------------------------------------------
/src/components/CreateNewDomainAlias/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description CreateNewDomainAlias Component Container
4 | */
5 |
6 | import CreateNewDomainAlias from './CreateNewDomainAlias';
7 |
8 | export default CreateNewDomainAlias;
9 |
--------------------------------------------------------------------------------
/src/components/CreateNewForwardedAddress/CreateNewForwardedAddress.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description CreateNewForwardedAddress Component
4 | */
5 |
6 | import React from 'react';
7 | import { Breadcrumb } from 'antd';
8 |
9 | import Link from 'app-ui/components/CustomLink';
10 | import Page from '../Page';
11 | import CreateNewForwardedAddressForm from './CreateNewForwardedAddressForm';
12 |
13 | /**
14 | * CreateNewForwardedAddress Component
15 | */
16 | const CreateNewForwardedAddress: React.FC = () => {
17 | const breadcrum = (
18 |
19 |
20 | Forwarded Addresses
21 |
22 | Create new Forwarded Address
23 |
24 | );
25 |
26 | return (
27 |
28 |
29 |
30 | );
31 | };
32 |
33 | export default CreateNewForwardedAddress;
34 |
--------------------------------------------------------------------------------
/src/components/CreateNewForwardedAddress/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for CreateNewForwardedAddress Component
4 | */
5 |
6 | import CreateNewForwardedAddress from './CreateNewForwardedAddress';
7 |
8 | export default CreateNewForwardedAddress;
9 |
--------------------------------------------------------------------------------
/src/components/CreateNewUser/CreateNewUser.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Add Users screen
4 | */
5 |
6 | import React from 'react';
7 | import { Breadcrumb } from 'antd';
8 |
9 | import Page from 'components/Page';
10 | import Link from 'app-ui/components/CustomLink';
11 | import CreateNewUserForm from './CreateNewUserForm';
12 |
13 | const CreateNewUser: React.FC = () => {
14 | const pageBreadcrumb = (
15 |
16 |
17 | Users
18 |
19 | Add User
20 |
21 | );
22 |
23 | return (
24 |
25 |
26 |
27 | );
28 | };
29 |
30 | export default CreateNewUser;
31 |
--------------------------------------------------------------------------------
/src/components/CreateNewUser/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description CreateNewUser Component Container
4 | */
5 |
6 | import CreateNewUser from './CreateNewUser';
7 |
8 | export default CreateNewUser;
9 |
--------------------------------------------------------------------------------
/src/components/CustomLink/index.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | * @description Custom Link component to prefix basepath for to
4 | */
5 |
6 | import React from 'react';
7 | import { Link, LinkProps } from 'react-router-dom';
8 | import _ from 'lodash';
9 |
10 | export const getBasePath = (): string => {
11 | return _.get(window, 'basePath', '').slice(0, -1);
12 | };
13 |
14 | /**
15 | * CustomLink to prefix basepath for to
16 | * @param props
17 | */
18 | function CustomLink (props: LinkProps & React.RefAttributes ): ReturnType> {
19 | const {to, children, ...restProps} = props;
20 | return (
21 | {children}
22 | );
23 | }
24 |
25 | export default CustomLink;
26 |
--------------------------------------------------------------------------------
/src/components/Dkim/Dkim.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Dkim screen
4 | */
5 |
6 | import React from 'react';
7 | import { useActions } from 'kea';
8 | import { Button, Input, Row, Col } from 'antd';
9 |
10 | import Page from 'components/Page';
11 | import Link from 'app-ui/components/CustomLink';
12 | import DkimTable from './DkimTable';
13 |
14 | import dkimLogic from 'app-ui/logic/dkimLogic';
15 |
16 | /**
17 | * Dkim component
18 | */
19 | const Dkim: React.FC = () => {
20 | const { setQuery } = useActions(dkimLogic);
21 |
22 | const { Search } = Input;
23 |
24 | const FilterSearch = () => {
25 | const onFinish = (values: any) => {
26 | setQuery(values);
27 | };
28 |
29 | return ;
30 | };
31 |
32 | return (
33 |
37 | Create DKIM key for Domain
38 | ,
39 | ]}
40 | >
41 |
42 | {}
43 |
44 |
45 |
46 |
47 |
48 | );
49 | };
50 |
51 | export default Dkim;
52 |
--------------------------------------------------------------------------------
/src/components/Dkim/DkimColumns.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Dkim Table Columns
4 | */
5 |
6 | import React from 'react';
7 | import moment from 'moment';
8 | import { Space, Button, Tooltip } from 'antd';
9 |
10 | import { EditFilled, DeleteFilled } from '@ant-design/icons';
11 | import { DATE_TIME_FORMAT_AP } from 'app-ui/utils/constants';
12 | import showConfirm from 'app-ui/utils/showConfirm';
13 | import getColumnsWithFilterAndSort from 'app-ui/utils/getColumnsWithFilterAndSort';
14 | import { GetDkimKeysResult } from 'client/wildduck-api';
15 | import { DkimDetailsLink } from '../Widgets/Link';
16 |
17 | export const getDkimColumns: any = ({ dataSource, deleteDkim }: { dataSource: any; deleteDkim(id: string): void }) => {
18 | const columnsDkim = [
19 | {
20 | title: 'Domain',
21 | dataIndex: 'domain',
22 | filter: true,
23 | render: (text: string, record: GetDkimKeysResult) => ,
24 | },
25 | {
26 | title: 'Selector',
27 | filter: true,
28 | dataIndex: 'selector',
29 | },
30 | {
31 | title: 'Description',
32 | dataIndex: 'description',
33 | },
34 | {
35 | title: 'Created',
36 | dataIndex: 'created',
37 | sortable: 'date',
38 | align: 'center' as const,
39 | render: (date: string) => moment(date).format(DATE_TIME_FORMAT_AP),
40 | },
41 | {
42 | title: 'Actions',
43 | dataIndex: 'Action',
44 | align: 'center' as const,
45 | render: (text: string, record: GetDkimKeysResult) => (
46 |
47 |
48 |
52 |
53 |
54 | }
55 | />
56 |
57 |
58 |
67 |
68 |
69 | ),
70 | },
71 | ];
72 |
73 | return getColumnsWithFilterAndSort(columnsDkim, dataSource);
74 | };
75 |
--------------------------------------------------------------------------------
/src/components/Dkim/DkimTable.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Dkim Table
4 | */
5 |
6 | import React from 'react';
7 | import { Table } from 'antd';
8 | import { useValues, useActions } from 'kea';
9 | import _ from 'lodash';
10 |
11 | import { getDkimColumns } from './DkimColumns';
12 | import { Pagination } from 'app-ui/utils/Pagination';
13 |
14 | import useDeleteDkim from 'app-ui/hooks/useDeleteDkim';
15 | import useDkim from 'app-ui/hooks/useDkim';
16 |
17 | import dkimLogic from 'app-ui/logic/dkimLogic';
18 |
19 | const DkimTable: React.FC = () => {
20 | const { query, page, limit, next, previous } = useValues(dkimLogic);
21 | const { setPrevious, setLimit, setNext, setPage } = useActions(dkimLogic);
22 | const { data: results, isLoading } = useDkim({
23 | query: query,
24 | page: page,
25 | next: page === 1 ? undefined : next || undefined,
26 | previous: previous || undefined,
27 | limit: limit,
28 | });
29 | const { data, previousCursor, nextCursor } = _.isUndefined(results)
30 | ? { data: [], nextCursor: undefined, previousCursor: undefined }
31 | : results;
32 |
33 | const { mutate } = useDeleteDkim();
34 |
35 | const columns = React.useMemo(
36 | () =>
37 | getDkimColumns({
38 | dataSource: data,
39 | deleteDkim: (id: string) => mutate(id),
40 | }),
41 | [data],
42 | );
43 |
44 | return (
45 | <>
46 |
56 |
65 | >
66 | );
67 | };
68 |
69 | export default DkimTable;
70 |
--------------------------------------------------------------------------------
/src/components/Dkim/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Dkim screen container
4 | */
5 |
6 | import Dkim from './Dkim';
7 |
8 | export default Dkim;
9 |
--------------------------------------------------------------------------------
/src/components/DkimDetails/DkimDetails.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Dkim Details screen
4 | */
5 |
6 | import React from 'react';
7 | import { Tabs, Descriptions, Breadcrumb } from 'antd';
8 | import { useParams, Link } from 'react-router-dom';
9 |
10 | import Page from 'components/Page';
11 |
12 | import useDkimDetails from 'app-ui/hooks/useDkimDetails';
13 |
14 | const DkimDetails: React.SFC = () => {
15 | const { TabPane } = Tabs;
16 | const params: { id: string } = useParams();
17 | const { data, isLoading } = useDkimDetails(params.id);
18 |
19 | const DescriptionBox = () => {
20 | return (
21 | !isLoading && (
22 |
23 | {data.id}
24 | {data.domain}
25 | {data.selector}
26 | {data.description}
27 | {data.fingerprint}
28 | {data.dnsTxt.name}
29 | {data.dnsTxt.value}
30 | {data.created}
31 |
32 | )
33 | );
34 | };
35 |
36 | const pageBreadcrumb = (
37 |
38 |
39 | DKIM
40 |
41 |
42 | {!isLoading && data.domain}
43 |
44 | );
45 | return (
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | );
54 | };
55 |
56 | export default DkimDetails;
57 |
--------------------------------------------------------------------------------
/src/components/DkimDetails/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description DkimDetails screen container
4 | */
5 |
6 | import DkimDetails from './DkimDetails';
7 |
8 | export default DkimDetails;
9 |
--------------------------------------------------------------------------------
/src/components/DomainAccess/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description DomainAccess Component Container
4 | */
5 |
6 | import DomainAccess from './DomainAccess';
7 |
8 | export default DomainAccess;
9 |
--------------------------------------------------------------------------------
/src/components/DomainAliases/Columns.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description DomainAliases Table Columns
4 | */
5 |
6 | import React from 'react';
7 | import { Space, Button, Tooltip } from 'antd';
8 |
9 | import { DeleteFilled } from '@ant-design/icons';
10 | import getColumnsWithFilterAndSort from 'app-ui/utils/getColumnsWithFilterAndSort';
11 | import showConfirm from 'app-ui/utils/showConfirm';
12 |
13 | export const getDomainAliasesColumns = ({
14 | dataSource,
15 | deleteDomainAliases,
16 | }: {
17 | dataSource: any;
18 | deleteDomainAliases(value: string): void;
19 | }): any => {
20 | const columnDomainAliases = [
21 | {
22 | title: 'Alias',
23 | dataIndex: 'alias',
24 | sortable: 'string',
25 | filter: true,
26 | },
27 | {
28 | title: 'Domain',
29 | dataIndex: 'domain',
30 | sortable: 'string',
31 | filter: true,
32 | },
33 | {
34 | title: 'Action',
35 | key: 'action',
36 | width: 100,
37 | align: 'center' as const,
38 | render: (text: string, record: any) => (
39 |
40 |
41 |
50 |
51 |
52 | ),
53 | },
54 | ];
55 |
56 | return getColumnsWithFilterAndSort(columnDomainAliases, dataSource);
57 | };
58 |
--------------------------------------------------------------------------------
/src/components/DomainAliases/DomainAliases.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description DomainAliases Component
4 | */
5 |
6 | import React from 'react';
7 | import { Button, Col, Row } from 'antd';
8 |
9 | import Link from 'app-ui/components/CustomLink';
10 | import Page from '../Page';
11 | import DomainAliasesTable from './DomainAliasesTable';
12 | import SearchAlias from './SearchAlias';
13 |
14 | /**
15 | * DomainAliases Component
16 | */
17 | const DomainAliases: React.FC = () => {
18 | return (
19 |
23 | Create new Domain Alias
24 | ,
25 | ]}
26 | >
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | );
37 | };
38 |
39 | export default DomainAliases;
40 |
--------------------------------------------------------------------------------
/src/components/DomainAliases/DomainAliasesTable.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description DomainAliasesTable Component
4 | */
5 |
6 | import React from 'react';
7 | import { Table } from 'antd';
8 | import { useValues, useActions } from 'kea';
9 | import _ from 'lodash';
10 |
11 | import { getDomainAliasesColumns } from './Columns';
12 | import { Pagination } from 'app-ui/utils/Pagination';
13 |
14 | import domainAliasesLogic from 'app-ui/logic/domainAliasesLogic';
15 |
16 | import useDomainAliases from 'app-ui/hooks/useDomainAliases';
17 | import useDeleteDomainAliases from 'app-ui/hooks/useDeleteDomainAliases';
18 |
19 | /**
20 | * DomainAliasesTable Component
21 | */
22 | const DomainAliasesTable: React.FC = () => {
23 | const { setPage, setLimit, setNext, setPrevious } = useActions(domainAliasesLogic);
24 |
25 | const { query, limit, page, next, previous } = useValues(domainAliasesLogic);
26 |
27 | const { mutate } = useDeleteDomainAliases();
28 |
29 | const { data: results, isLoading } = useDomainAliases({
30 | query: _.isEmpty(query) ? undefined : query,
31 | page: page,
32 | next: page === 1 ? undefined : next || undefined,
33 | previous: previous || undefined,
34 | limit: limit,
35 | });
36 |
37 | const { data, nextCursor, previousCursor } = _.isUndefined(results)
38 | ? { data: [], nextCursor: undefined, previousCursor: undefined }
39 | : results;
40 | setNext(nextCursor);
41 | setPrevious(previousCursor);
42 |
43 | const columns = React.useMemo(
44 | () =>
45 | getDomainAliasesColumns({
46 | dataSource: data,
47 | deleteDomainAliases: (aliasId: string) => mutate(aliasId),
48 | }),
49 | [data],
50 | );
51 |
52 | return _.isUndefined(data) ? null : (
53 | <>
54 |
64 |
74 | >
75 | );
76 | };
77 |
78 | export default DomainAliasesTable;
79 |
--------------------------------------------------------------------------------
/src/components/DomainAliases/SearchAlias.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description SearchAlias Component
4 | */
5 |
6 | import React from 'react';
7 | import { useActions, useValues } from 'kea';
8 |
9 | import Search from 'antd/lib/input/Search';
10 |
11 | import domainAliasesLogic from 'app-ui/logic/domainAliasesLogic';
12 |
13 | /**
14 | * SearchAlias Component
15 | */
16 | const SearchAlias: React.FC = () => {
17 | const { setQuery } = useActions(domainAliasesLogic);
18 | const { query } = useValues(domainAliasesLogic);
19 |
20 | const onSearch = (value: string) => {
21 | setQuery(value);
22 | };
23 |
24 | return (
25 |
33 | );
34 | };
35 |
36 | export default SearchAlias;
37 |
--------------------------------------------------------------------------------
/src/components/DomainAliases/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for DomainAliases Component
4 | */
5 |
6 | import DomainAliases from './DomainAliases';
7 |
8 | export default DomainAliases;
9 |
--------------------------------------------------------------------------------
/src/components/ErrorBoundary/ErrorBoundary.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import _ from 'lodash';
3 | import log from 'loglevel';
4 |
5 | import ErrorPage from './ErrorPage';
6 |
7 | /**
8 | * class component to handle erros
9 | * @class ErrorBoundary
10 | * @extends Component
11 | */
12 | class ErrorBoundary extends Component {
13 | /**
14 | * lifecycle to catch DOM errors
15 | *
16 | * @param {object|string} error error message
17 | * @param info {object|string} info stack information of error
18 | */
19 | componentDidCatch(error: Error, info: React.ErrorInfo): void {
20 | const { setError } = this.props.actions;
21 | if (error && _.isFunction(setError)) {
22 | setError({ error, info });
23 | } else {
24 | log.error(error, info);
25 | }
26 | }
27 |
28 | /**
29 | * ErrorBoundary Renderer
30 | */
31 | render(): JSX.Element | React.ReactNode {
32 | const { error, children } = this.props;
33 | if (error) {
34 | return ;
35 | }
36 | return children;
37 | }
38 | }
39 |
40 | export default ErrorBoundary;
41 |
--------------------------------------------------------------------------------
/src/components/ErrorBoundary/ErrorPage.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import _ from 'lodash';
3 | import { Result } from 'antd';
4 | import { WarningFilled } from '@ant-design/icons';
5 | import { ResultProps } from 'antd/lib/result';
6 |
7 | /**
8 | * interface for Error
9 | * @interface IError
10 | */
11 | interface IError {
12 | [key: string]: {
13 | /**
14 | * title
15 | * @type {ResultProps['status']}
16 | */
17 | title: ResultProps['status'];
18 | /**
19 | * description
20 | * @type {string}
21 | */
22 | description: string;
23 | };
24 | }
25 |
26 | /**
27 | * data for common errors
28 | */
29 | const commonErrors: IError = {
30 | error403: {
31 | title: 403,
32 | description: 'Unauthorized Access',
33 | },
34 | error404: {
35 | title: 404,
36 | description: 'Page Not Found',
37 | },
38 | error500: {
39 | title: 500,
40 | description: 'Server Error',
41 | },
42 | };
43 |
44 | /**
45 | * functional component to render error
46 | * @param {any} props
47 | */
48 | const ErrorPage = (props: any) => {
49 | let error = commonErrors.error404;
50 |
51 | if (_.has(props, 'error') && _.has(commonErrors, `error${_.get(props, 'error')}`)) {
52 | error = _.get(commonErrors, `error${_.get(props, 'error')}`);
53 | } else {
54 | error = props;
55 | }
56 |
57 | return } />;
58 | };
59 |
60 | export default ErrorPage;
61 |
--------------------------------------------------------------------------------
/src/components/ErrorBoundary/index.ts:
--------------------------------------------------------------------------------
1 | import { connect } from 'kea';
2 | import ErrorBoundary from './ErrorBoundary';
3 | import appLogic from 'app-ui/logic/appLogic';
4 |
5 | const logic = connect({
6 | values: [appLogic, ['error']],
7 | actions: [appLogic, ['setError']],
8 | });
9 |
10 | export default logic(ErrorBoundary) as any;
11 |
--------------------------------------------------------------------------------
/src/components/Filters/Filters.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Filters Component
4 | */
5 |
6 | import React from 'react';
7 | import _ from 'lodash';
8 | import { useValues } from 'kea';
9 |
10 | import AddFiltersForm from './AddFiltersForm';
11 | import FiltersTable from './FiltersTable';
12 |
13 | import filtersLogic from 'app-ui/logic/filtersLogic';
14 |
15 | const Filters: React.FC = () => {
16 | const { showAddFilterForm, filterId } = useValues(filtersLogic);
17 |
18 | return (
19 | <>
20 | {showAddFilterForm ? : null}
21 | {!_.isEmpty(filterId) ? : null}
22 | {_.isEmpty(filterId) && !showAddFilterForm && }
23 | >
24 | );
25 | };
26 |
27 | export default Filters;
28 |
--------------------------------------------------------------------------------
/src/components/Filters/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Container for Storage Component
4 | */
5 | import Filters from './Filters';
6 |
7 | export default Filters;
8 |
--------------------------------------------------------------------------------
/src/components/FloatingButton.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Floating Button
4 | */
5 |
6 | import React from 'react';
7 |
8 | export interface FloatingButtonProps {
9 | children?: React.ReactNode;
10 | }
11 |
12 | const FloatingButton: React.SFC = (props: FloatingButtonProps) => {
13 | return (
14 |
15 |
16 |
{props.children}
17 |
18 |
25 |
26 | );
27 | };
28 |
29 | export default FloatingButton;
30 |
--------------------------------------------------------------------------------
/src/components/FormLayout.ts:
--------------------------------------------------------------------------------
1 | const layout = {
2 | labelCol: {
3 | span: 4,
4 | },
5 | wrapperCol: {
6 | span: 6,
7 | },
8 | };
9 | const tailLayout = {
10 | wrapperCol: {
11 | offset: 4,
12 | span: 8,
13 | },
14 | };
15 | export { layout, tailLayout };
16 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddress/Columns.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description ForwardedAddress Table Columns
4 | */
5 |
6 | import React from 'react';
7 | import _ from 'lodash';
8 | import { Space, Button, Tag, Tooltip } from 'antd';
9 |
10 | import { DeleteFilled, EditFilled } from '@ant-design/icons';
11 | import getColumnsWithFilterAndSort from 'app-ui/utils/getColumnsWithFilterAndSort';
12 | import showConfirm from 'app-ui/utils/showConfirm';
13 | import { ForwardedAddressLink } from '../Widgets/Link';
14 |
15 | export const getForwardedAddressColumns = ({
16 | dataSource,
17 | deleteAddress,
18 | }: {
19 | dataSource: any;
20 | deleteAddress(value: string): void;
21 | }): any => {
22 | const columnsForwarded = [
23 | {
24 | title: 'Forwarded address',
25 | dataIndex: 'address',
26 | key: 'address',
27 | filter: true,
28 | render: (text: string, record: Address.IForwardedAddress) => (
29 |
30 |
31 |
32 | ),
33 | },
34 | {
35 | title: 'Name',
36 | dataIndex: 'name',
37 | key: 'name',
38 | filter: true,
39 | },
40 | {
41 | title: 'Tags',
42 | key: 'tags',
43 | dataIndex: 'tags',
44 | filter: true,
45 | align: 'center' as const,
46 | render: (tags: string[]) => (
47 | <>
48 | {_.map(tags, (tag) => {
49 | return {tag};
50 | })}
51 | >
52 | ),
53 | },
54 | {
55 | title: 'Action',
56 | key: 'action',
57 | align: 'center' as const,
58 | width: 100,
59 | render: (text: string, record: Address.IForwardedAddress) => (
60 |
61 |
62 |
66 |
67 |
68 | }
69 | />
70 |
71 |
72 |
81 |
82 |
83 | ),
84 | },
85 | ];
86 |
87 | return getColumnsWithFilterAndSort(columnsForwarded, dataSource);
88 | };
89 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddress/ForwardedAddress.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description ForwardedAddress Component
4 | */
5 |
6 | import React from 'react';
7 | import { Button, Breadcrumb, Row, Col } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 |
10 | import Link from 'app-ui/components/CustomLink';
11 | import Page from '../Page';
12 | import Search from 'antd/lib/input/Search';
13 | import RenameDomain from './RenameDomain';
14 | import ForwardedAddressTable from './ForwardedAddressTable';
15 |
16 | import addressLogic from 'app-ui/logic/addressLogic';
17 |
18 | /**
19 | * ForwardedAddress Component
20 | */
21 | const ForwardedAddress: React.FC = () => {
22 | const { error, renameDomainToggle, query } = useValues(addressLogic);
23 | const { setQuery, setRenameDomainToggle } = useActions(addressLogic);
24 |
25 | const onSearch = (value: string) => {
26 | setQuery(value);
27 | };
28 |
29 | return !renameDomainToggle ? (
30 |
31 | ) : (
32 | setRenameDomainToggle(false)}
41 | >
42 | Rename Domain
43 | ,
44 | ,
47 | ]}
48 | >
49 |
50 |
51 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | );
65 | };
66 |
67 | export default ForwardedAddress;
68 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddress/ForwardedAddressTable.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description ForwardedAddress Table
4 | */
5 |
6 | import React from 'react';
7 | import _ from 'lodash';
8 | import { Table } from 'antd';
9 | import { useValues } from 'kea';
10 |
11 | import { getForwardedAddressColumns } from './Columns';
12 |
13 | import useDeleteForwadedAddress from 'app-ui/hooks/useDeleteForwardedAddress';
14 | import useForwadedAddress from 'app-ui/hooks/useForwardedAddress';
15 |
16 | import addressLogic from 'app-ui/logic/addressLogic';
17 |
18 | /**
19 | * ForwardedAddressTable Component
20 | */
21 |
22 | const ForwardedAddressTable = (): JSX.Element => {
23 | const { query } = useValues(addressLogic);
24 |
25 | const { data, isLoading } = useForwadedAddress({ query: query });
26 |
27 | const { mutate } = useDeleteForwadedAddress();
28 |
29 | const forwardedAddressData = _.filter(data, (address) => _.get(address, 'forwarded'));
30 |
31 | const columns = React.useMemo(
32 | () =>
33 | getForwardedAddressColumns({
34 | dataSource: forwardedAddressData,
35 | deleteAddress: (addressId: string) => mutate(addressId),
36 | }),
37 | [forwardedAddressData],
38 | );
39 |
40 | return (
41 |
49 | );
50 | };
51 |
52 | export default ForwardedAddressTable;
53 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddress/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for ForwardedAddress Component
4 | */
5 |
6 | import ForwardedAddress from './ForwardedAddress';
7 |
8 | export default ForwardedAddress;
9 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddressInformation/ForwardedAddressInformation.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description ForwardedAddressInformation Component
4 | */
5 |
6 | import React from 'react';
7 | import { Tabs, Breadcrumb } from 'antd';
8 | import _ from 'lodash';
9 | import { useParams } from 'react-router-dom';
10 |
11 | import Link from 'app-ui/components/CustomLink';
12 | import Page from '../Page';
13 | import ForwardedAddressInformationForm from './ForwardedAddressInformationForm';
14 | import ListTarget from './ListTarget';
15 | import { ForwardedAddressInfoFomatter } from 'app-ui/lib/constants/Formatter';
16 |
17 | import useForwardedAddressInformation from 'app-ui/hooks/useForwardedAddressInformation';
18 |
19 | import 'styles/style.css';
20 |
21 | const { TabPane } = Tabs;
22 |
23 | /**
24 | * ForwardedAddressInformation Component
25 | */
26 | const ForwardedAddressInformation: React.FC = () => {
27 | const { id }: any = useParams();
28 |
29 | const { data, isLoading, isError } = useForwardedAddressInformation(id);
30 |
31 | const formattedData = ForwardedAddressInfoFomatter(data);
32 |
33 | const breadcrum = (
34 |
35 |
36 | Forwarded Addresses
37 |
38 | {_.get(data, 'address')}
39 |
40 | );
41 |
42 | return (
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | );
54 | };
55 |
56 | export default ForwardedAddressInformation;
57 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddressInformation/ListTarget.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description ListTargets Component
4 | */
5 |
6 | import React from 'react';
7 | import { List } from 'antd';
8 | import _ from 'lodash';
9 |
10 | const ListTarget: React.FC<{ data: any }> = ({ data }: any) => {
11 | return _.isUndefined(_.get(data, 'address')) ? null : (
12 | {item}}
17 | />
18 | );
19 | };
20 |
21 | export default ListTarget;
22 |
--------------------------------------------------------------------------------
/src/components/ForwardedAddressInformation/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for ForwardedAddressInformation Component
4 | */
5 |
6 | import ForwardedAddressInformation from './ForwardedAddressInformation';
7 |
8 | export default ForwardedAddressInformation;
9 |
--------------------------------------------------------------------------------
/src/components/Header/Header.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Harish.R
3 | * @description Header component
4 | */
5 |
6 | import React from 'react';
7 | import { Button, Layout, Tooltip } from 'antd';
8 | import { useActions } from 'kea';
9 | import { LogoutOutlined } from '@ant-design/icons';
10 | import WildDuckIcon from '../../assets/icons/WildDuckIcon';
11 | import { accessTokenString, apiString } from 'app-ui/lib/constants/constant';
12 | import appLogic from 'app-ui/logic/appLogic';
13 |
14 | /**
15 | * class component for Header
16 | * @class Header
17 | * @extends PureComponent
18 | */
19 | const Header = () => {
20 | const { setAccessToken } = useActions(appLogic);
21 | const logout = () => {
22 | sessionStorage.removeItem(accessTokenString);
23 | sessionStorage.removeItem(apiString);
24 | setAccessToken('');
25 | };
26 |
27 | /** Header Renderer */
28 | return (
29 |
30 |
31 |
32 | }>
33 |
34 |
35 | );
36 | };
37 |
38 | export default Header;
39 |
--------------------------------------------------------------------------------
/src/components/Header/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Harish.R
3 | * @description container for Header component
4 | */
5 |
6 | import Header from './Header';
7 |
8 | export default Header;
9 |
--------------------------------------------------------------------------------
/src/components/HtmlRenderer/HtmlRenderer.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | * @description Html render component
4 | */
5 |
6 | import React, { ReactElement } from 'react';
7 |
8 | /**
9 | * IProps
10 | */
11 | interface IProps {
12 | /**
13 | * stringifiedHtml
14 | * string to render as html
15 | * @type {string}
16 | */
17 | stringifiedHtml: string;
18 | /**
19 | * pointerEvents
20 | * @type {string}
21 | */
22 | disablePointerEvents?: boolean;
23 | /**
24 | * className
25 | * @type {string}
26 | */
27 | className?: string;
28 |
29 | /**
30 | * className
31 | * @type {React.CSSProperties}
32 | */
33 | style: React.CSSProperties;
34 | }
35 |
36 | /**
37 | * functional component to render string as HTML
38 | * @param param0
39 | */
40 | const HtmlRenderer = ({ stringifiedHtml, disablePointerEvents, style, ...restProps }: IProps): ReactElement => {
41 | return (
42 |
47 | );
48 | };
49 |
50 | HtmlRenderer.defaultProps = {
51 | style: {},
52 | disablePointerEvents: true,
53 | };
54 |
55 | export default HtmlRenderer;
56 |
--------------------------------------------------------------------------------
/src/components/HtmlRenderer/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | * @description HTML renderer
4 | */
5 |
6 | import HtmlRenderer from './HtmlRenderer';
7 | export default HtmlRenderer;
8 |
--------------------------------------------------------------------------------
/src/components/LoaderBoundary/LoaderBoundary.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Harish.R
3 | * @description LoaderBoundary component
4 | */
5 |
6 | import React from 'react';
7 | import { Spin } from 'antd';
8 |
9 | /**
10 | * props for LoaderBoundary
11 | * @interface IProps
12 | */
13 | interface IProps {
14 | /**
15 | *
16 | * loading
17 | * @type {boolean}
18 | * @memberof IProps
19 | */
20 | loading?: boolean;
21 | /**
22 | *
23 | * children
24 | * @type {React.ReactNode}
25 | * optional
26 | */
27 | children?: React.ReactNode;
28 | }
29 |
30 | /**
31 | * functional component to loaderBoundary
32 | * @param {IProps} props
33 | */
34 | const loaderBoundary = (props: IProps) => (
35 |
36 | {props.loading ? (
37 |
38 |
39 |
40 | ) : (
41 | props.children
42 | )}
43 |
44 | );
45 |
46 | export default loaderBoundary;
47 |
--------------------------------------------------------------------------------
/src/components/LoaderBoundary/index.ts:
--------------------------------------------------------------------------------
1 | import LoaderBoundary from './LoaderBoundary';
2 |
3 | export default LoaderBoundary;
4 |
--------------------------------------------------------------------------------
/src/components/LoadingPage/LoadingPage.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Harish.R
3 | * @description LoadingPage component
4 | */
5 |
6 | import React from 'react';
7 | import { LoadingComponentProps } from 'react-loadable';
8 |
9 | import ErrorPage from 'app-ui/components/ErrorBoundary/ErrorPage';
10 | import LoaderBoundary from '../LoaderBoundary';
11 |
12 | /**
13 | * functional component for loadingPage
14 | * @param {LoadingComponentProps} props
15 | */
16 | const loadingPage = (props: LoadingComponentProps): JSX.Element => {
17 | if (props.error || props.timedOut) {
18 | return ;
19 | } else {
20 | return ;
21 | }
22 | };
23 |
24 | export default loadingPage;
25 |
--------------------------------------------------------------------------------
/src/components/LoadingPage/index.ts:
--------------------------------------------------------------------------------
1 | import LoadingPage from './LoadingPage';
2 |
3 | export default LoadingPage;
4 |
--------------------------------------------------------------------------------
/src/components/Mailboxes/MailboxSearch.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description MailboxSearch Component
4 | */
5 |
6 | import React from 'react';
7 |
8 | import { Button, Form, Switch } from 'antd';
9 | import { useActions } from 'kea';
10 |
11 | import mailboxesLogic from 'app-ui/logic/mailboxesLogic';
12 |
13 | /**
14 | * MailboxSearch Component
15 | */
16 | const MailboxSearch = () => {
17 | const { setSpecialUse } = useActions(mailboxesLogic);
18 |
19 | const [form] = Form.useForm();
20 |
21 | const onFinish = ({ specialUse }: any) => {
22 | setSpecialUse(specialUse);
23 | };
24 |
25 | return (
26 |
40 |
41 |
42 |
43 |
46 |
47 |
48 | );
49 | };
50 |
51 | export default MailboxSearch;
52 |
--------------------------------------------------------------------------------
/src/components/Mailboxes/Mailboxes.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Mailboxes Component
4 | */
5 |
6 | import React from 'react';
7 | import { useValues } from 'kea';
8 |
9 | import Messages from '../Messages';
10 | import MailboxEditForm from './MailboxEditForm';
11 | import MailboxesTable from './MailboxesTable';
12 | import MailboxSearch from './MailboxSearch';
13 |
14 | import mailboxesLogic from 'app-ui/logic/mailboxesLogic';
15 |
16 | /**
17 | * Mailboxes Component
18 | */
19 | const Mailboxes: React.FC = () => {
20 | const { updateMailboxToggle, showMailboxMessagesTable } = useValues(mailboxesLogic);
21 |
22 | return updateMailboxToggle ? (
23 |
24 | ) : showMailboxMessagesTable ? (
25 |
26 | ) : (
27 | <>
28 |
29 |
30 | >
31 | );
32 | };
33 |
34 | export default Mailboxes;
35 |
--------------------------------------------------------------------------------
/src/components/Mailboxes/MailboxesTable.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description MailboxesTable Component
4 | */
5 |
6 | import React from 'react';
7 | import _ from 'lodash';
8 | import { Table } from 'antd';
9 | import { useActions, useValues } from 'kea';
10 | import { useParams } from 'react-router-dom';
11 |
12 | import { getMailboxesColumns } from './Columns';
13 | import useDeleteMessagesInMailbox from 'app-ui/hooks/useDeleteMessagesInMailbox';
14 |
15 | import useMailboxes from 'app-ui/hooks/useMailboxes';
16 |
17 | import messagesLogic from 'app-ui/logic/messagesLogic';
18 | import mailboxesLogic from 'app-ui/logic/mailboxesLogic';
19 |
20 | /**
21 | * MailboxesTable Component
22 | */
23 | const MailboxesTable: React.FC = () => {
24 | const { id }: any = useParams();
25 |
26 | const { specialUse } = useValues(mailboxesLogic);
27 |
28 | const { data, isLoading } = useMailboxes({ userId: id, params: { specialUse: specialUse } });
29 |
30 | const {
31 | setMailboxName,
32 | setShowMailboxMessagesTable,
33 | setMailboxId,
34 | setUpdateMailboxToggle,
35 | setSelectedMailboxData,
36 | } = useActions(mailboxesLogic);
37 |
38 | const { setMessageDetailsToggle, setMessageSourceToggle, setMessageId, setAttachmentId } = useActions(
39 | messagesLogic,
40 | );
41 |
42 | const { mutate } = useDeleteMessagesInMailbox();
43 |
44 | const columns = React.useMemo(
45 | () =>
46 | getMailboxesColumns({
47 | dataSource: data,
48 | drilldown: (record: any) => {
49 | setShowMailboxMessagesTable(true);
50 | setMailboxId(record.id);
51 | setMailboxName(record.name);
52 | setMessageDetailsToggle(false);
53 | setMessageSourceToggle(false);
54 | setMessageId('');
55 | setAttachmentId('');
56 | },
57 | edit: (record: any) => {
58 | setUpdateMailboxToggle(true);
59 | setSelectedMailboxData({
60 | mailboxId: _.get(record, 'id'),
61 | path: _.get(record, 'path'),
62 | subscribed: _.get(record, 'subscribed'),
63 | hidden: !_.get(record, 'hidden'),
64 | retention: _.get(record, 'retention', 0),
65 | });
66 | },
67 | deleteAllMessages: (mailboxId: string) => mutate({ userId: id, mailboxId: mailboxId }),
68 | }),
69 | [data],
70 | );
71 |
72 | return (
73 | 10 ? null : false}
80 | />
81 | );
82 | };
83 |
84 | export default MailboxesTable;
85 |
--------------------------------------------------------------------------------
/src/components/Mailboxes/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Mailboxes Component
4 | */
5 |
6 | import Mailboxes from './Mailboxes';
7 |
8 | export default Mailboxes;
9 |
--------------------------------------------------------------------------------
/src/components/Messages/MailboxMessages.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description Messages Display
4 | */
5 |
6 | import React from 'react';
7 | import { List } from 'antd';
8 | import _ from 'lodash';
9 | import { useActions, useValues } from 'kea';
10 | import { useParams } from 'react-router-dom';
11 |
12 | import MessageList from './MessagesList';
13 | import MessagesSearch from './MessagesSearch';
14 | import { Pagination } from 'app-ui/utils/Pagination';
15 |
16 | import useMessages from 'app-ui/hooks/useMessages';
17 |
18 | import mailboxesLogic from 'app-ui/logic/mailboxesLogic';
19 | import messagesLogic from 'app-ui/logic/messagesLogic';
20 |
21 | const MailboxMessages: React.FC = () => {
22 | const { limit, next, previous, page, unseen } = useValues(messagesLogic);
23 | const { setLimit, setNext, setPrevious, setPage } = useActions(messagesLogic);
24 |
25 | const { mailboxId } = useValues(mailboxesLogic);
26 |
27 | const { id }: any = useParams();
28 |
29 | const { data: results, isLoading } = useMessages({
30 | userId: id,
31 | mailboxId: mailboxId,
32 | params: {
33 | unseen: unseen,
34 | page: page,
35 | next: page === 1 ? undefined : next || undefined,
36 | previous: previous || undefined,
37 | limit: limit,
38 | },
39 | });
40 |
41 | const { data, nextCursor, previousCursor } = _.isUndefined(results)
42 | ? { data: [], nextCursor: undefined, previousCursor: undefined }
43 | : results;
44 | setNext(nextCursor);
45 | setPrevious(previousCursor);
46 |
47 | return (
48 | <>
49 |
50 |
60 | }
67 | />
68 | >
69 | );
70 | };
71 |
72 | export default MailboxMessages;
73 |
--------------------------------------------------------------------------------
/src/components/Messages/MessageActions.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya
3 | * @description Messages Actions Component
4 | */
5 |
6 | import React from 'react';
7 | import { Space, Tooltip, Button } from 'antd';
8 | import { useActions } from 'kea';
9 | import { useParams } from 'react-router-dom';
10 |
11 | import { GetMessagesResult } from 'client/wildduck-api';
12 | import { MailOutlined, DeleteFilled } from '@ant-design/icons';
13 | import showConfirm from 'app-ui/utils/showConfirm';
14 |
15 | import useDeleteMessage from 'app-ui/hooks/useDeleteMessage';
16 |
17 | import messagesLogic from 'app-ui/logic/messagesLogic';
18 |
19 | const MessageActions: React.FC<{ messageDetails: GetMessagesResult }> = ({
20 | messageDetails,
21 | }: {
22 | messageDetails: GetMessagesResult;
23 | }) => {
24 | const { id }: any = useParams();
25 | const { mutate } = useDeleteMessage();
26 | const { setMessageId, setMessageSourceToggle } = useActions(messagesLogic);
27 |
28 | return (
29 |
30 |
31 |
41 |
42 |
43 |
54 |
55 |
56 | );
57 | };
58 |
59 | export default MessageActions;
60 |
--------------------------------------------------------------------------------
/src/components/Messages/MessageSource.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description MessagesSource Component
4 | */
5 |
6 | import React from 'react';
7 | import { Card, Breadcrumb } from 'antd';
8 | import BraftEditor from 'braft-editor';
9 | import { useParams } from 'react-router-dom';
10 | import { useActions, useValues } from 'kea';
11 |
12 | import Page from '../Page';
13 |
14 | import mailboxesLogic from 'app-ui/logic/mailboxesLogic';
15 | import messagesLogic from 'app-ui/logic/messagesLogic';
16 |
17 | import useMessageSource from 'app-ui/hooks/useMessageSource';
18 |
19 | const MessageSource: React.FC = () => {
20 | const { mailboxId, mailboxName } = useValues(mailboxesLogic);
21 | const { setUpdateMailboxToggle, setShowMailboxMessagesTable } = useActions(mailboxesLogic);
22 |
23 | const { setMessageSourceToggle } = useActions(messagesLogic);
24 | const { messageId } = useValues(messagesLogic);
25 |
26 | const { id }: any = useParams();
27 |
28 | const { data } = useMessageSource({ userId: id, mailboxId: mailboxId, messageNumber: messageId });
29 |
30 | const pageBreadcrumb = (
31 |
32 |
33 | {
35 | event.stopPropagation();
36 | setUpdateMailboxToggle(false);
37 | setShowMailboxMessagesTable(false);
38 | }}
39 | >
40 | Mailboxes
41 |
42 |
43 |
44 | {
46 | event.stopPropagation();
47 | setMessageSourceToggle(false);
48 | }}
49 | >
50 | {mailboxName}
51 |
52 |
53 | Message Source
54 |
55 | );
56 |
57 | return (
58 |
59 |
60 |
61 |
62 |
63 | );
64 | };
65 |
66 | export default MessageSource;
67 |
--------------------------------------------------------------------------------
/src/components/Messages/Messages.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Messages Component
4 | */
5 |
6 | import React from 'react';
7 | import { Breadcrumb } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 |
10 | import MailboxMessages from './MailboxMessages';
11 | import { Page } from '../Page/Page';
12 | import MessageSource from './MessageSource';
13 | import MessageDetails from './MessageDetails';
14 |
15 | import messagesLogic from 'app-ui/logic/messagesLogic';
16 | import mailboxesLogic from 'app-ui/logic/mailboxesLogic';
17 |
18 | /**
19 | * Messages Component
20 | */
21 | const Messages: React.FC = () => {
22 | const { setUpdateMailboxToggle, setShowMailboxMessagesTable } = useActions(mailboxesLogic);
23 | const { mailboxName } = useValues(mailboxesLogic);
24 | const { messageSourceToggle, messageDetailsToggle } = useValues(messagesLogic);
25 |
26 | const pageBreadcrumb = (
27 |
28 |
29 | {
31 | event.stopPropagation();
32 | setUpdateMailboxToggle(false);
33 | setShowMailboxMessagesTable(false);
34 | }}
35 | >
36 | Mailboxes
37 |
38 |
39 | {mailboxName}
40 |
41 | );
42 |
43 | if (messageDetailsToggle) {
44 | return ;
45 | } else if (messageSourceToggle) {
46 | return ;
47 | } else {
48 | return (
49 |
50 |
51 |
52 | );
53 | }
54 | // }
55 | };
56 |
57 | export default Messages;
58 |
--------------------------------------------------------------------------------
/src/components/Messages/MessagesList.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Messages List Component
4 | */
5 |
6 | import React from 'react';
7 | import { List } from 'antd';
8 | import moment from 'moment';
9 | import { useActions } from 'kea';
10 |
11 | import { GetMessagesResult } from 'client/wildduck-api';
12 | import { DATE_TIME_FORMAT_AP } from 'app-ui/utils/constants';
13 | import MessageActions from './MessageActions';
14 |
15 | import messagesLogic from 'app-ui/logic/messagesLogic';
16 |
17 | const MessageList: React.FC<{ item: GetMessagesResult }> = ({ item }: { item: GetMessagesResult }) => {
18 | const { setMessageId, setMessageDetailsToggle } = useActions(messagesLogic);
19 | return (
20 | }>
21 | {
25 | setMessageId(item.id);
26 | setMessageDetailsToggle(true);
27 | }}
28 | >
29 | {`${item.from.name}<${item.from.address}> ${moment(item.date).format(DATE_TIME_FORMAT_AP)}`}
30 |
31 | }
32 | description={`${item.subject} - ${item.intro}`}
33 | />
34 |
35 | );
36 | };
37 |
38 | export default MessageList;
39 |
--------------------------------------------------------------------------------
/src/components/Messages/MessagesSearch.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description MessagesSearch Component
4 | */
5 |
6 | import React from 'react';
7 | import _ from 'lodash';
8 | import { Button, Form, Switch } from 'antd';
9 | import { useActions } from 'kea';
10 |
11 | import messagesLogic from 'app-ui/logic/messagesLogic';
12 |
13 | /**
14 | * MessagesSearch Component
15 | */
16 | const MessagesSearch: React.FC = () => {
17 | const { setUnseen } = useActions(messagesLogic);
18 |
19 | const [form] = Form.useForm();
20 |
21 | const onFinish = ({ unseen }: any) => {
22 | setUnseen(unseen);
23 | };
24 |
25 | return (
26 |
33 |
34 |
35 |
36 |
39 |
40 |
41 | );
42 | };
43 |
44 | export default MessagesSearch;
45 |
--------------------------------------------------------------------------------
/src/components/Messages/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Messages Component
4 | */
5 |
6 | import Messages from './Messages';
7 |
8 | export default Messages;
9 |
--------------------------------------------------------------------------------
/src/components/NavigationBar/index.ts:
--------------------------------------------------------------------------------
1 | import NavigationLogic from 'app-ui/logic/navigationLogic';
2 | import NavigationBar from './NavigationBar';
3 |
4 | export default NavigationLogic(NavigationBar) as any;
5 |
--------------------------------------------------------------------------------
/src/components/Page/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | * @description container for Page component
4 | */
5 |
6 | import Page from './Page';
7 |
8 | export default Page;
9 |
--------------------------------------------------------------------------------
/src/components/ResolveId/ResolveId.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description resolve id screen
4 | */
5 |
6 | import React from 'react';
7 | import { Input, Descriptions, Breadcrumb, Card } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 |
10 | import Page from '../Page';
11 | import Link from 'app-ui/components/CustomLink';
12 |
13 | import dkimLogic from 'app-ui/logic/dkimLogic';
14 |
15 | /**
16 | * ResolveId component
17 | */
18 | const ResolveId: React.FC = () => {
19 | const { Search } = Input;
20 | const { resolveId } = useActions(dkimLogic);
21 | const { domainId } = useValues(dkimLogic);
22 | const onSearch = (value: any) => {
23 | if (value.length > 0) {
24 | resolveId(value);
25 | }
26 | };
27 | const descriptionBox = (
28 |
29 |
30 | {domainId}
31 |
32 |
33 | );
34 |
35 | const pageBreadcrumb = (
36 |
37 |
38 | DKIM
39 |
40 |
41 | Resolve DKIM ID
42 |
43 | );
44 | return (
45 |
46 |
47 | {domainId.length > 0 && descriptionBox}
48 |
49 | );
50 | };
51 |
52 | export default ResolveId;
53 |
--------------------------------------------------------------------------------
/src/components/ResolveId/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description resolve id screen container
4 | */
5 |
6 | import ResolveId from './ResolveId';
7 |
8 | export default ResolveId;
9 |
--------------------------------------------------------------------------------
/src/components/User/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for User Component
4 | */
5 |
6 | import User from './User';
7 |
8 | export default User;
9 |
--------------------------------------------------------------------------------
/src/components/Users/FilterSearch.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description FilterSearch Component
4 | */
5 |
6 | import React from 'react';
7 | import { Button, Form, Input } from 'antd';
8 | import { useActions } from 'kea';
9 |
10 | import usersLogic from 'app-ui/logic/usersLogic';
11 |
12 | /**
13 | * FilterSearch Component
14 | */
15 | const FilterSearch: React.FC = () => {
16 | const { setSearchParams } = useActions(usersLogic);
17 |
18 | const [form] = Form.useForm();
19 |
20 | const onFinish = (values: any) => {
21 | setSearchParams(values);
22 | };
23 |
24 | return (
25 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 |
50 | );
51 | };
52 |
53 | export default FilterSearch;
54 |
--------------------------------------------------------------------------------
/src/components/Users/ResetPassword.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description ResetPassword screen
4 | */
5 |
6 | import React from 'react';
7 | import { Modal, Typography } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 |
10 | import usersLogic from 'app-ui/logic/usersLogic';
11 |
12 | const ResetPassword: React.FC = () => {
13 | const { setShowResetPasswordModal, setPassword } = useActions(usersLogic);
14 | const { password, showResetPasswordModal } = useValues(usersLogic);
15 |
16 | return (
17 | {
22 | setShowResetPasswordModal(false);
23 | setPassword('');
24 | }}
25 | >
26 | {password}
27 |
28 | );
29 | };
30 |
31 | export default ResetPassword;
32 |
--------------------------------------------------------------------------------
/src/components/Users/Users.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Users screen
4 | */
5 |
6 | import React from 'react';
7 | import { Button } from 'antd';
8 |
9 | import Link from 'app-ui/components/CustomLink';
10 | import Page from 'components/Page';
11 | import showConfirm from 'app-ui/utils/showConfirm';
12 | import FilterSearch from './FilterSearch';
13 | import UsersTable from './UsersTable';
14 | import ResetPassword from './ResetPassword';
15 |
16 | import useRecalculateQuotaForAll from 'app-ui/hooks/useRecalculateQuotaForAll';
17 |
18 | const Users: React.FC = () => {
19 | const { mutate } = useRecalculateQuotaForAll();
20 |
21 | return (
22 |
28 | showConfirm(() => mutate(), 'Are you sure you want to Recalculate Quota For All Users ?')
29 | }
30 | >
31 | Recalculate Quota For All Users
32 | ,
33 | ,
36 | ]}
37 | >
38 |
39 |
40 |
41 |
42 | );
43 | };
44 |
45 | export default Users;
46 |
--------------------------------------------------------------------------------
/src/components/Users/UsersTable.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Users Table
4 | */
5 |
6 | import React from 'react';
7 | import { Table } from 'antd';
8 | import { useActions, useValues } from 'kea';
9 | import _ from 'lodash';
10 |
11 | import { getUsersColumns } from './Columns';
12 | import { Pagination } from 'app-ui/utils/Pagination';
13 |
14 | import useUsers from 'app-ui/hooks/useUsers';
15 | import useDeleteUser from 'app-ui/hooks/useDeleteUser';
16 |
17 | import usersLogic from 'app-ui/logic/usersLogic';
18 |
19 | const UsersTable: React.FC = () => {
20 | const { setPage, setLimit, setNext, setPrevious } = useActions(usersLogic);
21 | const { searchParams, limit, page, next, previous } = useValues(usersLogic);
22 |
23 | const { data: results, isLoading } = useUsers({
24 | query: searchParams?.query,
25 | tags: searchParams?.tags,
26 | requiredTags: searchParams?.requiredTags,
27 | page: page,
28 | next: page === 1 ? undefined : next || undefined,
29 | previous: previous || undefined,
30 | limit: limit,
31 | });
32 |
33 | const { data, nextCursor, previousCursor } = _.isUndefined(results)
34 | ? { data: [], nextCursor: undefined, previousCursor: undefined }
35 | : results;
36 | setNext(nextCursor);
37 | setPrevious(previousCursor);
38 |
39 | const { mutate } = useDeleteUser();
40 |
41 | const columns = React.useMemo(
42 | () => getUsersColumns({ dataSource: data, deleteUser: (userId: string) => mutate(userId) }),
43 | [data],
44 | );
45 |
46 | return (
47 | <>
48 |
58 |
68 | >
69 | );
70 | };
71 |
72 | export default UsersTable;
73 |
--------------------------------------------------------------------------------
/src/components/Users/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Container for Users Component
4 | */
5 |
6 | import Users from './Users';
7 |
8 | export default Users;
9 |
--------------------------------------------------------------------------------
/src/components/Widgets/Link.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description Link
4 | */
5 |
6 | import React from 'react';
7 |
8 | import Link from 'app-ui/components/CustomLink';
9 |
10 | interface IProps {
11 | name: string | JSX.Element;
12 | id: string;
13 | }
14 |
15 | /** ForwardedAddress link */
16 | const ForwardedAddressLink = ({ id, name }: IProps): JSX.Element => {
17 | return {name};
18 | };
19 |
20 | /** UserLink link */
21 | const UserLink = ({ id, name }: IProps): JSX.Element => {
22 | return {name};
23 | };
24 |
25 | /** DkimDetailsLink */
26 | const DkimDetailsLink = ({ id, name }: IProps): JSX.Element => {
27 | return {name};
28 | };
29 |
30 | export { ForwardedAddressLink, UserLink, DkimDetailsLink };
31 |
--------------------------------------------------------------------------------
/src/components/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import store from 'store/index';
5 | import AxiosInterceptor from 'app-ui/lib/axios/AxiosInterceptors';
6 | import { apiString } from 'app-ui/lib/constants/constant';
7 |
8 | new AxiosInterceptor().inject({
9 | baseURL: sessionStorage.getItem(apiString),
10 | headers: { 'Content-Type': 'application/json' },
11 | });
12 |
13 | const MainApp = React.lazy(() => import('./App'));
14 |
15 | const PersistedApp = () => (
16 |
17 | >}>
18 |
19 |
20 |
21 | );
22 |
23 | ReactDOM.render(, document.getElementById('root'));
24 |
25 | if ((module as any).hot) {
26 | (module as any).hot.accept('./index', () => {
27 | // tslint:disable-next-line: variable-name
28 | const NextApp = require('./index').default;
29 | ReactDOM.render(, document.getElementById('root'));
30 | });
31 | }
32 |
--------------------------------------------------------------------------------
/src/hooks/useAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useAddress
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | /**
13 | * useAddress
14 | */
15 | const useAddress = (userId: string) => {
16 | return useQuery(['useAddress'], async () => {
17 | const { data } = await api.addressApi.getUserAddresses(userId);
18 | return addKey(_.get(data, 'results', []));
19 | });
20 | };
21 |
22 | export default useAddress;
23 |
--------------------------------------------------------------------------------
/src/hooks/useAddressInformation.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useAddressInformation
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 |
10 | /**
11 | * useAddressInformation
12 | */
13 | const useAddressInformation = (userId: string, addressId: string) => {
14 | return useQuery(['useAddressInformation', addressId], async () => {
15 | const { data } = await api.addressApi.getUserAddress(userId, addressId);
16 | return data;
17 | });
18 | };
19 |
20 | export default useAddressInformation;
21 |
--------------------------------------------------------------------------------
/src/hooks/useAllowedList.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useAllowedList
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import api from 'client/RequestClient';
10 |
11 | /*
12 | * useAllowedList
13 | */
14 |
15 | const useAllowedList = (tag: string) => {
16 | return useQuery(
17 | ['query-allowList', tag],
18 | async () => {
19 | const { data } = await api.domainAccessApi.getAllowedDomain(tag);
20 | return _.get(data, 'results', []);
21 | },
22 | { enabled: !_.isEmpty(tag), staleTime: 3000 },
23 | );
24 | };
25 |
26 | export default useAllowedList;
27 |
--------------------------------------------------------------------------------
/src/hooks/useArchive.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useArchive
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | interface IParam {
13 | userId: string;
14 | params: any;
15 | }
16 |
17 | /**
18 | * useArchive
19 | */
20 | const useArchive = ({ userId, params }: IParam) => {
21 | return useQuery(['useArchive', params?.limit, params?.page], async () => {
22 | const { data } = await api.archiveApi.getArchivedMessages(
23 | userId,
24 | _.get(params, 'limit'),
25 | _.get(params, 'page'),
26 | _.get(params, 'order'),
27 | _.get(params, 'next'),
28 | _.get(params, 'previous'),
29 | );
30 | return {
31 | previousCursor: _.get(data, 'previousCursor', ''),
32 | nextCursor: _.get(data, 'nextCursor', ''),
33 | data: addKey(_.get(data, 'results', []), ['messageId', 'mailbox', 'thread', 'id']),
34 | };
35 | });
36 | };
37 |
38 | export default useArchive;
39 |
--------------------------------------------------------------------------------
/src/hooks/useAuthentication.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useAuthentication
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import api from 'client/RequestClient';
10 | import { addKey } from 'app-ui/utils/logicUtils';
11 |
12 | /**
13 | * useAuthentication
14 | */
15 | const useAuthentication = (userId: string, params: any) => {
16 | return useQuery(['useAuthentication', userId, params?.limit, params?.page], async () => {
17 | const { data } = await api.authenticationApi.getAuthlog(
18 | userId,
19 | _.get(params, 'action'),
20 | _.get(params, 'filterIp'),
21 | _.get(params, 'limit'),
22 | _.get(params, 'page'),
23 | _.get(params, 'next'),
24 | _.get(params, 'previous'),
25 | );
26 | return {
27 | data: addKey(_.get(data, 'results', [])),
28 | previousCursor: _.get(data, 'previousCursor', ''),
29 | nextCursor: _.get(data, 'nextCursor', ''),
30 | };
31 | });
32 | };
33 |
34 | export default useAuthentication;
35 |
--------------------------------------------------------------------------------
/src/hooks/useAutoreplyDetails.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useAutoreplyDetails
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 |
10 | /**
11 | * useAutoreplyDetails
12 | */
13 | const useAutoreplyDetails = (userId: string) => {
14 | return useQuery(['useAutoreplyDetails', userId], async () => {
15 | const { data } = await api.autorepliesApi.getAutoreply(userId);
16 | return data;
17 | });
18 | };
19 |
20 | export default useAutoreplyDetails;
21 |
--------------------------------------------------------------------------------
/src/hooks/useBlockedList.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useBlockedList
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import api from 'client/RequestClient';
10 |
11 | /*
12 | * useBlockedList
13 | */
14 |
15 | const useBlockedList = (tag: string) => {
16 | return useQuery(
17 | ['query-blockList', tag],
18 | async () => {
19 | const { data } = await api.domainAccessApi.getBlockedDomain(tag);
20 | return _.get(data, 'results', []);
21 | },
22 | { enabled: !_.isEmpty(tag), staleTime: 3000 },
23 | );
24 | };
25 |
26 | export default useBlockedList;
27 |
--------------------------------------------------------------------------------
/src/hooks/useCreateAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useCreateAddress
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateUserAddressRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | interface IProp {
14 | userId: string;
15 | addressDetails: CreateUserAddressRequest;
16 | }
17 |
18 | /**
19 | * useCreateAddress
20 | */
21 | const useCreateAddress = () => {
22 | const queryClient = useQueryClient();
23 |
24 | return useMutation(
25 | ({ userId, addressDetails }: IProp) => api.addressApi.createUserAddress(userId, addressDetails),
26 | {
27 | onError: () => {
28 | AppEvents.publish(Events.Error, 'Error');
29 | },
30 | onSuccess: ({ data }) => {
31 | handleError(data);
32 | queryClient.invalidateQueries('useAddress');
33 | },
34 | },
35 | );
36 | };
37 |
38 | export default useCreateAddress;
39 |
--------------------------------------------------------------------------------
/src/hooks/useCreateAllowedDomain.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useCreateAllowedDomain
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /*
12 | * useCreateAllowedDomain
13 | */
14 | const useCreateAllowedDomain = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation(
18 | (domain: { tag: string; domain: string }) =>
19 | api.domainAccessApi.createAllowedDomain(domain.tag, { domain: domain.domain }),
20 | {
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('query-allowList');
24 | queryClient.invalidateQueries('query-blockList');
25 | },
26 | onError: () => {
27 | AppEvents.publish(Events.Error, 'Error');
28 | },
29 | },
30 | );
31 | };
32 |
33 | export default useCreateAllowedDomain;
34 |
--------------------------------------------------------------------------------
/src/hooks/useCreateBlockedDomain.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useCreateBlockedDomain
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /*
12 | * useCreateBlockedDomain
13 | */
14 | const useCreateBlockedDomain = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation(
18 | (domain: { tag: string; domain: string }) =>
19 | api.domainAccessApi.createBlockedDomain(domain.tag, { domain: domain.domain }),
20 | {
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('query-blockList');
24 | queryClient.invalidateQueries('query-allowList');
25 | },
26 | onError: () => {
27 | AppEvents.publish(Events.Error, 'Error');
28 | },
29 | },
30 | );
31 | };
32 |
33 | export default useCreateBlockedDomain;
34 |
--------------------------------------------------------------------------------
/src/hooks/useCreateDkim.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useCreateDkim
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import api from 'client/RequestClient';
10 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
11 | import { UpdateDkimKeyRequest } from 'client/wildduck-api';
12 |
13 | /*
14 | * useCreateDkim
15 | */
16 | const useCreateDkim = () => {
17 | const queryClient = useQueryClient();
18 |
19 | return useMutation((dkim: UpdateDkimKeyRequest) => api.dkimApi.updateDkimKey(dkim), {
20 | onSuccess: () => {
21 | AppEvents.publish(Events.Success, 'Success');
22 | queryClient.invalidateQueries('query-dkim');
23 | },
24 | onError: () => {
25 | AppEvents.publish(Events.Error, 'Error');
26 | },
27 | });
28 | };
29 |
30 | export default useCreateDkim;
31 |
--------------------------------------------------------------------------------
/src/hooks/useCreateDomainAliases.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useCreateDomainAliases
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateDomainAliasRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | /**
14 | * useCreateDomainAliases
15 | */
16 | const useCreateDomainAliases = () => {
17 | return useMutation(
18 | (newDomainAlias: CreateDomainAliasRequest) => api.domainAliasesApi.createDomainAlias(newDomainAlias),
19 | {
20 | onError: () => {
21 | AppEvents.publish(Events.Error, 'Error');
22 | },
23 | onSuccess: ({ data }) => {
24 | handleError(data);
25 | },
26 | },
27 | );
28 | };
29 |
30 | export default useCreateDomainAliases;
31 |
--------------------------------------------------------------------------------
/src/hooks/useCreateFilter.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useCreateFilter
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateFilterRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | /**
14 | * useCreateFilter
15 | */
16 | const useCreateFilter = () => {
17 | return useMutation(
18 | ({ userId, filterDetails }: { userId: string; filterDetails: CreateFilterRequest }) =>
19 | api.filtersApi.createFilter(userId, filterDetails),
20 | {
21 | onError: () => {
22 | AppEvents.publish(Events.Error, 'Error');
23 | },
24 | onSuccess: ({ data }) => {
25 | handleError(data);
26 | },
27 | },
28 | );
29 | };
30 |
31 | export default useCreateFilter;
32 |
--------------------------------------------------------------------------------
/src/hooks/useCreateForwardedAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useCreateForwardedAddress
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateForwardedAddressRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | /**
14 | * useCreateForwardedAddress
15 | */
16 | const useCreateForwardedAddress = () => {
17 | return useMutation(
18 | (newForwardedAddress: CreateForwardedAddressRequest) =>
19 | api.addressApi.createForwardedAddress(newForwardedAddress),
20 | {
21 | onError: () => {
22 | AppEvents.publish(Events.Error, 'Error');
23 | },
24 | onSuccess: ({ data }) => {
25 | handleError(data);
26 | },
27 | },
28 | );
29 | };
30 |
31 | export default useCreateForwardedAddress;
32 |
--------------------------------------------------------------------------------
/src/hooks/useCreateUser.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useCreateUser
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateUserRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | /**
14 | * useCreateUser
15 | */
16 | const useCreateUser = () => {
17 | return useMutation((user: CreateUserRequest) => api.usersApi.createUser(user), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: ({ data }) => {
22 | handleError(data);
23 | },
24 | });
25 | };
26 |
27 | export default useCreateUser;
28 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteAddress
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | interface IDeleteAddress {
12 | userId: string;
13 | addressId: string;
14 | }
15 |
16 | /**
17 | * useDeleteAddress
18 | */
19 | const useDeleteAddress = () => {
20 | const queryClient = useQueryClient();
21 |
22 | return useMutation(({ userId, addressId }: IDeleteAddress) => api.addressApi.deleteUserAddress(userId, addressId), {
23 | onError: () => {
24 | AppEvents.publish(Events.Error, 'Error');
25 | },
26 | onSuccess: () => {
27 | AppEvents.publish(Events.Success, 'Success');
28 | queryClient.invalidateQueries('useAddress');
29 | },
30 | });
31 | };
32 |
33 | export default useDeleteAddress;
34 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteAutoreply.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteAutoreply
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useDeleteAutoreply
13 | */
14 | const useDeleteAutoreply = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((userId: string) => api.autorepliesApi.deleteAutoreply(userId), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('useAutoreplyDetails');
24 | },
25 | });
26 | };
27 |
28 | export default useDeleteAutoreply;
29 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteDkim.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useDeleteDkim
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /*
12 | * useDeleteDkim
13 | */
14 | const useDeleteDkim = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((dkimId: string) => api.dkimApi.deleteDkimKey(dkimId), {
18 | onSuccess: () => {
19 | AppEvents.publish(Events.Success, 'Success');
20 | queryClient.invalidateQueries('query-dkim');
21 | },
22 | onError: () => {
23 | AppEvents.publish(Events.Error, 'Error');
24 | },
25 | });
26 | };
27 |
28 | export default useDeleteDkim;
29 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteDomain.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useDeleteDomain
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /*
12 | * useDeleteDomain
13 | */
14 | const useDeleteDomain = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((id: string) => api.domainAccessApi.deleteDomainListing(id), {
18 | onSuccess: () => {
19 | AppEvents.publish(Events.Success, 'Deleted !');
20 | queryClient.invalidateQueries('query-blockList');
21 | queryClient.invalidateQueries('query-allowList');
22 | },
23 | onError: () => {
24 | AppEvents.publish(Events.Error, 'Error');
25 | },
26 | });
27 | };
28 |
29 | export default useDeleteDomain;
30 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteDomainAliases.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteDomainAliases
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useDeleteDomainAliases
13 | */
14 | const useDeleteDomainAliases = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((aliasId: string) => api.domainAliasesApi.deleteDomainAlias(aliasId), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('useDomainAliases');
24 | },
25 | });
26 | };
27 |
28 | export default useDeleteDomainAliases;
29 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteFilter.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteFilter
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateFilterRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | /**
14 | * useDeleteFilter
15 | */
16 | const useDeleteFilter = () => {
17 | const queryClient = useQueryClient();
18 |
19 | return useMutation(
20 | ({ userId, filterId }: { userId: string; filterId: string }) => api.filtersApi.deleteFilter(userId, filterId),
21 | {
22 | onError: () => {
23 | AppEvents.publish(Events.Error, 'Error');
24 | },
25 | onSuccess: ({ data }) => {
26 | handleError(data);
27 | queryClient.invalidateQueries('query-filters');
28 | },
29 | },
30 | );
31 | };
32 |
33 | export default useDeleteFilter;
34 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteForwardedAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteForwadedAddress
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useDeleteForwadedAddress
13 | */
14 | const useDeleteForwadedAddress = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((addressId: string) => api.addressApi.deleteForwardedAddress(addressId), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('useForwardedAddress');
24 | },
25 | });
26 | };
27 |
28 | export default useDeleteForwadedAddress;
29 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteMessage.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteMessage
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | interface IParams {
12 | userId: string;
13 | mailboxId: string;
14 | messageNumber: number;
15 | }
16 |
17 | /**
18 | * useDeleteMessage
19 | */
20 | const useDeleteMessage = () => {
21 | const queryClient = useQueryClient();
22 |
23 | return useMutation(
24 | ({ userId, mailboxId, messageNumber }: IParams) =>
25 | api.messagesApi.deleteMessage(userId, mailboxId, messageNumber),
26 | {
27 | onError: () => {
28 | AppEvents.publish(Events.Error, 'Error');
29 | },
30 | onSuccess: () => {
31 | AppEvents.publish(Events.Success, 'Success');
32 | queryClient.invalidateQueries('useMessages');
33 | },
34 | },
35 | );
36 | };
37 |
38 | export default useDeleteMessage;
39 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteMessagesInMailbox.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteMessagesInMailbox
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | interface IParams {
12 | userId: string;
13 | mailboxId: string;
14 | }
15 |
16 | /**
17 | * useDeleteMessagesInMailbox
18 | */
19 | const useDeleteMessagesInMailbox = () => {
20 | const queryClient = useQueryClient();
21 |
22 | return useMutation(({ userId, mailboxId }: IParams) => api.messagesApi.deleteMessagesInMailbox(userId, mailboxId), {
23 | onError: () => {
24 | AppEvents.publish(Events.Error, 'Error');
25 | },
26 | onSuccess: () => {
27 | AppEvents.publish(Events.Success, 'Success');
28 | queryClient.invalidateQueries('useMailboxes');
29 | },
30 | });
31 | };
32 |
33 | export default useDeleteMessagesInMailbox;
34 |
--------------------------------------------------------------------------------
/src/hooks/useDeleteUser.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDeleteUser
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useDeleteUser
13 | */
14 | const useDeleteUser = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((userId: string) => api.usersApi.deleteUser(userId), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('useUsers');
24 | },
25 | });
26 | };
27 |
28 | export default useDeleteUser;
29 |
--------------------------------------------------------------------------------
/src/hooks/useDkim.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useDkim
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | /*
13 | * useDkim
14 | */
15 |
16 | interface DkimProps {
17 | query?: string;
18 | limit?: number;
19 | next?: number;
20 | previous?: number;
21 | page?: number;
22 | }
23 |
24 | const useDkim = ({ query = '', limit, page, next, previous }: DkimProps) => {
25 | return useQuery(['query-dkim', query, page, limit], async () => {
26 | const { data } = await api.dkimApi.getDkimKeys(query, limit, page, _.toString(next), _.toString(previous));
27 | return {
28 | previousCursor: _.get(data, 'previousCursor'),
29 | nextCursor: _.get(data, 'nextCursor'),
30 | data: addKey(_.get(data, 'results', [])),
31 | };
32 | });
33 | };
34 |
35 | export default useDkim;
36 |
--------------------------------------------------------------------------------
/src/hooks/useDkimDetails.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useDkimDetails
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import api from 'client/RequestClient';
10 |
11 | /*
12 | * useDkimDetails
13 | */
14 | const useDkimDetails = (dkimId: string) => {
15 | return useQuery(
16 | ['query-dkim', dkimId],
17 | async () => {
18 | const { data } = await api.dkimApi.getDkimKey(dkimId);
19 | return data;
20 | },
21 | { enabled: !_.isEmpty(dkimId) },
22 | );
23 | };
24 |
25 | export default useDkimDetails;
26 |
--------------------------------------------------------------------------------
/src/hooks/useDomainAliases.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDomainAliases
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | /**
13 | * useDomainAliases
14 | */
15 | const useDomainAliases = (params: any) => {
16 | return useQuery(['useDomainAliases', params?.query, params?.limit, params?.page], async () => {
17 | const { data } = await api.domainAliasesApi.getDomainAliases(
18 | _.get(params, 'query'),
19 | _.get(params, 'limit'),
20 | _.get(params, 'page'),
21 | _.get(params, 'next'),
22 | _.get(params, 'previous'),
23 | );
24 |
25 | return {
26 | previousCursor: _.get(data, 'previousCursor'),
27 | nextCursor: _.get(data, 'nextCursor'),
28 | data: addKey(_.get(data, 'results', [])),
29 | };
30 | });
31 | };
32 |
33 | export default useDomainAliases;
34 |
--------------------------------------------------------------------------------
/src/hooks/useDownloadAttachment.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useDownloadAttachment
4 | */
5 |
6 | import _ from 'lodash';
7 | import { useQuery } from 'react-query';
8 |
9 | import api from 'client/RequestClient';
10 |
11 | interface IParams {
12 | userId: string;
13 | attachment: any;
14 | mailboxId: string;
15 | messageId: number;
16 | }
17 |
18 | /**
19 | * useDownloadAttachment
20 | */
21 | const useDownloadAttachment = ({ userId, attachment, mailboxId, messageId }: IParams) => {
22 | return useQuery(
23 | ['useDownloadAttachment', mailboxId, messageId, attachment],
24 | async () => {
25 | const { contentType, id, filename } = attachment;
26 | const { data } = await api.messagesApi.getMessageAttachment(userId, mailboxId, messageId, id, {
27 | responseType: 'blob',
28 | });
29 | const link = document.createElement('a');
30 | const fileCreated = new Blob([data], { type: contentType });
31 | link.href = URL.createObjectURL(fileCreated);
32 | link.download = filename;
33 | link.click();
34 | },
35 | { enabled: !_.isEmpty(messageId) && !_.isEmpty(attachment) },
36 | );
37 | };
38 |
39 | export default useDownloadAttachment;
40 |
--------------------------------------------------------------------------------
/src/hooks/useFIlterDetails.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useFilterDetails
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import api from 'client/RequestClient';
10 |
11 | /*
12 | * useFilterDetails
13 | */
14 |
15 | const useFilterDetails = (id: string, filterId: string) => {
16 | return useQuery(
17 | ['query-filterDetails', id, filterId],
18 | async () => {
19 | const { data } = await api.filtersApi.getFilter(id, filterId);
20 | const details = {};
21 | _.assign(
22 | details,
23 | _.get(data, 'query', {}),
24 | _.get(data, 'action', {}),
25 | _.pick(data, ['id', 'name', 'disabled']),
26 | );
27 | return details;
28 | },
29 | { enabled: !_.isEmpty(filterId) },
30 | );
31 | };
32 |
33 | export default useFilterDetails;
34 |
--------------------------------------------------------------------------------
/src/hooks/useFilters.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description React hook useFilters
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | /*
13 | * useFilters
14 | */
15 |
16 | const useFilters = (id: string) => {
17 | return useQuery(
18 | ['query-filters', id],
19 | async () => {
20 | const { data } = await api.filtersApi.getFilters(id);
21 | return addKey(_.get(data, 'results', []));
22 | },
23 | { enabled: !_.isEmpty(id) },
24 | );
25 | };
26 |
27 | export default useFilters;
28 |
--------------------------------------------------------------------------------
/src/hooks/useForwardedAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useForwadedAddress
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | /**
13 | * useForwadedAddress
14 | */
15 | const useForwadedAddress = (params?: Address.IParams) => {
16 | return useQuery(['useForwardedAddress', params?.query], async () => {
17 | let addressList: any = [];
18 | let response = await api.addressApi.getAddresses(
19 | _.get(params, 'query', ' '),
20 | '',
21 | _.get(params, 'tags', ' '),
22 | _.get(params, 'requiredTags', ' '),
23 | _.get(params, 'metaData', false),
24 | _.get(params, 'internalData', false),
25 | _.get(params, 'limit', 250),
26 | _.get(params, 'page', 1),
27 | _.toString(_.get(params, 'next')),
28 | _.toString(_.get(params, 'previous')),
29 | );
30 |
31 | addressList = _.get(response, 'data.results', []);
32 |
33 | while (!_.isEmpty(_.get(response, 'nextCursor'))) {
34 | response = await api.addressApi.getAddresses(
35 | _.get(params, 'query', ' '),
36 | '',
37 | _.get(params, 'tags', ' '),
38 | _.get(params, 'requiredTags', ' '),
39 | _.get(params, 'metaData', false),
40 | _.get(params, 'internalData', false),
41 | _.get(params, 'limit', 250),
42 | _.get(params, 'page', 1),
43 | _.toString(_.get(params, 'next')),
44 | _.toString(_.get(params, 'previous')),
45 | );
46 |
47 | _.concat(addressList, _.get(response, 'data.results', []));
48 | }
49 | return addKey(addressList);
50 | });
51 | };
52 |
53 | export default useForwadedAddress;
54 |
--------------------------------------------------------------------------------
/src/hooks/useForwardedAddressInformation.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useForwardedAddressInformation
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 |
10 | /**
11 | * useForwardedAddressInformation
12 | */
13 | const useForwardedAddressInformation = (addressId: string) => {
14 | return useQuery(['useForwardedAddressInformation', addressId], async () => {
15 | const { data } = await api.addressApi.getForwardedAddress(addressId);
16 | return data;
17 | });
18 | };
19 |
20 | export default useForwardedAddressInformation;
21 |
--------------------------------------------------------------------------------
/src/hooks/useLogoutUser.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useLogoutUser
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useLogoutUser
13 | */
14 | const useLogoutUser = () => {
15 | return useMutation((userId: string) => api.usersApi.logoutUser(userId, { reason: 'you have been logged out' }), {
16 | onError: () => {
17 | AppEvents.publish(Events.Error, 'Error');
18 | },
19 | onSuccess: () => {
20 | AppEvents.publish(Events.Success, 'Success');
21 | },
22 | });
23 | };
24 |
25 | export default useLogoutUser;
26 |
--------------------------------------------------------------------------------
/src/hooks/useMailboxes.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useMailboxes
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | interface IParams {
13 | userId: string;
14 | params?: any;
15 | }
16 |
17 | /**
18 | * useMailboxes
19 | */
20 | const useMailboxes = ({ userId, params }: IParams) => {
21 | return useQuery(['useMailboxes', params?.specialUse], async () => {
22 | if (!_.isEmpty(userId)) {
23 | const { data } = await api.mailboxesApi.getMailboxes(
24 | userId,
25 | _.get(params, 'specialUse'),
26 | _.get(params, 'showHidden', true),
27 | _.get(params, 'counters', true),
28 | _.get(params, 'sizes', true),
29 | );
30 | return addKey(_.get(data, 'results', []));
31 | }
32 | });
33 | };
34 |
35 | export default useMailboxes;
36 |
--------------------------------------------------------------------------------
/src/hooks/useMessageDetails.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useMessageDetails
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 |
10 | interface IParams {
11 | userId: string;
12 | messageId: any;
13 | mailboxId: string;
14 | }
15 |
16 | /**
17 | * useMessageDetails
18 | */
19 | const useMessageDetails = ({ userId, messageId, mailboxId }: IParams) => {
20 | return useQuery(['useMessageDetails', mailboxId, messageId], async () => {
21 | const { data } = await api.messagesApi.getMessage(userId, mailboxId, messageId);
22 | return data;
23 | });
24 | };
25 |
26 | export default useMessageDetails;
27 |
--------------------------------------------------------------------------------
/src/hooks/useMessageSource.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useMessageSource
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 |
10 | interface IParams {
11 | userId: string;
12 | mailboxId: string;
13 | messageNumber: number;
14 | }
15 | /**
16 | * useMessageSource
17 | */
18 | const useMessageSource = ({ userId, mailboxId, messageNumber }: IParams) => {
19 | return useQuery(['useMessageSource'], async () => {
20 | const { data } = await api.messagesApi.getMessageSource(userId, mailboxId, messageNumber);
21 |
22 | return data;
23 | });
24 | };
25 |
26 | export default useMessageSource;
27 |
--------------------------------------------------------------------------------
/src/hooks/useMessages.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useMessages
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | interface IParams {
13 | userId: string;
14 | mailboxId: string;
15 | params?: any;
16 | }
17 |
18 | /**
19 | * useMessages
20 | */
21 | const useMessages = ({ userId, mailboxId, params }: IParams) => {
22 | return useQuery(
23 | ['useMessages', userId, mailboxId, params?.limit, params?.page, params?.specialUse, params?.unseen],
24 | async () => {
25 | const { data } = await api.messagesApi.getMessages(
26 | userId,
27 | mailboxId,
28 | _.get(params, 'unseen'),
29 | _.get(params, 'metaData', true),
30 | _.get(params, 'limit'),
31 | _.get(params, 'page'),
32 | _.get(params, 'order'),
33 | _.get(params, 'next'),
34 | _.get(params, 'previous'),
35 | );
36 |
37 | return {
38 | data: addKey(_.get(data, 'results', []), ['messageId', 'mailbox', 'thread', 'id']),
39 | previousCursor: _.get(data, 'previousCursor', ''),
40 | nextCursor: _.get(data, 'nextCursor', ''),
41 | };
42 | },
43 | );
44 | };
45 |
46 | export default useMessages;
47 |
--------------------------------------------------------------------------------
/src/hooks/useRecalculateQuota.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useRecalculateQuota
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useRecalculateQuota
13 | */
14 | const useRecalculateQuota = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation((userId: string) => api.usersApi.recalculateQuota(userId), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('useUsers');
24 | },
25 | });
26 | };
27 |
28 | export default useRecalculateQuota;
29 |
--------------------------------------------------------------------------------
/src/hooks/useRecalculateQuotaForAll.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useRecalculateQuotaForAll
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useRecalculateQuotaForAll
13 | */
14 | const useRecalculateQuotaForAll = () => {
15 | const queryClient = useQueryClient();
16 |
17 | return useMutation(() => api.usersApi.recalculateQuotaAllUsers(), {
18 | onError: () => {
19 | AppEvents.publish(Events.Error, 'Error');
20 | },
21 | onSuccess: () => {
22 | AppEvents.publish(Events.Success, 'Success');
23 | queryClient.invalidateQueries('useUsers');
24 | },
25 | });
26 | };
27 |
28 | export default useRecalculateQuotaForAll;
29 |
--------------------------------------------------------------------------------
/src/hooks/useRenameDomain.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useRenameDomain
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { RenameDomainRequest } from 'client/wildduck-api';
11 |
12 | /**
13 | * useRenameDomain
14 | */
15 | const useRenameDomain = () => {
16 | const queryClient = useQueryClient();
17 |
18 | return useMutation((newDomain: RenameDomainRequest) => api.addressApi.renameDomain(newDomain), {
19 | onError: () => {
20 | AppEvents.publish(Events.Error, 'Error');
21 | },
22 | onSuccess: () => {
23 | AppEvents.publish(Events.Success, 'Success');
24 | queryClient.invalidateQueries('useForwardedAddress');
25 | },
26 | });
27 | };
28 |
29 | export default useRenameDomain;
30 |
--------------------------------------------------------------------------------
/src/hooks/useResetPassword.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useResetPassword
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 |
11 | /**
12 | * useResetPassword
13 | */
14 | const useResetPassword = () => {
15 | return useMutation((userId: string) => api.usersApi.resetUserPassword(userId), {
16 | onError: () => {
17 | AppEvents.publish(Events.Error, 'Error');
18 | },
19 | onSuccess: () => {
20 | AppEvents.publish(Events.Success, 'Success');
21 | },
22 | });
23 | };
24 |
25 | export default useResetPassword;
26 |
--------------------------------------------------------------------------------
/src/hooks/useRestoreArchiveMessage.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useRestoreArchiveMessage
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { RestoreMessageRequest } from 'client/wildduck-api';
11 |
12 | export interface IRestoreArchiveMessage {
13 | userId: string;
14 | message: number | string;
15 | params?: RestoreMessageRequest;
16 | }
17 |
18 | /**
19 | * useRestoreArchiveMessage
20 | */
21 | const useRestoreArchiveMessage = () => {
22 | const queryClient = useQueryClient();
23 |
24 | return useMutation(
25 | ({ userId, message, params }: IRestoreArchiveMessage) =>
26 | api.archiveApi.restoreMessage(userId, message as number, params),
27 | {
28 | onError: () => {
29 | AppEvents.publish(Events.Error, 'Error');
30 | },
31 | onSuccess: () => {
32 | AppEvents.publish(Events.Success, 'Success');
33 | queryClient.invalidateQueries('useArchive');
34 | queryClient.invalidateQueries('useMailboxes');
35 | },
36 | },
37 | );
38 | };
39 |
40 | export default useRestoreArchiveMessage;
41 |
--------------------------------------------------------------------------------
/src/hooks/useRestoreArchiveMessages.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useRestoreArchiveMessages
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { RestoreMessagesRequest } from 'client/wildduck-api';
11 |
12 | interface IParams {
13 | userId: string;
14 | params: RestoreMessagesRequest;
15 | }
16 |
17 | /**
18 | * useRestoreArchiveMessages
19 | */
20 | const useRestoreArchiveMessages = () => {
21 | const queryClient = useQueryClient();
22 |
23 | return useMutation(async ({ userId, params }: IParams) => await api.archiveApi.restoreMessages(userId, params), {
24 | onError: () => {
25 | AppEvents.publish(Events.Error, 'Error');
26 | },
27 | onSuccess: ({ data }) => {
28 | AppEvents.publish(Events.Success, data.success ? 'Success' : 'Changes will reflect after 15 sec');
29 | queryClient.invalidateQueries('useArchive');
30 | },
31 | });
32 | };
33 |
34 | export default useRestoreArchiveMessages;
35 |
--------------------------------------------------------------------------------
/src/hooks/useUpdateAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUpdateAddress
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { UpdateUserAddressRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | interface IParams {
14 | userId: string;
15 | addressId: string;
16 | updateAddressInfo: UpdateUserAddressRequest;
17 | }
18 | /**
19 | * useUpdateAddress
20 | */
21 | const useUpdateAddress = () => {
22 | const queryClient = useQueryClient();
23 |
24 | return useMutation(
25 | (params: IParams) =>
26 | api.addressApi.updateUserAddress(params.userId, params.addressId, params.updateAddressInfo),
27 | {
28 | onError: () => {
29 | AppEvents.publish(Events.Error, 'Error');
30 | },
31 | onSuccess: ({ data }) => {
32 | handleError(data);
33 | queryClient.invalidateQueries('useAddressInformation');
34 | },
35 | },
36 | );
37 | };
38 |
39 | export default useUpdateAddress;
40 |
--------------------------------------------------------------------------------
/src/hooks/useUpdateAutoreply.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUpdateAutoreply
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { UpdateAutoreplyRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | interface IParams {
14 | userId: string;
15 | updateAutoreply: UpdateAutoreplyRequest;
16 | }
17 | /**
18 | * useUpdateAutoreply
19 | */
20 | const useUpdateAutoreply = () => {
21 | const queryClient = useQueryClient();
22 |
23 | return useMutation((params: IParams) => api.autorepliesApi.updateAutoreply(params.userId, params.updateAutoreply), {
24 | onError: () => {
25 | AppEvents.publish(Events.Error, 'Error');
26 | },
27 | onSuccess: ({ data }) => {
28 | handleError(data);
29 | queryClient.invalidateQueries('useAutoreplyDetails');
30 | },
31 | });
32 | };
33 |
34 | export default useUpdateAutoreply;
35 |
--------------------------------------------------------------------------------
/src/hooks/useUpdateFilter.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUpdateFilter
4 | */
5 |
6 | import { useMutation } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { CreateFilterRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | /**
14 | * useUpdateFilter
15 | */
16 | const useUpdateFilter = () => {
17 | return useMutation(
18 | ({
19 | userId,
20 | filterId,
21 | filterDetails,
22 | }: {
23 | userId: string;
24 | filterId: string;
25 | filterDetails: CreateFilterRequest;
26 | }) => api.filtersApi.updateFilter(userId, filterId, filterDetails),
27 | {
28 | onError: () => {
29 | AppEvents.publish(Events.Error, 'Error');
30 | },
31 | onSuccess: ({ data }) => {
32 | handleError(data);
33 | },
34 | },
35 | );
36 | };
37 |
38 | export default useUpdateFilter;
39 |
--------------------------------------------------------------------------------
/src/hooks/useUpdateForwardedAddress.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUpdateForwardedAddress
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { UpdateForwardedAddressRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | interface IParams {
14 | addressId: string;
15 | updateForwardedAddressInformation: UpdateForwardedAddressRequest;
16 | }
17 | /**
18 | * useUpdateForwardedAddress
19 | */
20 | const useUpdateForwardedAddress = () => {
21 | const queryClient = useQueryClient();
22 |
23 | return useMutation(
24 | (params: IParams) =>
25 | api.addressApi.updateForwardedAddress(params.addressId, params.updateForwardedAddressInformation),
26 | {
27 | onError: () => {
28 | AppEvents.publish(Events.Error, 'Error');
29 | },
30 | onSuccess: ({ data }) => {
31 | handleError(data);
32 | queryClient.invalidateQueries('useForwardedAddressInformation');
33 | },
34 | },
35 | );
36 | };
37 |
38 | export default useUpdateForwardedAddress;
39 |
--------------------------------------------------------------------------------
/src/hooks/useUpdateMailbox.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUpdateMailbox
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { UpdateMailboxRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | interface IParams {
14 | userId: string;
15 | mailboxId: string;
16 | params: UpdateMailboxRequest;
17 | }
18 | /**
19 | * useUpdateMailbox
20 | */
21 | const useUpdateMailbox = () => {
22 | const queryClient = useQueryClient();
23 |
24 | return useMutation(
25 | ({ userId, mailboxId, params }: IParams) => api.mailboxesApi.updateMailbox(userId, mailboxId, params),
26 | {
27 | onError: () => {
28 | AppEvents.publish(Events.Error, 'Error');
29 | },
30 | onSuccess: ({ data }) => {
31 | handleError(data);
32 | queryClient.invalidateQueries('useMailboxes');
33 | },
34 | },
35 | );
36 | };
37 |
38 | export default useUpdateMailbox;
39 |
--------------------------------------------------------------------------------
/src/hooks/useUpdateUserDetails.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUpdateUserDetails
4 | */
5 |
6 | import { useMutation, useQueryClient } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
10 | import { UpdateUserRequest } from 'client/wildduck-api';
11 | import handleError from 'app-ui/utils/handleError';
12 |
13 | interface IParams {
14 | userDetails: UpdateUserRequest;
15 | userId: string;
16 | }
17 |
18 | /**
19 | * useUpdateUserDetails
20 | */
21 | const useUpdateUserDetails = () => {
22 | const queryClient = useQueryClient();
23 |
24 | return useMutation((params: IParams) => api.usersApi.updateUser(params.userId, params.userDetails), {
25 | onError: () => {
26 | AppEvents.publish(Events.Error, 'Error');
27 | },
28 | onSuccess: ({ data }) => {
29 | handleError(data);
30 | queryClient.invalidateQueries('useUserDetails');
31 | },
32 | });
33 | };
34 |
35 | export default useUpdateUserDetails;
36 |
--------------------------------------------------------------------------------
/src/hooks/useUserDetails.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUserDetails
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 |
8 | import api from 'client/RequestClient';
9 |
10 | /**
11 | * useUserDetails
12 | */
13 | const useUserDetails = (userId: string) => {
14 | return useQuery(['useUserDetails', userId], async () => {
15 | const { data } = await api.usersApi.getUser(userId);
16 | return data;
17 | });
18 | };
19 |
20 | export default useUserDetails;
21 |
--------------------------------------------------------------------------------
/src/hooks/useUsers.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description React hook useUsers
4 | */
5 |
6 | import { useQuery } from 'react-query';
7 | import _ from 'lodash';
8 |
9 | import { addKey } from 'app-ui/utils/logicUtils';
10 | import api from 'client/RequestClient';
11 |
12 | /**
13 | * useUsers
14 | */
15 | const useUsers = (params?: IUsers.IFilterUsers) => {
16 | return useQuery(
17 | ['useUsers', params?.query, params?.tags, params?.requiredTags, params?.page, params?.limit],
18 | async () => {
19 | const { data } = await api.usersApi.getUsers(
20 | params?.query,
21 | '',
22 | params?.tags,
23 | params?.requiredTags,
24 | params?.metaData,
25 | params?.internalData,
26 | params?.limit,
27 | params?.page,
28 | _.toString(params?.next),
29 | _.toString(params?.previous),
30 | );
31 | return {
32 | data: addKey(_.sortBy(_.get(data, 'results', []), (user: any) => user.username)),
33 | previousCursor: _.get(data, 'previousCursor', ''),
34 | nextCursor: _.get(data, 'nextCursor', ''),
35 | };
36 | },
37 | );
38 | };
39 |
40 | export default useUsers;
41 |
--------------------------------------------------------------------------------
/src/logic/addressLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description address logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const addressLogic = kea({
11 | path: () => ['address'],
12 | defaults: {
13 | updatableField: false,
14 |
15 | query: '',
16 |
17 | addressId: '',
18 |
19 | addressInformationToggle: false,
20 | creatNewAddressToggle: false,
21 | renameDomainToggle: true,
22 | },
23 | actions: {
24 | setQuery: (query: string) => ({ query }),
25 |
26 | setAddressId: (addressId: string) => ({ addressId }),
27 |
28 | setAddressInformationToggle: (addressInformationToggle: boolean) => ({ addressInformationToggle }),
29 | setCreatNewAddressToggle: (creatNewAddressToggle: boolean) => ({ creatNewAddressToggle }),
30 | setRenameDomainToggle: (renameDomainToggle: boolean) => ({ renameDomainToggle }),
31 | },
32 | reducers: {
33 | query: {
34 | setQuery: get('query'),
35 | },
36 |
37 | addressId: {
38 | setAddressId: get('addressId'),
39 | },
40 |
41 | renameDomainToggle: {
42 | setRenameDomainToggle: get('renameDomainToggle'),
43 | },
44 | addressInformationToggle: {
45 | setAddressInformationToggle: get('addressInformationToggle'),
46 | },
47 | creatNewAddressToggle: {
48 | setCreatNewAddressToggle: get('creatNewAddressToggle'),
49 | },
50 | },
51 | });
52 |
53 | export default addressLogic;
54 |
--------------------------------------------------------------------------------
/src/logic/appLogic.ts:
--------------------------------------------------------------------------------
1 | import { kea } from 'kea';
2 | import _ from 'lodash';
3 | import { get } from 'app-ui/utils/logicUtils';
4 | import menuConfig from 'app-ui/config/menuConfig';
5 |
6 | const appLogic = kea({
7 | path: () => ['app'],
8 | defaults: {
9 | loading: true,
10 | error: false,
11 | menuConfig: [],
12 | basePath: '',
13 | accessToken: '',
14 | showFloatingButton: false,
15 | },
16 | actions: {
17 | syncAppData: (basePath: string) => ({ basePath }),
18 | setError: true,
19 | setAccessToken: (token: string) => ({ token }),
20 | setShowFloatingButton: (status: boolean) => ({ status }),
21 | },
22 | reducers: {
23 | basePath: {
24 | syncAppData: get('basePath'),
25 | },
26 | loading: {
27 | syncAppData: _.stubFalse,
28 | },
29 | error: {
30 | syncAppData: _.stubFalse,
31 | setError: _.stubTrue,
32 | },
33 | menuConfig: {
34 | syncAppData: () => menuConfig,
35 | },
36 | accessToken: {
37 | setAccessToken: get('token'),
38 | },
39 | showFloatingButton: {
40 | setShowFloatingButton: get('status'),
41 | },
42 | },
43 | });
44 |
45 | export default appLogic;
46 |
--------------------------------------------------------------------------------
/src/logic/archiveLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description archive logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const archiveLogic = kea({
11 | path: () => ['archive'],
12 | defaults: {
13 | page: 1,
14 | limit: 20,
15 | next: '',
16 | previous: '',
17 |
18 | dateData: [],
19 | isModalVisible: false,
20 | },
21 | actions: {
22 | setNext: (next: string) => ({ next }),
23 | setPrevious: (previous: string) => ({ previous }),
24 | setLimit: (limit: number) => ({ limit }),
25 | setPage: (page: number) => ({ page }),
26 |
27 | setDateData: (dateData: Array) => ({ dateData }),
28 | setIsModalVisible: (isModalVisible: boolean) => ({ isModalVisible }),
29 | },
30 | reducers: {
31 | page: {
32 | setPage: get('page'),
33 | },
34 | next: {
35 | setNext: get('next'),
36 | },
37 | previous: {
38 | setPrevious: get('previous'),
39 | },
40 | limit: {
41 | setLimit: get('limit'),
42 | },
43 |
44 | dateData: {
45 | setDateData: get>('dateData'),
46 | },
47 | isModalVisible: {
48 | setIsModalVisible: get('isModalVisible'),
49 | },
50 | },
51 | });
52 |
53 | export default archiveLogic;
54 |
--------------------------------------------------------------------------------
/src/logic/authenticationLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Authentication logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const authenticationLogic = kea({
11 | path: () => ['authentication'],
12 |
13 | defaults: {
14 | limit: 20,
15 | next: '',
16 | previous: '',
17 | page: 1,
18 | },
19 |
20 | actions: {
21 | setNext: (next: string) => ({ next }),
22 | setPrevious: (previous: string) => ({ previous }),
23 | setLimit: (limit: number) => ({ limit }),
24 | setPage: (page: number) => ({ page }),
25 | },
26 |
27 | reducers: {
28 | next: {
29 | setNext: get('next'),
30 | },
31 | previous: {
32 | setPrevious: get('previous'),
33 | },
34 | limit: {
35 | setLimit: get('limit'),
36 | },
37 | page: {
38 | setPage: get('page'),
39 | },
40 | },
41 | });
42 |
43 | export default authenticationLogic;
44 |
--------------------------------------------------------------------------------
/src/logic/dkimLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Dkim logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const dkimLogic = kea({
11 | path: () => ['dkim'],
12 | defaults: {
13 | next: '',
14 | previous: '',
15 | limit: 20,
16 | page: 1,
17 |
18 | query: '',
19 | },
20 | actions: {
21 | setLimit: (limit: number) => ({ limit }),
22 | setNext: (next: string) => ({ next }),
23 | setPrevious: (previous: string) => ({ previous }),
24 | setPage: (page: number) => ({ page }),
25 |
26 | setQuery: (query: string) => ({ query }),
27 | },
28 | reducers: {
29 | next: {
30 | setNext: get('next'),
31 | },
32 | previous: {
33 | setPrevious: get('previous'),
34 | },
35 | limit: {
36 | setLimit: get('limit'),
37 | },
38 | page: {
39 | setPage: get('page'),
40 | },
41 |
42 | query: {
43 | setQuery: get('query'),
44 | },
45 | },
46 | });
47 |
48 | export default dkimLogic;
49 |
--------------------------------------------------------------------------------
/src/logic/domainAccessLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Domain access logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 | import { GetAllowedDomainResult } from 'client/wildduck-api';
10 |
11 | const domainAccessLogic = kea({
12 | path: () => ['domain-access'],
13 | defaults: {
14 | allowedList: [],
15 | blockedList: [],
16 | dataSource: [],
17 | tag: '',
18 | addDomainModalVisiblity: false,
19 | },
20 | actions: {
21 | setAllowedList: (list: Array) => ({ list }),
22 | setBlockedList: (list: Array) => ({ list }),
23 | getAllowedList: (tags: string) => ({ tags }),
24 | getBlockedList: (tags: string) => ({ tags }),
25 | setDataSource: (list: GetAllowedDomainResult) => ({
26 | list,
27 | }),
28 | setTag: (tag: string) => ({ tag }),
29 | setAddDomainModalVisiblity: (status: boolean) => ({ status }),
30 | },
31 | reducers: {
32 | allowedList: {
33 | setAllowedList: get>('list'),
34 | },
35 | blockedList: {
36 | setBlockedList: get>('list'),
37 | },
38 | dataSource: {
39 | setDataSource: get>('list'),
40 | },
41 | tag: {
42 | setTag: get('tag'),
43 | },
44 | addDomainModalVisiblity: {
45 | setAddDomainModalVisiblity: get('status'),
46 | },
47 | },
48 | });
49 |
50 | export default domainAccessLogic;
51 |
--------------------------------------------------------------------------------
/src/logic/domainAliasesLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description domain aliases logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const domainAliasesLogic = kea({
11 | path: () => ['domainAliases'],
12 | defaults: {
13 | query: '',
14 |
15 | limit: 20,
16 | next: '',
17 | previous: '',
18 | page: 1,
19 | },
20 |
21 | actions: {
22 | setQuery: (query: string) => ({ query }),
23 |
24 | setNext: (next: string) => ({ next }),
25 | setPrevious: (previous: string) => ({ previous }),
26 | setLimit: (limit: number) => ({ limit }),
27 | setPage: (page: number) => ({ page }),
28 | },
29 |
30 | reducers: {
31 | query: {
32 | setQuery: get('query'),
33 | },
34 |
35 | page: {
36 | setPage: get('page'),
37 | },
38 | dir: {
39 | setDir: get('dir'),
40 | },
41 | next: {
42 | setNext: get('next'),
43 | },
44 | previous: {
45 | setPrevious: get('previous'),
46 | },
47 | limit: {
48 | setLimit: get('limit'),
49 | },
50 | },
51 | });
52 |
53 | export default domainAliasesLogic;
54 |
--------------------------------------------------------------------------------
/src/logic/filtersLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description filters logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const filtersLogic = kea({
11 | path: () => ['filters'],
12 | defaults: {
13 | showAddFilterForm: false,
14 | filterId: '',
15 | },
16 | actions: {
17 | setShowAddFilterForm: (buttonStatus: boolean) => ({ buttonStatus }),
18 | setFilterId: (filterId: string) => ({ filterId }),
19 | },
20 | reducers: {
21 | showAddFilterForm: {
22 | setShowAddFilterForm: get('buttonStatus'),
23 | },
24 | filterId: {
25 | setFilterId: get('filterId'),
26 | },
27 | },
28 | });
29 |
30 | export default filtersLogic;
31 |
--------------------------------------------------------------------------------
/src/logic/mailboxesLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description domain aliases logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 | import { UpdateMailboxRequest } from 'client/wildduck-api';
10 |
11 | const mailboxesLogic = kea({
12 | path: () => ['mailboxes'],
13 | defaults: {
14 | mailboxId: '',
15 |
16 | selectedMailboxData: {},
17 |
18 | updateMailboxToggle: false,
19 | showMailboxMessagesTable: false,
20 |
21 | specialUse: false,
22 |
23 | mailboxName: '',
24 | },
25 | actions: {
26 | setMailboxId: (mailboxId: boolean) => ({ mailboxId }),
27 |
28 | setSelectedMailboxData: (selectedMailboxData: UpdateMailboxRequest) => ({ selectedMailboxData }),
29 |
30 | setUpdateMailboxToggle: (updateMailboxToggle: boolean) => ({ updateMailboxToggle }),
31 | setShowMailboxMessagesTable: (showMailboxMessagesTable: boolean) => ({ showMailboxMessagesTable }),
32 |
33 | setSpecialUse: (specialUse: boolean) => ({ specialUse }),
34 |
35 | setMailboxName: (mailboxName: string) => ({ mailboxName }),
36 | },
37 | reducers: {
38 | specialUse: {
39 | setSpecialUse: get('specialUse'),
40 | },
41 |
42 | mailboxName: {
43 | setMailboxName: get('mailboxName'),
44 | },
45 |
46 | updateMailboxToggle: {
47 | setUpdateMailboxToggle: get('updateMailboxToggle'),
48 | },
49 | showMailboxMessagesTable: {
50 | setShowMailboxMessagesTable: get('showMailboxMessagesTable'),
51 | },
52 |
53 | mailboxId: {
54 | setMailboxId: get('mailboxId'),
55 | },
56 |
57 | selectedMailboxData: {
58 | setSelectedMailboxData: get('selectedMailboxData'),
59 | },
60 | },
61 | });
62 |
63 | export default mailboxesLogic;
64 |
--------------------------------------------------------------------------------
/src/logic/messagesLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description messages logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const messagesLogic = kea({
11 | path: () => ['messages'],
12 | defaults: {
13 | limit: 20,
14 | next: '',
15 | previous: '',
16 | page: 1,
17 |
18 | messageId: '',
19 | attachmentId: '',
20 |
21 | unseen: false,
22 |
23 | showUploadMessageForm: false,
24 | messageDetailsToggle: false,
25 | messageSourceToggle: false,
26 | },
27 | actions: {
28 | setPage: (page: number) => ({ page }),
29 | setNext: (next: string) => ({ next }),
30 | setPrevious: (previous: string) => ({ previous }),
31 | setLimit: (limit: number) => ({ limit }),
32 |
33 | setUnseen: (unseen: boolean) => ({ unseen }),
34 |
35 | setMessageId: (messageId: string | number) => ({ messageId }),
36 | setAttachmentId: (attachmentId: string | number) => ({ attachmentId }),
37 |
38 | setMessageDetailsToggle: (messageDetailsToggle: boolean) => ({ messageDetailsToggle }),
39 | setMessageSourceToggle: (messageSourceToggle: boolean) => ({ messageSourceToggle }),
40 | },
41 | reducers: {
42 | messageId: {
43 | setMessageId: get('messageId'),
44 | },
45 | attachmentId: {
46 | setAttachmentId: get('attachmentId'),
47 | },
48 |
49 | messageSourceToggle: {
50 | setMessageSourceToggle: get('messageSourceToggle'),
51 | },
52 | messageDetailsToggle: {
53 | setMessageDetailsToggle: get('messageDetailsToggle'),
54 | },
55 |
56 | next: {
57 | setNext: get('next'),
58 | },
59 | previous: {
60 | setPrevious: get('previous'),
61 | },
62 | limit: {
63 | setLimit: get('limit'),
64 | },
65 | page: {
66 | setPage: get('page'),
67 | },
68 |
69 | unseen: {
70 | setUnseen: get('unseen'),
71 | },
72 | },
73 | });
74 |
75 | export default messagesLogic;
76 |
--------------------------------------------------------------------------------
/src/logic/navigationLogic.ts:
--------------------------------------------------------------------------------
1 | import { get } from 'app-ui/utils/logicUtils';
2 | import { kea } from 'kea';
3 | import _ from 'lodash';
4 |
5 | import AppLogic from './appLogic';
6 |
7 | const logic = kea({
8 | connect: {
9 | values: [AppLogic, ['menuConfig', 'basePath']],
10 | },
11 |
12 | path: () => ['navigations'],
13 |
14 | defaults: {
15 | collapsed: false,
16 | selectedKeys: [],
17 | openKeys: [],
18 | },
19 |
20 | actions: () => ({
21 | setCollapsed: (collapsed: boolean) => ({ collapsed }),
22 | setOpenKeys: (openKeys: string[]) => ({ openKeys }),
23 | setSelectedKeys: (selectedKeys: string[]) => ({ selectedKeys }),
24 | redirect: (nextURL: string) => ({ nextURL }),
25 | setNavigationKeys: (selectedKeys: string[], openKeys: string[]) => ({ selectedKeys, openKeys }),
26 | }),
27 |
28 | listeners: ({ actions, values }) => ({
29 | redirect: ({ nextURL }: { nextURL: string }) => {
30 | let url = `/${nextURL}`;
31 | const { menuConfig } = values;
32 | const basePath = _.get(window, 'basePath', '');
33 | if (basePath.length > 1 && new RegExp(`^${basePath}.*`).test(url)) {
34 | url = url.slice(basePath.length - 1);
35 | }
36 | const match = _.find(menuConfig, (config: string) => _.get(config, 'url') === url);
37 | actions.setNavigationKeys([_.get(match, 'key', '')], _.get(match, 'hierarchy', []));
38 | },
39 | }),
40 |
41 | reducers: () => ({
42 | collapsed: {
43 | setCollapsed: get('collapsed'),
44 | },
45 | openKeys: {
46 | setOpenKeys: get('openKeys'),
47 | setNavigationKeys: get('openKeys'),
48 | },
49 | selectedKeys: {
50 | setSelectedKeys: get('selectedKeys'),
51 | setNavigationKeys: get('selectedKeys'),
52 | },
53 | }),
54 | });
55 |
56 | export default logic;
57 |
--------------------------------------------------------------------------------
/src/logic/usersLogic.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Aditya Negi
3 | * @description Users logic
4 | */
5 |
6 | import { kea } from 'kea';
7 |
8 | import { get } from 'app-ui/utils/logicUtils';
9 |
10 | const usersLogic = kea({
11 | path: () => ['users'],
12 | defaults: {
13 | next: '',
14 | previous: '',
15 | limit: 20,
16 | page: 1,
17 |
18 | searchParams: {},
19 |
20 | userDetails: {},
21 | password: '',
22 | showResetPasswordModal: false,
23 | },
24 | actions: {
25 | setPassword: (password: string) => ({ password }),
26 | setShowResetPasswordModal: (status: boolean) => ({ status }),
27 |
28 | setSearchParams: (searchParams: string) => ({ searchParams }),
29 |
30 | setNext: (next: string) => ({ next }),
31 | setPrevious: (previous: string) => ({ previous }),
32 | setLimit: (limit: number) => ({ limit }),
33 | setPage: (page: number) => ({ page }),
34 | },
35 | reducers: {
36 | searchParams: {
37 | setSearchParams: get('searchParams'),
38 | },
39 |
40 | next: {
41 | setNext: get('next'),
42 | },
43 | previous: {
44 | setPrevious: get('previous'),
45 | },
46 | limit: {
47 | setLimit: get('limit'),
48 | },
49 | page: {
50 | setPage: get('page'),
51 | },
52 |
53 | password: {
54 | setPassword: get('password'),
55 | },
56 | showResetPasswordModal: {
57 | setShowResetPasswordModal: get('status'),
58 | },
59 | },
60 | });
61 |
62 | export default usersLogic;
63 |
--------------------------------------------------------------------------------
/src/react-query.config.ts:
--------------------------------------------------------------------------------
1 | const config = {
2 | defaultOptions: {
3 | queries: {
4 | retry: false,
5 | retryDelay: 5000,
6 | refetchOnWindowFocus: false,
7 | },
8 | },
9 | };
10 |
11 | export default config;
12 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import { resetContext, getContext } from 'kea';
2 |
3 | resetContext({
4 | createStore: {},
5 | plugins: [],
6 | });
7 |
8 | export default getContext().store;
9 |
--------------------------------------------------------------------------------
/src/types/axios.d.ts:
--------------------------------------------------------------------------------
1 | declare interface IAxiosInterceptors {
2 | request: any;
3 | response: any;
4 | reject: any;
5 | }
6 |
7 | declare type IAxiosInstance = import('axios').AxiosInstance;
8 | declare type IAxiosError = import('axios').AxiosError;
9 | declare type IAxiosRequestConfig = import('axios').AxiosRequestConfig;
10 | declare type IAxiosResponse = import('axios').AxiosResponse;
11 |
--------------------------------------------------------------------------------
/src/types/dkim.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace IDkim {
2 | interface IFilterGetDkimKeysList {
3 | query: string;
4 | limit: number;
5 | }
6 |
7 | interface ICreateDkim {
8 | domain: string;
9 | selector: string;
10 | description?: string;
11 | privateKey?: string;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/types/domainAliases.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace DomainAliases {
2 | interface IRequstListParams {
3 | query: string;
4 | limit: number;
5 | page: number;
6 | next: number;
7 | previous: number;
8 | }
9 |
10 | type IDomainAliasesList = IDomainAliases[];
11 |
12 | interface IResolveId {
13 | success: boolean;
14 | id: string;
15 | }
16 |
17 | interface IDomainAliasInfo {
18 | success: boolean;
19 | id: string;
20 | alias: string;
21 | domain: string;
22 | created: string;
23 | }
24 |
25 | interface ICreateNewDomainAlias {
26 | domain: string;
27 | alias: string;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/types/navigationBar.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace Navigation {
2 | type Icon = {
3 | type: string;
4 | theme?: 'filled' | 'outlined' | 'twoTone';
5 | };
6 |
7 | interface IMenuItem {
8 | key: string;
9 | icon: Icon | React.FC;
10 | title: string;
11 | path: string;
12 | url: string;
13 | hideMenu: boolean;
14 | }
15 |
16 | type ISubMenuItem = {
17 | key: string;
18 | icon: Icon | React.FC;
19 | title: string;
20 | children: (ISubMenuItem | IMenuItem)[];
21 | };
22 |
23 | type IMenuItems = (ISubMenuItem | IMenuItem)[];
24 |
25 | interface IStoreStates {
26 | route?: string;
27 | nextRoute?: string;
28 | collapsed: boolean;
29 | openKeys: string[];
30 | selectedKeys: string[];
31 | accessableFeatures: any[];
32 | basePath: string;
33 | menuConfig: any;
34 | }
35 |
36 | interface IActions {
37 | setSelectedKeys: (keys: string[]) => void;
38 | setOpenKeys: (openKeys: string[]) => void;
39 | setCollapsed: (collapsed: boolean) => void;
40 | redirect: (nextUrl: string) => void;
41 | }
42 |
43 | interface Props extends IStoreStates {
44 | actions: IActions;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/types/storage.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace Storage {
2 | interface IStorage {
3 | id: string;
4 | filename: string;
5 | size: number;
6 | }
7 | type IStorageList = IStorage[];
8 | }
9 |
--------------------------------------------------------------------------------
/src/types/users.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace IUsers {
2 | interface IFilterUsers {
3 | query?: string;
4 | tags?: string;
5 | requiredTags?: string;
6 | limit?: number;
7 | metaData?: boolean;
8 | internalData?: boolean;
9 | page?: number;
10 | next?: number;
11 | previous?: number;
12 | }
13 |
14 | interface ICreateUser {
15 | username: string;
16 | name?: string;
17 | password: string;
18 | address?: string;
19 | pubKey?: string;
20 | metaData?: string;
21 | internalData?: string;
22 | language?: string;
23 | sess?: string;
24 | ip?: string;
25 | address?: string;
26 | address?: string;
27 | address?: string;
28 | address?: string;
29 | tags?: string[];
30 | disabledScopes: string[];
31 | targets?: string[];
32 | fromWhitelist?: string[];
33 | autoreply?: boolean;
34 | encryptMessages?: boolean;
35 | encryptForwarded?: boolean;
36 | quota?: number;
37 | recipients?: number;
38 | forwards?: number;
39 | imapMaxUpload?: number;
40 | pop3MaxDownload?: number;
41 | pop3MaxMessages?: number;
42 | imapMaxConnections?: number;
43 | receivedMax?: number;
44 | imapMaxDownload?: number;
45 | imapMaxDownload?: number;
46 | imapMaxDownload?: number;
47 | hasPasswordSet?: boolean;
48 | activated?: boolean;
49 | disabled?: boolean;
50 | suspended?: boolean;
51 | hashedPassword?: boolean;
52 | allowUnsafe?: boolean;
53 | requirePasswordChange?: boolean;
54 | addTagsToAddress?: boolean;
55 | uploadSentMessages?: boolean;
56 | addTagsToAddress?: boolean;
57 | addTagsToAddress?: boolean;
58 | }
59 |
60 | interface IResults {
61 | id: string;
62 | username: string;
63 | name: string;
64 | address: string;
65 | tags: Array;
66 | forward: Array;
67 | enabled2a: string[];
68 | autoreply: boolean;
69 | encryptMessages: boolean;
70 | encryptForwarded: boolean;
71 | quota: {
72 | allowed: number;
73 | used: number;
74 | };
75 | hasPasswordSet: boolean;
76 | activated: boolean;
77 | disabled: boolean;
78 | suspended: boolean;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/utils/AppEvents.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Event Bus using pub/sub design pattern
3 | * @author Harish.R
4 | */
5 |
6 | import _ from 'lodash';
7 | import log from 'loglevel';
8 |
9 | /**
10 | * Events
11 | */
12 | enum Events {
13 | Loading = 'M_LOADING',
14 | Warn = 'M_WARN',
15 | Info = 'M_INFO',
16 | Success = 'M_SUCCESS',
17 | Error = 'M_ERROR',
18 | N_Loading = 'N_LOADING',
19 | N_Warn = 'N_WARN',
20 | N_Info = 'N_INFO',
21 | N_Success = 'N_SUCCESS',
22 | N_Error = 'N_ERROR',
23 | MO_Success = 'MO_Success',
24 | MO_Error = 'MO_Error',
25 | MO_Info = 'MO_Info',
26 | MO_Warn = 'MO_Warn',
27 | }
28 |
29 | /**
30 | * App Events
31 | * @class
32 | */
33 | class AppEvents {
34 | /**
35 | * All Subscriptions
36 | * @member subscribers
37 | */
38 | subscribers: Record;
39 | constructor() {
40 | this.subscribers = {};
41 | }
42 |
43 | /**
44 | * publish an event
45 | * @method publish
46 | * @param {string} event
47 | * @param rest
48 | */
49 | publish = (event: string, ...rest: any) => {
50 | if (_.has(this.subscribers, event)) {
51 | _.forOwn(_.get(this.subscribers, event), (callback: any) => {
52 | try {
53 | callback(...rest);
54 | } catch (ex) {
55 | log.error(`[Eventbus] ${ex}`);
56 | }
57 | });
58 | }
59 | };
60 |
61 | /**
62 | * Subscribes an event
63 | * @method subscribe
64 | * @param {event} event
65 | * @param {function} callback
66 | */
67 | subscribe = (event: string, callback: any) => {
68 | if (!_.has(this.subscribers, event)) {
69 | _.setWith(this.subscribers, event, [], Object);
70 | }
71 | if (_.isFunction(callback)) {
72 | _.get(this.subscribers, event).push(callback);
73 | } else {
74 | log.error(`[Eventbus] ${callback} is not a function`);
75 | }
76 | };
77 | }
78 |
79 | export default new AppEvents();
80 |
81 | export { Events };
82 |
--------------------------------------------------------------------------------
/src/utils/FilterDropdownStyle.css:
--------------------------------------------------------------------------------
1 | .filterWrapper .ant-list, .selectCheckBox {
2 | padding: 8px;
3 | }
4 |
5 | .filterFooter {
6 | width: 100%;
7 | display: inline-flex;
8 | flex-direction: row;
9 | justify-content: space-between;
10 | padding: 7px 8px;
11 | overflow: hidden;
12 | border-top: 1px solid #e8e8e8;
13 | }
14 |
15 | .filterWrapper .ant-list-item {
16 | display: flex;
17 | align-items: center;
18 | padding: 5px 0;
19 | border-bottom: 0 !important;
20 | }
21 |
22 | .filterListWrapper {
23 | max-height: 190px;
24 | overflow-y: scroll;
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils/Pagination.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag Kushwaha
3 | * @description Pagination Component
4 | */
5 |
6 | import React from 'react';
7 | import { Button, Tooltip, Select, Space } from 'antd';
8 | import _ from 'lodash';
9 |
10 | import { RightOutlined, LeftOutlined } from '@ant-design/icons';
11 |
12 | interface IPagination {
13 | next: string;
14 | previous: string;
15 | limit: number;
16 | page: number;
17 | setLimit(value: number): void;
18 | setPrevious(value: string): void;
19 | setNext(value: string): void;
20 | setPage(value: number): void;
21 | }
22 |
23 | export const Pagination: React.FC = ({
24 | limit,
25 | previous,
26 | next,
27 | page,
28 | setLimit,
29 | setPrevious,
30 | setNext,
31 | setPage,
32 | }: IPagination) => {
33 | return (
34 |
35 |
36 |
46 |
47 |
60 |
61 |
71 |
72 |
73 | );
74 | };
75 |
--------------------------------------------------------------------------------
/src/utils/constants.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | * @description constants
4 | */
5 |
6 | /**
7 | * DATE_TIME_FORMAT
8 | * @type {string}
9 | * @exports
10 | */
11 | const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
12 |
13 | /**
14 | * DATE_TIME_FORMAT_AP
15 | * @type {string}
16 | * @exports
17 | */
18 | const DATE_TIME_FORMAT_AP = 'YYYY-MM-DD hh:mm:ss A';
19 |
20 | export { DATE_TIME_FORMAT, DATE_TIME_FORMAT_AP };
21 |
--------------------------------------------------------------------------------
/src/utils/getUniqValuesBy.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Lakkanna Walikar
3 | */
4 |
5 | import _ from 'lodash';
6 |
7 | /**
8 | * index signature for object
9 | */
10 | interface IIndexSignature {
11 | [key: string]: any;
12 | }
13 |
14 | /**
15 | * Function to get uniq values based on object key
16 | *
17 | * @param {RevenueForecastDetails} data - A revenue forecast detail
18 | * @param {string} filterFor - This is key in a object
19 | * @returns {string[]} Uniq values for given filterFor key from the array of object
20 | */
21 | const getUniqValuesBy = (dataArray: IIndexSignature[], filterFor: string): string[] => {
22 | if (filterFor) {
23 | return _.chain(dataArray)
24 | .map((data) => _.toString( _.get(data, filterFor)))
25 | .filter((value) => value !== undefined)
26 | .uniq()
27 | .sort()
28 | .value();
29 | }
30 | return [];
31 | };
32 |
33 | export default getUniqValuesBy;
34 |
--------------------------------------------------------------------------------
/src/utils/handleError.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Chirag
3 | * @description Handle error from the server
4 | */
5 |
6 | import _ from 'lodash';
7 |
8 | import AppEvents, { Events } from 'app-ui/utils/AppEvents';
9 |
10 | const handleError = (data: any) => {
11 | let error = _.get(data, 'error', '');
12 | if (_.isEqual(error, 'Mailbox update failed with code CANNOT')) {
13 | error = 'Special Mailbox path cannot be changed';
14 | } else if (_.isEqual(error, 'Mailbox update failed with code ALREADYEXISTS')) {
15 | error = 'Mailbox with this name already exists';
16 | }
17 |
18 | _.isEmpty(error) ? AppEvents.publish(Events.Success, 'Success') : AppEvents.publish(Events.Error, `${error}`);
19 | };
20 |
21 | export default handleError;
22 |
--------------------------------------------------------------------------------
/src/utils/logicUtils.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import AppEvents, { Events } from './AppEvents';
3 |
4 | /**
5 | * gets the specified value using key
6 | * @param key
7 | */
8 | const get = (key: string, defaults?: T) => (state: T, payload: Record): T => {
9 | return _.get(payload, key, !_.isUndefined(defaults) ? defaults : state);
10 | };
11 |
12 | /**
13 | * creates an object from specified keys
14 | * @param key
15 | */
16 | const pick = (keys: K[]) => (state: T, payload: { [k in K]: T[k] }): { [k in K]: T[k] } => {
17 | return _.pick(payload, keys);
18 | };
19 |
20 | /**
21 | * creates an array of object with keys
22 | * @param arrayOfObject
23 | */
24 | const addKey = (
25 | arrayOfObject: Array>,
26 | keys: Array = ['id'],
27 | ): Array> => {
28 | return _.map(arrayOfObject, (obj) => {
29 | let mkey = '';
30 | return {
31 | ...obj,
32 | key: _.map(keys, (tkey: string) => {
33 | mkey += _.get(obj, tkey, '');
34 | return mkey;
35 | }),
36 | };
37 | });
38 | };
39 |
40 | const handleError = (error = '', success = 'Successfull !'): void => {
41 | _.isEmpty(error) ? AppEvents.publish(Events.Success, success) : AppEvents.publish(Events.Error, `${error}`);
42 | };
43 |
44 | export { get, pick, addKey, handleError };
45 |
--------------------------------------------------------------------------------
/src/utils/showConfirm.ts:
--------------------------------------------------------------------------------
1 | import Modal from 'antd/lib/modal';
2 |
3 | const { confirm } = Modal;
4 |
5 | function showConfirm(actionCall: () => void, title = 'Are you sure ?'): void {
6 | confirm({
7 | title: title,
8 | onOk() {
9 | actionCall();
10 | },
11 | });
12 | }
13 |
14 | export default showConfirm;
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "experimentalDecorators": true,
4 | "strictNullChecks": false,
5 | "baseUrl": ".",
6 | "outDir": "./dist",
7 | "sourceMap": true,
8 | "lib": ["dom", "dom.iterable", "esnext"],
9 | "allowJs": false,
10 | "allowSyntheticDefaultImports": true,
11 | "alwaysStrict": true,
12 | "skipLibCheck": true,
13 | "esModuleInterop": true,
14 | "strict": true,
15 | "forceConsistentCasingInFileNames": true,
16 | "module": "esnext",
17 | "target": "es6",
18 | "moduleResolution": "node",
19 | "resolveJsonModule": true,
20 | "isolatedModules": true,
21 | "jsx": "react",
22 | "removeComments": true,
23 | "paths": {
24 | "app-ui/*": ["src/*"],
25 | "components/*": ["src/components/*"],
26 | "lib/*": ["src/lib/*"],
27 | "ui-utils/*": ["src/utils/*"],
28 | "styles/*": ["src/styles/*"],
29 | "ui-types/*": ["src/types/*"],
30 | "redux-types/*": ["src/types/*"],
31 | "client/*": ["src/client/*"],
32 | "logic/*": ["src/logic/*"],
33 | "store/*": ["src/store/*"]
34 | }
35 | },
36 | "include": ["src"],
37 | "exclude": ["node_modules"]
38 | }
39 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const { merge } = require('webpack-merge');
4 |
5 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
6 | const HtmlWebpackPlugin = require('html-webpack-plugin');
7 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
8 | const CopyWebpackPlugin = require('copy-webpack-plugin');
9 |
10 | const modeConfig = (mode) => require(`./buildUtils/webpack.${mode}`);
11 |
12 | const getIncludeDirs = () => [path.join(__dirname, 'src')];
13 |
14 | const getPlugins = (analyse) => {
15 | const plugins = [
16 | new CleanWebpackPlugin(),
17 | new HtmlWebpackPlugin({
18 | template: './public/index.html',
19 | }),
20 | new CopyWebpackPlugin({
21 | patterns: ['favicon', 'svg', 'style.css', 'manifest.json', 'robots.txt'].map((file) => ({
22 | from: path.join(__dirname, `public/${file}`),
23 | to: path.join(__dirname, `dist/${file}`),
24 | })),
25 | }),
26 | // ___ANTD___ specific
27 | new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /es-us/),
28 | ];
29 | if (analyse) {
30 | plugins.push(new BundleAnalyzerPlugin());
31 | }
32 | return plugins;
33 | };
34 |
35 | module.exports = (props) => {
36 | let mode = 'production';
37 | if (props?.development) {
38 | mode = 'development';
39 | }
40 |
41 | return merge(
42 | {
43 | entry: path.join(__dirname, 'src/components/index.tsx'),
44 | module: {
45 | rules: [
46 | {
47 | test: /\.(png|svg|jpg|gif)$/,
48 | exclude: /(node_modules)/,
49 | use: 'file-loader',
50 | },
51 | {
52 | test: /\.(ts|tsx)$/,
53 | include: getIncludeDirs(),
54 | loader: 'ts-loader',
55 | },
56 | ],
57 | },
58 | plugins: getPlugins(props.analyze),
59 | resolve: {
60 | alias: {
61 | 'app-ui': path.resolve(__dirname, 'src'),
62 | // UI
63 | components: path.resolve(__dirname, 'src/components'),
64 | lib: path.resolve(__dirname, 'src/lib'),
65 | 'ui-utils': path.resolve(__dirname, 'src/utils'),
66 | styles: path.resolve(__dirname, 'src/styles'),
67 | 'ui-types': path.resolve(__dirname, 'src/types'),
68 | client: path.resolve(__dirname, 'src/client'),
69 | store: path.resolve(__dirname, 'src/store'),
70 | },
71 | extensions: ['.tsx', '.ts', '.js', '.json'],
72 | },
73 | target: 'web',
74 | },
75 | modeConfig(mode),
76 | );
77 | };
78 |
--------------------------------------------------------------------------------