Skip to content

Commit e08f715

Browse files
committed
Merge branch 'release-2.20.7' into release
2 parents 094e054 + 4b9476c commit e08f715

File tree

28 files changed

+1274
-81
lines changed

28 files changed

+1274
-81
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.env.staging
55
.vscode/
66
node_modules/
7+
minio/
78
npm-debug.log
89
dump.rdb
910
static/dist/
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import { render, screen, fireEvent, waitFor } from '../../test-utils';
3+
import { DropdownMenu, DropdownMenuAlignment } from './DropdownMenu';
4+
5+
describe('DropdownMenu', () => {
6+
const renderDropdown = () => {
7+
render(
8+
<DropdownMenu
9+
aria-label="More options"
10+
align={DropdownMenuAlignment.RIGHT}
11+
>
12+
<li role="menuitem">Item One</li>
13+
<li role="menuitem">Item Two</li>
14+
<li role="menuitem">Item Three</li>
15+
</DropdownMenu>
16+
);
17+
};
18+
19+
it('should render the dropdown button', () => {
20+
renderDropdown();
21+
22+
const button = screen.getByRole('button', { name: 'More options' });
23+
expect(button).toBeInTheDocument();
24+
25+
expect(screen.queryByRole('menu')).not.toBeInTheDocument();
26+
});
27+
28+
it('should open dropdown and render menu items when button is clicked', () => {
29+
renderDropdown();
30+
31+
const button = screen.getByRole('button', { name: 'More options' });
32+
33+
fireEvent.click(button);
34+
35+
expect(screen.getByRole('menu')).toBeInTheDocument();
36+
37+
expect(screen.getByText('Item One')).toBeInTheDocument();
38+
expect(screen.getByText('Item Two')).toBeInTheDocument();
39+
expect(screen.getByText('Item Three')).toBeInTheDocument();
40+
});
41+
42+
it('should close the menu after selecting an item', async () => {
43+
renderDropdown();
44+
45+
const button = screen.getByRole('button', { name: 'More options' });
46+
fireEvent.click(button);
47+
48+
const item = screen.getByText('Item One');
49+
fireEvent.mouseUp(item);
50+
51+
await waitFor(() => {
52+
expect(screen.queryByRole('menu')).not.toBeInTheDocument();
53+
});
54+
});
55+
});

client/i18n.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ export const availableLanguages = [
4141
'zh-CN',
4242
'zh-TW',
4343
'tr',
44-
'ur'
44+
'ur',
45+
'ne'
4546
];
4647

4748
const detectedLanguage = getPreferredLanguage(
@@ -76,7 +77,8 @@ export function languageKeyToLabel(lang) {
7677
'zh-CN': '简体中文',
7778
'zh-TW': '正體中文',
7879
tr: 'Türkçe',
79-
ur: 'اردو'
80+
ur: 'اردو',
81+
ne: 'नेपाली'
8082
};
8183
return languageMap[lang];
8284
}

client/modules/IDE/actions/uploader.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,23 @@ export function dropzoneCompleteCallback(file) {
8282
content: file.content
8383
};
8484
dispatch(handleCreateFile(formParams, false));
85+
} else if (file.status === 'error' || file.xhr.status >= 400) {
86+
let uploadFileErrorMessage = 'Uploading file to AWS failed.';
87+
if (file.xhr?.response) {
88+
const parser = new DOMParser();
89+
const xmlDoc = parser.parseFromString(file.xhr.response, 'text/xml');
90+
const message = xmlDoc.getElementsByTagName('Message')[0]?.textContent;
91+
const code = xmlDoc.getElementsByTagName('Code')[0]?.textContent;
92+
uploadFileErrorMessage = `${code}: ${message}`;
93+
}
94+
file.previewElement.classList.add('dz-error');
95+
file.previewElement.classList.remove('dz-success');
96+
const dzErrorMessageElement = file.previewElement?.querySelector(
97+
'[data-dz-errormessage]'
98+
);
99+
if (dzErrorMessageElement) {
100+
dzErrorMessageElement.textContent = uploadFileErrorMessage;
101+
}
85102
}
86103
};
87104
}

client/modules/IDE/components/FileUploader.jsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,36 @@ const StyledUploader = styled.div`
2323
.dz-preview.dz-image-preview {
2424
background-color: transparent;
2525
}
26+
.dz-image img {
27+
width: 100%;
28+
height: auto;
29+
}
30+
.dz-details .dz-filename:hover {
31+
overflow: hidden;
32+
}
33+
.dz-error-message span {
34+
width: 100%;
35+
height: auto;
36+
overflow: hidden;
37+
display: block;
38+
}
39+
.dz-error-mark:hover {
40+
cursor: pointer !important;
41+
}
2642
`;
2743

