mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
Compare commits
30 Commits
v0.9.9
...
api-rate-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b0feb9022 | ||
|
|
92f929152f | ||
|
|
da514403a1 | ||
|
|
d57f9e5171 | ||
|
|
0a1299b8a6 | ||
|
|
326a2038e7 | ||
|
|
94bb153120 | ||
|
|
223756b7ae | ||
|
|
a773ee9966 | ||
|
|
47790fba84 | ||
|
|
b122fdc43a | ||
|
|
cb93f313ec | ||
|
|
74c31c5f20 | ||
|
|
d411ae3e68 | ||
|
|
aecef878ba | ||
|
|
ec90056f7b | ||
|
|
30f2f1fb4c | ||
|
|
c72f5374f3 | ||
|
|
66de03b143 | ||
|
|
2b33583a03 | ||
|
|
e5611b4446 | ||
|
|
d12157a8d4 | ||
|
|
b24badfa52 | ||
|
|
c992562760 | ||
|
|
b46154ba59 | ||
|
|
7171fb2a69 | ||
|
|
c64a14aef3 | ||
|
|
ac539aed34 | ||
|
|
b35d22d3b3 | ||
|
|
44fce6f33e |
53
.all-contributorsrc
Normal file
53
.all-contributorsrc
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"imageSize": 100,
|
||||||
|
"commit": false,
|
||||||
|
"commitType": "docs",
|
||||||
|
"commitConvention": "angular",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"login": "abouolia",
|
||||||
|
"name": "Ahmed Bouhuolia",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/2197422?v=4",
|
||||||
|
"profile": "https://github.com/abouolia",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "ameir",
|
||||||
|
"name": "Ameir Abdeldayem",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/374330?v=4",
|
||||||
|
"profile": "http://ameir.net",
|
||||||
|
"contributions": [
|
||||||
|
"bug"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "elforjani13",
|
||||||
|
"name": "ElforJani13",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/39470382?v=4",
|
||||||
|
"profile": "https://github.com/elforjani13",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "scheibling",
|
||||||
|
"name": "Lars Scheibling",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/24367830?v=4",
|
||||||
|
"profile": "https://scheibling.se",
|
||||||
|
"contributions": [
|
||||||
|
"bug"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contributorsPerLine": 7,
|
||||||
|
"skipCi": true,
|
||||||
|
"repoType": "github",
|
||||||
|
"repoHost": "https://github.com",
|
||||||
|
"projectName": "bigcapital",
|
||||||
|
"projectOwner": "bigcapitalhq"
|
||||||
|
}
|
||||||
@@ -47,3 +47,6 @@ AGENDASH_AUTH_PASSWORD=123123
|
|||||||
SIGNUP_DISABLED=false
|
SIGNUP_DISABLED=false
|
||||||
SIGNUP_ALLOWED_DOMAINS=
|
SIGNUP_ALLOWED_DOMAINS=
|
||||||
SIGNUP_ALLOWED_EMAILS=
|
SIGNUP_ALLOWED_EMAILS=
|
||||||
|
|
||||||
|
# API rate limit (points,duration,block duration).
|
||||||
|
API_RATE_LIMIT=120,60,600
|
||||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -2,6 +2,18 @@
|
|||||||
|
|
||||||
All notable changes to Bigcapital server-side will be in this file.
|
All notable changes to Bigcapital server-side will be in this file.
|
||||||
|
|
||||||
|
# [0.9.9] - 28-06-2023
|
||||||
|
|
||||||
|
* refactor: Customer and vendor select component by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/171
|
||||||
|
* chore: Move auto-increment components in separate files by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/170
|
||||||
|
* fix: Style of quick item drawer by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/173
|
||||||
|
* fix: Should not show the form before loading account by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/172
|
||||||
|
* fix: Payment made form does not handle not unique number an e… by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/177
|
||||||
|
* fix: Internal note of invoice/bill payment does not saving by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/181
|
||||||
|
* fix: Storing cash flow transaction description by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/180
|
||||||
|
* fix: No currency in amount field on money in/out dialogs by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/179
|
||||||
|
* fix: No default branch for customer/vendor opening balance branch by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/182
|
||||||
|
|
||||||
# [0.9.8] - 19-06-2023
|
# [0.9.8] - 19-06-2023
|
||||||
|
|
||||||
`bigcapitalhq/webapp`
|
`bigcapitalhq/webapp`
|
||||||
|
|||||||
35
README.md
35
README.md
@@ -47,3 +47,38 @@ Bigcapital is a smart and open-source accounting and inventory software, Bigcapi
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
Please see [Releases](https://github.com/bigcapitalhq/bigcapital/releases) for more information what has changed recently.
|
Please see [Releases](https://github.com/bigcapitalhq/bigcapital/releases) for more information what has changed recently.
|
||||||
|
|
||||||
|
# Recognition
|
||||||
|
|
||||||
|
<a href="https://news.ycombinator.com/item?id=36118990">
|
||||||
|
<img
|
||||||
|
style="width: 250px; height: 54px;" width="250" height="54"
|
||||||
|
alt="Featured on Hacker News"
|
||||||
|
src="https://hackernews-badge.vercel.app/api?id=36118990"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/abouolia"><img src="https://avatars.githubusercontent.com/u/2197422?v=4?s=100" width="100px;" alt="Ahmed Bouhuolia"/><br /><sub><b>Ahmed Bouhuolia</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=abouolia" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/elforjani13"><img src="https://avatars.githubusercontent.com/u/39470382?v=4?s=100" width="100px;" alt="ElforJani13"/><br /><sub><b>ElforJani13</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=elforjani13" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="http://ameir.net"><img src="https://avatars.githubusercontent.com/u/374330?v=4?s=100" width="100px;" alt="Ameir Abdeldayem"/><br /><sub><b>Ameir Abdeldayem</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Aameir" title="Bug reports">🐛</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://scheibling.se"><img src="https://avatars.githubusercontent.com/u/24367830?v=4?s=100" width="100px;" alt="Lars Scheibling"/><br /><sub><b>Lars Scheibling</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Ascheibling" title="Bug reports">🐛</a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
|||||||
13
e2e/_utils.ts
Normal file
13
e2e/_utils.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export const clearLocalStorage = (page: Page) => {
|
||||||
|
return page.evaluate(`window.localStorage.clear()`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const defaultPageConfig = () => {
|
||||||
|
return {
|
||||||
|
extraHTTPHeaders: {
|
||||||
|
'ngrok-skip-browser-warning': 'any-value',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,14 +1,23 @@
|
|||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, Page } from '@playwright/test';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { clearLocalStorage, defaultPageConfig } from './_utils';
|
||||||
|
|
||||||
let authPage: Page;
|
let authPage: Page;
|
||||||
|
|
||||||
test.describe('authentication', () => {
|
test.describe('authentication', () => {
|
||||||
test.beforeAll(async ({ browser }) => {
|
test.beforeAll(async ({ browser }) => {
|
||||||
authPage = await browser.newPage();
|
authPage = await browser.newPage({ ...defaultPageConfig() });
|
||||||
|
});
|
||||||
|
test.afterAll(async () => {
|
||||||
|
await authPage.close();
|
||||||
|
});
|
||||||
|
test.afterEach(async ({ context }) => {
|
||||||
|
context.clearCookies();
|
||||||
|
await clearLocalStorage(authPage);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('login', () => {
|
test.describe('login', () => {
|
||||||
test.beforeAll(async () => {
|
test.beforeEach(async () => {
|
||||||
await authPage.goto('/auth/login');
|
await authPage.goto('/auth/login');
|
||||||
});
|
});
|
||||||
test('should show the login page.', async () => {
|
test('should show the login page.', async () => {
|
||||||
@@ -30,10 +39,23 @@ test.describe('authentication', () => {
|
|||||||
await authPage.getByRole('link', { name: 'Sign up' }).click();
|
await authPage.getByRole('link', { name: 'Sign up' }).click();
|
||||||
await expect(authPage.url()).toContain('/auth/register');
|
await expect(authPage.url()).toContain('/auth/register');
|
||||||
});
|
});
|
||||||
|
test('should the email or password is not correct.', async () => {
|
||||||
|
await authPage.getByLabel('Email Address').click();
|
||||||
|
await authPage.getByLabel('Email Address').fill(faker.internet.email());
|
||||||
|
|
||||||
|
await authPage.getByLabel('Password').click();
|
||||||
|
await authPage.getByLabel('Password').fill(faker.internet.password());
|
||||||
|
|
||||||
|
await authPage.getByRole('button', { name: 'Log in' }).click();
|
||||||
|
|
||||||
|
await expect(authPage.locator('body')).toContainText(
|
||||||
|
'The email and password you entered did not match our records.'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('register', () => {
|
test.describe('register', () => {
|
||||||
test.beforeAll(async () => {
|
test.beforeEach(async () => {
|
||||||
await authPage.goto('/auth/register');
|
await authPage.goto('/auth/register');
|
||||||
});
|
});
|
||||||
test('should first name, last name, email and password be required.', async () => {
|
test('should first name, last name, email and password be required.', async () => {
|
||||||
@@ -52,10 +74,36 @@ test.describe('authentication', () => {
|
|||||||
'Password is a required field'
|
'Password is a required field'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
test('should signup successfully.', async () => {
|
||||||
|
const form = authPage.locator('form');
|
||||||
|
await form.getByLabel('First Name').click();
|
||||||
|
await form.getByLabel('First Name').fill(faker.person.firstName());
|
||||||
|
|
||||||
|
await form.getByLabel('Email').click();
|
||||||
|
await form.getByLabel('Email').fill(faker.internet.email());
|
||||||
|
|
||||||
|
await form.getByLabel('Last Name').click();
|
||||||
|
await form.getByLabel('Last Name').fill(faker.person.lastName());
|
||||||
|
|
||||||
|
await form.getByLabel('Password').click();
|
||||||
|
await form.getByLabel('Password').fill(faker.internet.password());
|
||||||
|
|
||||||
|
await authPage.getByRole('button', { name: 'Register' }).click();
|
||||||
|
|
||||||
|
await expect(authPage.locator('h1')).toContainText(
|
||||||
|
'Register a New Organization now!'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('reset password', () => {
|
test.describe('reset password', () => {
|
||||||
test.beforeAll(async () => {
|
test.beforeAll(async ({ browser }) => {
|
||||||
|
authPage = await browser.newPage({ ...defaultPageConfig() });
|
||||||
|
});
|
||||||
|
test.afterAll(async () => {
|
||||||
|
await authPage.close();
|
||||||
|
});
|
||||||
|
test.beforeEach(async () => {
|
||||||
await authPage.goto('/auth/send_reset_password');
|
await authPage.goto('/auth/send_reset_password');
|
||||||
});
|
});
|
||||||
test('should email be required.', async () => {
|
test('should email be required.', async () => {
|
||||||
|
|||||||
86
e2e/onboarding.spec.ts
Normal file
86
e2e/onboarding.spec.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { test, expect, Page } from '@playwright/test';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { defaultPageConfig } from './_utils';
|
||||||
|
|
||||||
|
let authPage: Page;
|
||||||
|
let businessLegalName: string = faker.company.name();
|
||||||
|
|
||||||
|
test.describe('onboarding', () => {
|
||||||
|
test.beforeAll(async ({ browser }) => {
|
||||||
|
authPage = await browser.newPage({ ...defaultPageConfig() });
|
||||||
|
await authPage.goto('/auth/register');
|
||||||
|
|
||||||
|
const form = authPage.locator('form');
|
||||||
|
|
||||||
|
await form.getByLabel('First Name').fill(faker.person.firstName());
|
||||||
|
await form.getByLabel('Email').fill(faker.internet.email());
|
||||||
|
await form.getByLabel('Last Name').fill(faker.person.lastName());
|
||||||
|
await form.getByLabel('Password').fill(faker.internet.password());
|
||||||
|
|
||||||
|
await authPage.getByRole('button', { name: 'Register' }).click();
|
||||||
|
});
|
||||||
|
test('should validation catch all required fields', async () => {
|
||||||
|
const form = authPage.locator('form');
|
||||||
|
|
||||||
|
await authPage.getByRole('button', { name: 'Save & Continue' }).click();
|
||||||
|
|
||||||
|
await expect(form).toContainText('Organization name is a required field');
|
||||||
|
await expect(form).toContainText('Location is a required field');
|
||||||
|
await expect(form).toContainText('Base currency is a required field');
|
||||||
|
await expect(form).toContainText('Fiscal year is a required field');
|
||||||
|
await expect(form).toContainText('Time zone is a required field');
|
||||||
|
});
|
||||||
|
test.describe('after onboarding', () => {
|
||||||
|
test.beforeAll(async () => {
|
||||||
|
await authPage.getByLabel('Legal Organization Name').click();
|
||||||
|
await authPage
|
||||||
|
.getByLabel('Legal Organization Name')
|
||||||
|
.fill(businessLegalName);
|
||||||
|
|
||||||
|
// Fill Business Location.
|
||||||
|
await authPage
|
||||||
|
.getByRole('button', { name: 'Select Business Location...' })
|
||||||
|
.click();
|
||||||
|
await authPage.locator('a').filter({ hasText: 'Albania' }).click();
|
||||||
|
|
||||||
|
// Fill Base Currency.
|
||||||
|
await authPage
|
||||||
|
.getByRole('button', { name: 'Select Base Currency...' })
|
||||||
|
.click();
|
||||||
|
await authPage
|
||||||
|
.locator('a')
|
||||||
|
.filter({ hasText: 'AED - United Arab Emirates Dirham' })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// Fill Fasical Year.
|
||||||
|
await authPage
|
||||||
|
.getByRole('button', { name: 'Select Fiscal Year...' })
|
||||||
|
.click();
|
||||||
|
await authPage.locator('a').filter({ hasText: 'June - May' }).click();
|
||||||
|
|
||||||
|
// Fill Timezone.
|
||||||
|
await authPage
|
||||||
|
.getByRole('button', { name: 'Select Time Zone...' })
|
||||||
|
.click();
|
||||||
|
await authPage.getByText('Pacific/Marquesas-09:30').click();
|
||||||
|
|
||||||
|
// Click on Submit button
|
||||||
|
await authPage.getByRole('button', { name: 'Save & Continue' }).click();
|
||||||
|
});
|
||||||
|
test('should onboarding process success', async () => {
|
||||||
|
await expect(authPage.locator('body')).toContainText(
|
||||||
|
'Congrats! You are ready to go',
|
||||||
|
{
|
||||||
|
timeout: 30000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('should go to the dashboard after clicking on "Go to dashboard" button.', async () => {
|
||||||
|
await authPage.getByRole('button', { name: 'Go to dashboard' }).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
authPage.locator('[data-testId="dashboard-topbar"] h1')
|
||||||
|
).toContainText(businessLegalName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -333,6 +333,12 @@
|
|||||||
"@jridgewell/trace-mapping": "0.3.9"
|
"@jridgewell/trace-mapping": "0.3.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@faker-js/faker": {
|
||||||
|
"version": "8.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.2.tgz",
|
||||||
|
"integrity": "sha512-Uo3pGspElQW91PCvKSIAXoEgAUlRnH29sX2/p89kg7sP1m2PzCufHINd0FhTXQf6DYGiUlVncdSPa2F9wxed2A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@gar/promisify": {
|
"@gar/promisify": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
|
||||||
@@ -945,6 +951,7 @@
|
|||||||
"version": "1.32.3",
|
"version": "1.32.3",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.3.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.3.tgz",
|
||||||
"integrity": "sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==",
|
"integrity": "sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"fsevents": "2.3.2",
|
"fsevents": "2.3.2",
|
||||||
@@ -954,7 +961,8 @@
|
|||||||
"playwright-core": {
|
"playwright-core": {
|
||||||
"version": "1.32.3",
|
"version": "1.32.3",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.32.3.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.32.3.tgz",
|
||||||
"integrity": "sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg=="
|
"integrity": "sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1003,7 +1011,8 @@
|
|||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "18.14.6",
|
"version": "18.14.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz",
|
||||||
"integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA=="
|
"integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/normalize-package-data": {
|
"@types/normalize-package-data": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
@@ -2324,6 +2333,7 @@
|
|||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
"shared/*"
|
"shared/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^17.4.2",
|
||||||
"@commitlint/config-conventional": "^17.4.2",
|
"@commitlint/config-conventional": "^17.4.2",
|
||||||
"@commitlint/config-lerna-scopes": "^17.4.2",
|
"@commitlint/config-lerna-scopes": "^17.4.2",
|
||||||
|
"@faker-js/faker": "^8.0.2",
|
||||||
|
"@playwright/test": "^1.32.3",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"lerna": "^6.4.1",
|
"lerna": "^6.4.1"
|
||||||
"@commitlint/cli": "^17.4.2",
|
|
||||||
"@playwright/test": "^1.32.3"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "14.x"
|
"node": "14.x"
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { toInteger } from 'lodash';
|
||||||
import { castCommaListEnvVarToArray, parseBoolean } from '@/utils';
|
import { castCommaListEnvVarToArray, parseBoolean } from '@/utils';
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
const API_RATE_LIMIT = process.env.API_RATE_LIMIT?.split(',') || [];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
* Your favorite port
|
* Your favorite port
|
||||||
@@ -97,7 +100,7 @@ module.exports = {
|
|||||||
jwtSecret: process.env.JWT_SECRET,
|
jwtSecret: process.env.JWT_SECRET,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
resetPasswordSeconds: 600,
|
resetPasswordSeconds: 600,
|
||||||
|
|
||||||
@@ -130,9 +133,9 @@ module.exports = {
|
|||||||
blockDuration: 60 * 15,
|
blockDuration: 60 * 15,
|
||||||
},
|
},
|
||||||
requests: {
|
requests: {
|
||||||
points: 60,
|
points: API_RATE_LIMIT[0] ? toInteger(API_RATE_LIMIT[0]) : 120,
|
||||||
duration: 60,
|
duration: API_RATE_LIMIT[1] ? toInteger(API_RATE_LIMIT[1]) : 60,
|
||||||
blockDuration: 60 * 10,
|
blockDuration: API_RATE_LIMIT[2] ? toInteger(API_RATE_LIMIT[2]) : 60 * 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
14
packages/webapp/package-lock.json
generated
14
packages/webapp/package-lock.json
generated
@@ -1205,9 +1205,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@blueprintjs-formik/core": {
|
"@blueprintjs-formik/core": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/@blueprintjs-formik/core/-/core-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@blueprintjs-formik/core/-/core-0.3.4.tgz",
|
||||||
"integrity": "sha512-ko7g54YSEcSq2K/GEpmiTG0foGLqe7DwgXGhkGxYEiHhLAUv8WvQmrFsm8e/KOW7n8mLGq0uaZVe2l8m3JTGGQ==",
|
"integrity": "sha512-gksuBYXXvX7IhZXbPEFEAHgmJWp1vt/GTMW0GYBkCoGBAvXy08hIHjMc85M0WNyen+tic3NRas6I2wsjgokgqw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.keyby": "^4.6.0",
|
"lodash.keyby": "^4.6.0",
|
||||||
@@ -1227,9 +1227,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@blueprintjs-formik/select": {
|
"@blueprintjs-formik/select": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@blueprintjs-formik/select/-/select-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@blueprintjs-formik/select/-/select-0.2.5.tgz",
|
||||||
"integrity": "sha512-zB28/hLkuO5zZXkjFmqfiVDGW+uvj9b8e6kHh9aOfY70edSFIfw3bj+NYR7BaDZoIYu3KuZQDFGqgs23ua5Z1g==",
|
"integrity": "sha512-Sztf5dOemedUBfEjnDWD8ryfMU/x95hyhIgJT5/ywC/jQfX+d/K2OhujklTrCDzQilUeAJLoVkSdV+w77n8ckQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.keyby": "^4.6.0",
|
"lodash.keyby": "^4.6.0",
|
||||||
@@ -17751,4 +17751,4 @@
|
|||||||
"integrity": "sha512-7UlRWU4Q3uCMCeDVMOm7eBrIu145OqsIJ3p6zq58l8UsSYwKWxc6zEapC5YA9tIeh0oheb4cT9Kk2Wq353loFg=="
|
"integrity": "sha512-7UlRWU4Q3uCMCeDVMOm7eBrIu145OqsIJ3p6zq58l8UsSYwKWxc6zEapC5YA9tIeh0oheb4cT9Kk2Wq353loFg=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
"version": "0.9.6",
|
"version": "0.9.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blueprintjs-formik/core": "^0.3.3",
|
"@blueprintjs-formik/core": "^0.3.4",
|
||||||
"@blueprintjs-formik/datetime": "^0.3.4",
|
"@blueprintjs-formik/datetime": "^0.3.4",
|
||||||
"@blueprintjs-formik/select": "^0.2.4",
|
"@blueprintjs-formik/select": "^0.2.5",
|
||||||
"@blueprintjs/core": "^3.50.2",
|
"@blueprintjs/core": "^3.50.2",
|
||||||
"@blueprintjs/datetime": "^3.23.12",
|
"@blueprintjs/datetime": "^3.23.12",
|
||||||
"@blueprintjs/popover2": "^0.11.1",
|
"@blueprintjs/popover2": "^0.11.1",
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ function DashboardTopbar({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="dashboard__topbar">
|
<div class="dashboard__topbar" data-testId={'dashboard-topbar'}>
|
||||||
<div class="dashboard__topbar-left">
|
<div class="dashboard__topbar-left">
|
||||||
<div class="dashboard__topbar-sidebar-toggle">
|
<div class="dashboard__topbar-sidebar-toggle">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { compose } from '@/utils';
|
|||||||
|
|
||||||
let toastKeySessionExpired;
|
let toastKeySessionExpired;
|
||||||
let toastKeySomethingWrong;
|
let toastKeySomethingWrong;
|
||||||
|
let toastTooManyRequests;
|
||||||
|
|
||||||
function GlobalErrors({
|
function GlobalErrors({
|
||||||
// #withGlobalErrors
|
// #withGlobalErrors
|
||||||
@@ -41,6 +42,18 @@ function GlobalErrors({
|
|||||||
toastKeySomethingWrong,
|
toastKeySomethingWrong,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (globalErrors.too_many_requests) {
|
||||||
|
toastTooManyRequests = AppToaster.show(
|
||||||
|
{
|
||||||
|
message: intl.get('global_error.too_many_requests'),
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
onDismiss: () => {
|
||||||
|
globalErrorsSet({ too_many_requests: false });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
toastTooManyRequests,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (globalErrors.access_denied) {
|
if (globalErrors.access_denied) {
|
||||||
toastKeySomethingWrong = AppToaster.show(
|
toastKeySomethingWrong = AppToaster.show(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ export default function useApiRequest() {
|
|||||||
if (status === 403) {
|
if (status === 403) {
|
||||||
setGlobalErrors({ access_denied: true });
|
setGlobalErrors({ access_denied: true });
|
||||||
}
|
}
|
||||||
|
if (status === 429) {
|
||||||
|
setGlobalErrors({ too_many_requests: true });
|
||||||
|
}
|
||||||
if (status === 400) {
|
if (status === 400) {
|
||||||
const lockedError = data.errors.find(
|
const lockedError = data.errors.find(
|
||||||
(error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
|
(error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
|
||||||
|
|||||||
@@ -2292,5 +2292,6 @@
|
|||||||
"sidebar.projects": "Projects",
|
"sidebar.projects": "Projects",
|
||||||
"sidebar.new_project": "New Project",
|
"sidebar.new_project": "New Project",
|
||||||
"sidebar.new_time_entry": "New Time Entry",
|
"sidebar.new_time_entry": "New Time Entry",
|
||||||
"sidebar.project_profitability_summary": "Project Profitability Summary"
|
"sidebar.project_profitability_summary": "Project Profitability Summary",
|
||||||
|
"global_error.too_many_requests": "Too many requests"
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
|
@import '@/style/variables.scss';
|
||||||
|
|
||||||
.bigcapital-loading {
|
.bigcapital-loading {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
z-index: 999999;
|
z-index: $zindex-dashboard-splash-screen;
|
||||||
|
|
||||||
.center {
|
.center {
|
||||||
width: auto;
|
width: auto;
|
||||||
@@ -18,4 +20,4 @@
|
|||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,3 +45,7 @@ $form-check-input-checked-color: #fff;
|
|||||||
$form-check-input-checked-bg-color: $blue1;
|
$form-check-input-checked-bg-color: $blue1;
|
||||||
$form-check-input-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M12,5c-0.28,0-0.53,0.11-0.71,0.29L7,9.59L4.71,7.29C4.53,7.11,4.28,7,4,7C3.45,7,3,7.45,3,8c0,0.28,0.11,0.53,0.29,0.71l3,3C6.47,11.89,6.72,12,7,12s0.53-0.11,0.71-0.29l5-5C12.89,6.53,13,6.28,13,6C13,5.45,12.55,5,12,5z'/></g></g></svg>") !default;
|
$form-check-input-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M12,5c-0.28,0-0.53,0.11-0.71,0.29L7,9.59L4.71,7.29C4.53,7.11,4.28,7,4,7C3.45,7,3,7.45,3,8c0,0.28,0.11,0.53,0.29,0.71l3,3C6.47,11.89,6.72,12,7,12s0.53-0.11,0.71-0.29l5-5C12.89,6.53,13,6.28,13,6C13,5.45,12.55,5,12,5z'/></g></g></svg>") !default;
|
||||||
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M11,7H5C4.45,7,4,7.45,4,8c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1C12,7.45,11.55,7,11,7z'/></g></g></svg>") !default;
|
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M11,7H5C4.45,7,4,7.45,4,8c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1C12,7.45,11.55,7,11,7z'/></g></g></svg>") !default;
|
||||||
|
|
||||||
|
// z-indexs
|
||||||
|
$zindex-dashboard-splash-screen: 39;
|
||||||
|
$zindex-toast: 40;
|
||||||
11
vercel.json
11
vercel.json
@@ -3,7 +3,12 @@
|
|||||||
"buildCommand": "CI='' npm run build:webapp",
|
"buildCommand": "CI='' npm run build:webapp",
|
||||||
"outputDirectory": "packages/webapp/build",
|
"outputDirectory": "packages/webapp/build",
|
||||||
"rewrites": [{
|
"rewrites": [{
|
||||||
"source": "/(.*)",
|
"source": "/api/:slug*",
|
||||||
"destination": "/"
|
"destination": "https://dev.bigcapital.ly/api/:slug*"
|
||||||
}]
|
},
|
||||||
|
{
|
||||||
|
"source": "/(.*)",
|
||||||
|
"destination": "/"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user