Skip to content

Commit bc59bfa

Browse files
create-issue-branch[bot]loiswells97patch0
authored
Rename a file (#193)
- Created modal for renaming a file using inference based on existing designs for other modals since could not find exact design for this - Refactored `NewComponentButton` to be inside `#app` in the DOM and not to need custom inline styling - Abstracted out the file name validation checking so it can be shared between `NewComponentButton` and `RenameFile` - Added styles for a secondary button Co-authored-by: Lois Wells <lois.wells@raspberrypi.org> Co-authored-by: Patrick Cherry <patch0@users.noreply.github.com>
1 parent 594e4f0 commit bc59bfa

19 files changed

Lines changed: 389 additions & 72 deletions

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
## [Unreleased]
77

88
### Added
9+
10+
- Functionality for renaming a file (#193)
11+
- Styling for a secondary button (#193)
912
- The web component `runCompleted` event now returns `duration: null` if the host page's tab loses focus during the code run (#192)
1013

14+
### Changed
15+
16+
- Updated modal styling (#193)
17+
1118
## [0.4.0]
1219

1320
### Added

src/App.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
button {
55
all: initial;
6+
cursor: pointer;
67
}
78

89
#app {
@@ -34,7 +35,7 @@ button {
3435
fill: $editor-white;
3536
}
3637

37-
button svg {
38+
.btn svg {
3839
fill: inherit;
3940
}
4041
}

src/Icons.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ export const ChevronDown = () => {
2525
)
2626
}
2727

28+
export const CloseIcon = () => {
29+
const [cookies] = useCookies(['fontSize'])
30+
const scale = fontScaleFactors[cookies.fontSize] || 1
31+
return (
32+
<svg transform={`scale(${scale}, ${scale})`} width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
33+
<path d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z"/>
34+
</svg>
35+
)
36+
}
37+
2838
export const CogIcon = () => {
2939
return (
3040
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -115,6 +125,16 @@ export const NewFileIcon = () => {
115125
)
116126
}
117127

128+
export const PencilIcon = () => {
129+
const [cookies] = useCookies(['fontSize'])
130+
const scale = (fontScaleFactors[cookies.fontSize] || 1)
131+
return (
132+
<svg transform={`scale(${scale}, ${scale})`} width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
133+
<path d="M6.75795 3.67889L7.32009 4.24111L1.7842 9.77778H1.22205V9.21556L6.75795 3.67889V3.67889ZM8.95765 0C8.80489 0 8.64602 0.0611111 8.52993 0.177222L7.41175 1.29556L9.7031 3.58722L10.8213 2.46889C11.0596 2.23056 11.0596 1.84556 10.8213 1.60722L9.39147 0.177222C9.26927 0.055 9.11651 0 8.95765 0V0ZM6.75795 1.94944L0 8.70833V11H2.29135L9.0493 4.24111L6.75795 1.94944V1.94944Z"/>
134+
</svg>
135+
)
136+
}
137+
118138
export const PressureIcon = () => {
119139
const [cookies] = useCookies(['fontSize'])
120140
const scale = (fontScaleFactors[cookies.fontSize] || 1) * 1.6

src/Modal.scss

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
@import './colours.scss';
2+
3+
.modal__content {
4+
position: absolute;
5+
width: 40%;
6+
max-width: 450px;
7+
top: 50%;
8+
left: 50%;
9+
right: auto;
10+
bottom: auto;
11+
margin-right: -50%;
12+
transform: translate(-50%, -50%);
13+
border: 0;
14+
border-radius: 10px;
15+
display: flex;
16+
flex-direction: column;
17+
padding: var(--spacing-2);
18+
19+
.modal__header {
20+
display: flex;
21+
h2 {
22+
margin-top: 0;
23+
margin-bottom: var(--spacing-3);
24+
font-size: var(--font-size-u-2)
25+
}
26+
27+
button {
28+
margin-left: auto;
29+
height: fit-content;
30+
margin-right: var(--spacing-1);
31+
margin-top: var(--spacing-1);
32+
}
33+
}
34+
35+
label {
36+
margin-bottom: var(--spacing-1);
37+
font-weight: var(--font-weight-bold);
38+
}
39+
input {
40+
font-size: 1em;
41+
border-radius: 12px;
42+
padding: var(--spacing-1);
43+
}
44+
45+
.modal__buttons {
46+
display: flex;
47+
justify-content: space-between;
48+
margin-top: var(--spacing-2);
49+
margin-left: calc(-1 * var(--spacing-half));
50+
margin-right: calc(-1 * var(--spacing-half));
51+
52+
button {
53+
flex: 1;
54+
margin: 0 var(--spacing-half);
55+
}
56+
}
57+
}
58+
59+
.modal__overlay {
60+
z-index: 1000;
61+
position: fixed;
62+
inset: 0px;
63+
}
64+
65+
.--dark {
66+
.modal__overlay {
67+
background-color: rgba(0,0,0,0.5);
68+
69+
input {
70+
border: 2px solid $editor-white;
71+
background-color: $editor-dark;
72+
color: inherit;
73+
}
74+
}
75+
.modal__content {
76+
background-color: $editor-dark;
77+
}
78+
}
79+
80+
.--light {
81+
.modal__overlay{
82+
background-color: rgba(67,69,76,0.5);
83+
input {
84+
border: 2px solid $editor-light-grey;
85+
background-color: $editor-light-light-light-grey;
86+
}
87+
}
88+
.modal__content {
89+
background-color: $editor-white;
90+
}
91+
}
92+
93+
.font-size-medium {
94+
.modal__overlay {
95+
.modal__header {
96+
h2 {
97+
font-size: var(--font-size-u-4)
98+
}
99+
}
100+
}
101+
}
102+
103+
.font-size-large {
104+
.modal__overlay {
105+
.modal__header {
106+
h2 {
107+
font-size: var(--font-size-u-6)
108+
}
109+
}
110+
}
111+
}

src/components/Button/Button.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
color: inherit;
2424
text-decoration: none;
2525
}
26+
27+
&--secondary {
28+
background-color: $editor-light-grey;
29+
&:hover {
30+
background-color: $editor-mid-light-grey;
31+
}
32+
}
2633

2734
&:disabled {
2835
background-color: $editor-grey;
@@ -35,3 +42,11 @@
3542
}
3643
}
3744

45+
.--dark {
46+
.btn--secondary {
47+
background-color: $editor-mid-light-grey;
48+
&:hover {
49+
background-color: $editor-mid-grey;
50+
}
51+
}
52+
}

src/components/Editor/EditorSlice.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ export const EditorSlice = createSlice({
6868
},
6969
updateComponentName: (state, action) => {
7070
const key = action.payload.key;
71-
const fileName = action.payload.name;
72-
state.project.components[key].name = fileName;
71+
const name = action.payload.name;
72+
const extension = action.payload.extension
73+
state.project.components[key].name = name;
74+
state.project.components[key].extension = extension;
7375
},
7476
setError: (state, action) => {
7577
state.error = action.payload;

src/components/Editor/ErrorMessage/ErrorMessage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import './ErrorMessage.css'
2+
import './ErrorMessage.scss'
33
import { useSelector } from 'react-redux'
44

55
const ErrorMessage = () => {

src/components/Editor/ErrorMessage/ErrorMessage.css renamed to src/components/Editor/ErrorMessage/ErrorMessage.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
color: #7e0305;
33
background-color: #FDE2E1;
44
padding: 0.75rem 1.25rem;
5-
}
65

7-
.error-message--content {
8-
padding: 0;
9-
margin: 0;
6+
&--content {
7+
padding: 0;
8+
margin: 0;
9+
}
1010
}

src/components/Editor/ErrorMessage/NameErrorMessage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import './ErrorMessage.css'
1+
import './ErrorMessage.scss'
22
import { useSelector } from 'react-redux'
33

44
const NameErrorMessage = () => {

src/components/Editor/NewComponentButton/NewComponentButton.js

Lines changed: 26 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,9 @@ import Modal from 'react-modal';
77
import { addProjectComponent, setNameError } from '../EditorSlice';
88
import Button from '../../Button/Button'
99
import NameErrorMessage from '../ErrorMessage/NameErrorMessage';
10-
import { NewFileIcon } from '../../../Icons';
11-
12-
const allowedExtensions = {
13-
"python": [
14-
"py",
15-
"csv",
16-
"txt"
17-
]
18-
}
19-
20-
const allowedExtensionsString = (projectType) => {
21-
const extensionsList = allowedExtensions[projectType];
22-
if (extensionsList.length === 1) {
23-
return `'.${extensionsList[0]}'`
24-
} else {
25-
return `'.` + extensionsList.slice(0,-1).join(`', '.`) + `' or '.` + extensionsList[extensionsList.length-1] + `'`;
26-
}
27-
}
10+
import { CloseIcon, NewFileIcon } from '../../../Icons';
11+
import { validateFileName } from '../../../utils/componentNameValidation';
12+
import { useCookies } from 'react-cookie';
2813

2914
const NewComponentButton = () => {
3015
const [modalIsOpen, setIsOpen] = useState(false);
@@ -33,6 +18,10 @@ const NewComponentButton = () => {
3318
const projectComponents = useSelector((state) => state.editor.project.components);
3419
const componentNames = projectComponents.map(component => `${component.name}.${component.extension}`)
3520

21+
const [cookies] = useCookies(['fontSize', 'theme'])
22+
const isDarkMode = cookies.theme==="dark" || (!cookies.theme && window.matchMedia("(prefers-color-scheme:dark)").matches)
23+
const theme = isDarkMode ? "dark" : "light"
24+
3625
const closeModal = () => setIsOpen(false);
3726
const showModal = () => {
3827
dispatch(setNameError(""));
@@ -42,62 +31,42 @@ const NewComponentButton = () => {
4231
const fileName = document.getElementById('name').value
4332
const name = fileName.split('.')[0];
4433
const extension = fileName.split('.').slice(1).join('.');
45-
if (isValidFileName(fileName)) {
34+
validateFileName(fileName, projectType, componentNames, dispatch, () => {
4635
dispatch(addProjectComponent({extension: extension, name: name}));
4736
closeModal();
48-
} else if (componentNames.includes(fileName)) {
49-
dispatch(setNameError("File names must be unique."));
50-
} else if (!allowedExtensions[projectType].includes(extension)) {
51-
dispatch(setNameError(`File names must end in ${allowedExtensionsString(projectType)}.`));
52-
} else {
53-
dispatch(setNameError("Error"));
54-
}
37+
})
5538
}
5639

57-
const isValidFileName = (fileName) => {
58-
const extension = fileName.split('.').slice(1).join('.')
59-
if (allowedExtensions[projectType].includes(extension) && !componentNames.includes(fileName)) {
60-
return true;
61-
} else {
62-
return false;
63-
}
64-
}
65-
66-
const customStyles = {
67-
content: {
68-
top: '50%',
69-
left: '50%',
70-
right: 'auto',
71-
bottom: 'auto',
72-
marginRight: '-50%',
73-
transform: 'translate(-50%, -50%)',
74-
},
75-
overlay: {
76-
zIndex: 1000
77-
}
78-
};
79-
8040
return (
81-
<>
41+
<div className={`--${theme}`}>
8242
<Button buttonText={<><NewFileIcon />Add file</>} onClickHandler={showModal} className="proj-new-component-button" />
8343

8444
<Modal
8545
isOpen={modalIsOpen}
8646
onRequestClose={closeModal}
87-
style={customStyles}
8847
contentLabel="New File"
89-
appElement={document.getElementById('root') || undefined}
48+
className='modal__content'
49+
overlayClassName='modal__overlay'
50+
parentSelector={() => document.querySelector('#app')}
51+
appElement={document.getElementById('app') || undefined}
9052
>
91-
<h2>Add a new file to your project</h2>
53+
<div className='modal__header'>
54+
<h2>Add a new file to your project</h2>
55+
<button onClick={closeModal}>
56+
<CloseIcon/>
57+
</button>
58+
</div>
9259

60+
<label htmlFor='name'>Name your file</label>
9361
<NameErrorMessage />
94-
<label htmlFor='name'>Name: </label>
9562
<input type='text' name='name' id='name'></input>
96-
<Button buttonText='Cancel' onClickHandler={closeModal} />
97-
<Button buttonText='Save' onClickHandler={createComponent} />
63+
<div className='modal__buttons'>
64+
<Button className='btn--secondary' buttonText='Cancel' onClickHandler={closeModal} />
65+
<Button buttonText='Save' onClickHandler={createComponent} />
66+
</div>
9867

9968
</Modal>
100-
</>
69+
</div>
10170
);
10271
}
10372

0 commit comments

Comments
 (0)