2844
function FileUploader() {
2945
const { t } = useTranslation();
3046
const dispatch = useDispatch();
3147
const userId = useSelector((state) => state.user.id);
32-
48+
const deleteUploadErrorFiles = (uploader, file) => {
49+
if (file.status === 'error') {
50+
file.previewElement.addEventListener('click', (e) => {
51+
e.stopPropagation();
52+
uploader.removeFile(file);
53+
});
54+
}
55+
};
3356
useEffect(() => {
3457
const uploader = new Dropzone('div#uploader', {
3558
url: s3BucketHttps,
@@ -52,6 +75,7 @@ function FileUploader() {
5275
});
5376
uploader.on('complete', (file) => {
5477
dispatch(dropzoneCompleteCallback(file));
78+
deleteUploadErrorFiles(uploader, file);
5579
});
5680
return () => {
5781
uploader.destroy();

client/modules/User/components/AccountForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function AccountForm() {
148148
<Field name="currentPassword">
149149
{(field) => (
150150
<p className="form__field">
151-
<label htmlFor="current password" className="form__label">
151+
<label htmlFor="currentPassword" className="form__label">
152152
{t('AccountForm.CurrentPassword')}
153153
</label>
154154
<input
@@ -172,7 +172,7 @@ export function AccountForm() {
172172
<Field name="newPassword">
173173
{(field) => (
174174
<p className="form__field">
175-
<label htmlFor="new password" className="form__label">
175+
<label htmlFor="newPassword" className="form__label">
176176
{t('AccountForm.NewPassword')}
177177
</label>
178178
<input

client/modules/User/components/NewPasswordForm.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function NewPasswordForm(props: { resetPasswordToken: string }) {
3434
className="form__input"
3535
aria-label={t('NewPasswordForm.TitleARIA')}
3636
type="password"
37-
id="Password"
37+
id="password"
3838
autoComplete="new-password"
3939
{...field.input}
4040
/>
@@ -49,14 +49,14 @@ export function NewPasswordForm(props: { resetPasswordToken: string }) {
4949
<Field name="confirmPassword">
5050
{(field) => (
5151
<p className="form__field">
52-
<label htmlFor="confirm password" className="form__label">
52+
<label htmlFor="confirmPassword" className="form__label">
5353
{t('NewPasswordForm.ConfirmPassword')}
5454
</label>
5555
<input
5656
className="form__input"
5757
type="password"
5858
aria-label={t('NewPasswordForm.ConfirmPasswordARIA')}
59-
id="confirm password"
59+
id="confirmPassword"
6060
autoComplete="new-password"
6161
{...field.input}
6262
/>

client/styles/abstracts/_variables.scss

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ $themes: (
5757
error-color: $p5js-pink,
5858
file-hover-color: $light,
5959
file-selected-color: $medium-light,
60-
form-input-placeholder-text-color: $middle-light,
60+
form-input-placeholder-text-color: $middle-gray,
6161
form-input-text-color: $dark,
6262
form-navigation-options-color: $middle-dark,
6363
form-secondary-title-color: $medium-dark,
@@ -91,7 +91,7 @@ $themes: (
9191
ide-border-color: $medium-light,
9292
inactive-text-color: $middle-dark,
9393
input-background-color: $lightest,
94-
input-border-color: $middle-light,
94+
input-border-color: $middle-dark,
9595
input-secondary-background-color: $lightest,
9696
input-selection-background-color: $medium-light,
9797
input-selection-text-color: $dark,
@@ -155,6 +155,7 @@ $themes: (
155155
error-color: $p5js-pink,
156156
file-hover-color: $dark,
157157
file-selected-color: $medium-dark,
158+
form-input-placeholder-text-color: $middle-gray,
158159
form-navigation-options-color: $middle-light,
159160
form-secondary-title-color: $medium-light,
160161
form-title-color: $lightest,
@@ -187,7 +188,7 @@ $themes: (
187188
ide-border-color: $middle-dark,
188189
inactive-text-color: $middle-light,
189190
input-background-color: $dark,
190-
input-border-color: $middle-dark,
191+
input-border-color: $light,
191192
input-secondary-background-color: $medium-dark,
192193
input-selection-background-color: $lightest,
193194
input-selection-text-color: $darkest,

common/p5Versions.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const currentP5Version = '1.11.11'; // Don't update to 2.x until 2026
1+
export const currentP5Version = '1.11.12'; // Don't update to 2.x until 2026
22

33
// Generated from https://www.npmjs.com/package/p5?activeTab=versions
44
// Run this in the console:
@@ -17,7 +17,8 @@ export const p5Versions = [
1717
'2.0.2',
1818
'2.0.1',
1919
'2.0.0',
20-
{ version: '1.11.11', label: '(Default)' },
20+
{ version: '1.11.12', label: '(Default)' },
21+
'1.11.11',
2122
'1.11.10',
2223
'1.11.9',
2324
'1.11.8',

contributor_docs/installation.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ _Note_: The installation steps assume you are using a Unix-like shell. If you ar
3737
7. Install MongoDB and make sure it is running
3838
* For Mac OSX with [homebrew](http://brew.sh/): `brew tap mongodb/brew` then `brew install mongodb-community` and finally start the server with `brew services start mongodb-community` or you can visit the installation guide here [Installation Guide For MacOS](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/)
3939
* For Windows and Linux: [MongoDB Installation](https://docs.mongodb.com/manual/installation/)
40+
* If you have trouble setting up MongoDB locally, an alternative is to use [MongoDB Atlas](https://cloud.mongodb.com/) to get a connection string that you can use as your `MONGO_URL` in the `.env` file. To get your connection string:
41+
- Navigate to [mongodb.com](https://www.mongodb.com/) and sign up or log in.
42+
- Create a new project. Give it any name, and either add a key-value pair or skip that step.
43+
- Create a cluster by choosing the free tier. Give your cluster a name, choose a region, and keep the provider as AWS.
44+
- Set a username and password for your database-user, these will be part of your connection string.
45+
- Choose **Node.js** as the driver for your connection method. You will see a connection string, with or without the password filled in.
46+
- Copy the string and use it as your `MONGO_URL` in the `.env` file.
4047
8. `$ cp .env.example .env`
4148
9. (Optional) Update `.env` with necessary keys to enable certain app behaviors, i.e. add Github ID and Github Secret if you want to be able to log in with Github.
4249
* See the [GitHub API Configuration](#github-api-configuration) section for information on how to authenticate with Github.

0 commit comments

Comments
 (0)