Skip to content

Commit 9b67c90

Browse files
Complete Settings integration (API + UI), logging
1 parent 7eadaf2 commit 9b67c90

32 files changed

+2077
-940
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,5 @@ dist
107107
/public
108108

109109
client/src/assets/*.identifier
110+
111+
.nopalm

client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"react": "^18.2.0",
1818
"react-dom": "^18.2.0",
1919
"react-router-dom": "^6.21.1",
20+
"react-toggle-dark-mode": "^1.1.1",
2021
"tailwindcss": "^3.4.0"
2122
},
2223
"devDependencies": {

client/src/App.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ import NopalmLogo from './logos/NopalmLogo';
1717

1818
import SocialMediaLinks from './components/SocialMediaLinks';
1919

20+
import { AppProps } from './helpers/types';
21+
2022
const { Header, Content, Footer, Sider } = Layout;
2123

2224
type MenuItem = Required<MenuProps>['items'][number];
2325

2426
const routesToPages: any = {
25-
project_details: <ProjectDetails />,
26-
packages: <Packages />,
27-
settings: <Settings />,
27+
project_details: (settings) => <ProjectDetails settings={settings} />,
28+
packages: (settings) => <Packages settings={settings} />,
29+
settings: (settings, reflectUpdatedUserSettings) => <Settings settings={settings} reflectUpdatedUserSettings={reflectUpdatedUserSettings}/>,
2830
};
2931

3032
function getMenuItem(
@@ -47,11 +49,9 @@ const items: MenuItem[] = [
4749
getMenuItem('Settings', 'settings', <Link to='/settings'><SettingOutlined /></Link>),
4850
];
4951

50-
const App: React.FC = () => {
52+
const App: React.FC<AppProps> = (props) => {
5153
const [collapsed, setCollapsed] = useState(true);
52-
const {
53-
token: { borderRadiusLG }
54-
} = theme.useToken();
54+
const { token } = theme.useToken();
5555

5656
const [currentActiveRoute, setCurrentActiveRoute] = useState('project_details');
5757

@@ -80,17 +80,18 @@ const App: React.FC = () => {
8080
width: '100%',
8181
display: 'flex',
8282
alignItems: 'center',
83+
background: token.colorBgBase
8384
}}>
8485
<NopalmLogo includeTitle />
8586
</Header>
8687
<Content style={{ margin: '0 10px', padding: 0, overflow: 'initial' }}>
8788
<div
8889
style={{
8990
padding: 24,
90-
borderRadius: borderRadiusLG,
91+
borderRadius: token.borderRadiusLG,
9192
}}
9293
>
93-
{routesToPages[currentActiveRoute]}
94+
{routesToPages[currentActiveRoute](props.settings, props.reflectUpdatedUserSettings)}
9495
</div>
9596
</Content>
9697
{/* <Footer style={{

client/src/api/Dataservice.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const API_BASE_URL = 'http://localhost:8001/api';
44
// Actual
55
// const API_BASE_URL = '/api'
66

7-
import { InstalledPackageProps, ProjectDetailsProps } from '../helpers/types';
7+
import { InstalledPackageProps, ProjectDetailsProps, SettingsResultProps } from '../helpers/types';
88

99
async function getProjectDetails(): Promise<ProjectDetailsProps> {
1010
const urlPath = 'project';
@@ -53,6 +53,10 @@ async function installPackage(packageName: string, versionToInstall: string, isD
5353
})
5454
});
5555

56+
if (result.ok === false) {
57+
throw result.json();
58+
}
59+
5660
return result;
5761
}
5862

@@ -68,7 +72,7 @@ async function updatePackage(packageName: string, versionToUpdate: string | unde
6872
name: packageName
6973
};
7074

71-
if (versionToUpdate.length > 0) {
75+
if (versionToUpdate && versionToUpdate.length > 0) {
7276
packageDetailsToUpdate.version = versionToUpdate;
7377
packageDetailsToUpdate.latest = !!packageDetailsToUpdate.latest
7478
}
@@ -87,6 +91,10 @@ async function updatePackage(packageName: string, versionToUpdate: string | unde
8791
})
8892
});
8993

94+
if (result.ok === false) {
95+
throw result.json();
96+
}
97+
9098
return result;
9199
}
92100

@@ -103,6 +111,38 @@ async function uninstallPackage(packageName: string) {
103111
})
104112
});
105113

114+
if (result.ok === false) {
115+
throw result.json();
116+
}
117+
118+
return result;
119+
}
120+
121+
async function getSettings(scope: 'global' | 'local'): Promise<SettingsResultProps> {
122+
const urlPath = 'settings';
123+
124+
const result = await fetch(`${API_BASE_URL}/${urlPath}?scope=${scope}`);
125+
126+
const { settings } = await result.json();
127+
128+
return settings;
129+
}
130+
131+
async function updateSettings(scope: 'global' | 'local', settingsToUpdate: SettingsResultProps) {
132+
const urlPath = 'settings';
133+
134+
const result = await fetch(`${API_BASE_URL}/${urlPath}?scope=${scope}`, {
135+
method: 'PATCH',
136+
headers: {
137+
'Content-Type': 'application/json'
138+
},
139+
body: JSON.stringify(settingsToUpdate)
140+
});
141+
142+
if (result.ok === false) {
143+
throw result.json();
144+
}
145+
106146
return result;
107147
}
108148

@@ -112,7 +152,9 @@ const Dataservice = {
112152
searchPackages,
113153
installPackage,
114154
updatePackage,
115-
uninstallPackage
155+
uninstallPackage,
156+
getSettings,
157+
updateSettings
116158
};
117159

118160
export default Dataservice;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.accent-color-picker-container {
2+
display: grid;
3+
grid-template-columns: repeat(12, 1fr);
4+
grid-template-rows: repeat(12, 1fr);
5+
gap: 5px;
6+
7+
.accent-color {
8+
cursor: pointer;
9+
border-radius: 50%;
10+
width: 30px;
11+
height: 30px;
12+
opacity: 75%;
13+
box-sizing: border-box;
14+
transition: border 0.2s ease;
15+
}
16+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
3+
import * as antDColor from '@ant-design/colors'
4+
5+
import { theme, Tooltip } from 'antd';
6+
7+
import './AccentColorPicker.scss';
8+
9+
import { AccentColors, AccentColorPickerProps } from '../helpers/types';
10+
11+
const AccentColorPicker: React.FC<AccentColorPickerProps> = (props: AccentColorPickerProps) => {
12+
const { token } = theme.useToken();
13+
14+
return (
15+
<div className='accent-color-picker-container'>
16+
{
17+
Object.keys(AccentColors).map(accentColor => (
18+
// capitalized color name
19+
<Tooltip key={accentColor} title={`${accentColor[0].toUpperCase()}${accentColor.slice(1)}`}>
20+
<div onClick={() => props.onColorChange(accentColor)}
21+
style={{
22+
background: antDColor[accentColor].primary,
23+
boxShadow: props.selectedAccentColor === accentColor ? `0 0 2px ${antDColor[accentColor].primary}` : '',
24+
border: props.selectedAccentColor === accentColor ? `3px solid ${token.colorBgContainer}` : ''
25+
}}
26+
className='accent-color' />
27+
</Tooltip>
28+
))
29+
}
30+
</div>
31+
)
32+
};
33+
34+
export default AccentColorPicker;
Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
11
.card-main-container {
2-
display: flex;
3-
justify-content: space-between;
4-
.upgradable-tag {
5-
height: 25px;
6-
margin-left: 60%;
7-
margin-top: 43px;
2+
display: flex;
3+
justify-content: space-between;
4+
transition: text-decoration .3s ease-in-out;
5+
.package-link {
6+
&:hover {
7+
text-decoration: underline;
8+
text-underline-offset: 5px;
89
}
9-
.card-actions-container {
10-
width: 130px;
11-
.toggle-select-buttons {
12-
display: flex;
13-
}
14-
&.installed {
15-
width: 65px;
16-
}
17-
.action-buttons {
18-
display: flex;
19-
}
10+
}
11+
12+
.upgradable-tag {
13+
height: 25px;
14+
right: 6.5rem;
15+
position: absolute;
16+
top: 4.1rem;
17+
width: 110px;
18+
text-align: center;
19+
}
20+
21+
.card-actions-container {
22+
width: 130px;
23+
24+
.toggle-select-buttons {
25+
display: flex;
2026
}
27+
28+
&.installed {
29+
width: 65px;
30+
}
31+
32+
.action-buttons {
33+
display: flex;
34+
}
35+
}
2136
}

client/src/components/PackageCard.tsx

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Card, Switch, Avatar, Button, Select, Tag, Tooltip, Popconfirm, notification } from 'antd';
1+
import { Card, Switch, Avatar, Button, Select, Tag, Tooltip, Popconfirm, notification, theme as antdTheme } from 'antd';
22

33
import { UploadOutlined, DeleteFilled, PlusOutlined, MinusOutlined } from '@ant-design/icons';
44

@@ -17,12 +17,16 @@ const { Meta } = Card;
1717
const PackageCard: React.FC<PackageCardProps> = (props: PackageCardProps) => {
1818
type NotificationType = 'success' | 'info' | 'warning' | 'error';
1919

20+
const { token: theme } = antdTheme.useToken();
21+
2022
const [api, contextHolder] = notification.useNotification();
2123

2224
const [isDevPackage, setIsDevPackage] = useState(props.package.is_dev);
2325

2426
const [isDevDepToggleLoading, setIsDevDepToggleLoading] = useState(false);
2527

28+
const [packageDescription,] = useState(`${props.package.description.slice(0, 75)}${props.package.description.length >= 75 ? '...' : ''}`);
29+
2630
const [selectedVersionToInstall, setSelectedVersionToInstall] = useState(props.package.versions[0]);
2731

2832
function notify(message: string, description: string, type: NotificationType) {
@@ -39,19 +43,25 @@ const PackageCard: React.FC<PackageCardProps> = (props: PackageCardProps) => {
3943
try {
4044
await Dataservice.updatePackage(props.package.name, props.package.installed_version, checked);
4145

46+
debugger;
4247
setIsDevDepToggleLoading(false);
4348

4449
props.reRenderPackages();
4550

46-
notify('Updated the package', `Successfully updated the package as ${checked ? 'dev' : 'normal'} dependency`, 'success');
51+
return notify('Updated the package', `Successfully updated the package as ${checked ? 'dev' : 'normal'} dependency`, 'success');
4752
} catch (ex) {
53+
console.log('imma here')
54+
debugger;
4855
const msg = `Error updating the package ${props.package.name}`;
4956

5057
console.error(msg, ex);
5158

52-
notify('Updating Package', msg, 'error');
59+
return notify('Updating Package', msg, 'error');
5360
}
5461
}
62+
63+
// update the existing package - dep type
64+
props.modifyListOfPackagesToInstall(props.package.name, selectedVersionToInstall, isDevPackage)
5565
}
5666

5767
function uninstallPackage(packageName: string) {
@@ -107,18 +117,25 @@ const PackageCard: React.FC<PackageCardProps> = (props: PackageCardProps) => {
107117
{contextHolder}
108118
<div className="card-main-container">
109119
<Meta
110-
style={{ width: '90%', overflow: 'hidden' }}
120+
style={{ width: '90' }}
111121
avatar={<Avatar src={props.package.logo} />}
112122
title={
113-
<a href={props.package.homepage} target='_blank'>
123+
<a href={props.package.homepage} className="package-link"
124+
target='_blank' style={{ color: theme.colorText, textDecorationColor: theme.colorPrimary }}>
114125
{`${props.package.name} ${props.installed ? ` (${props.package.installed_version})` : ''}`}
115126
</a>
116127
}
117-
description={`${props.package.description.slice(0, 150)}${props.package.description.length >= 150 ? '...' : ''}`}
128+
description={
129+
<div title={props.package.description}>
130+
{packageDescription}
131+
</div>
132+
}
118133
/>
119134
{
120135
props.installed && (compare(props.package.installed_version || '', props.package.latest_version, '=') ? ""
121-
: <Tag className="upgradable-tag" color="success">Latest : {props.package.latest_version}</Tag>)
136+
: <Tag className="upgradable-tag" color={props.accentColor}>
137+
Latest : {props.package.latest_version}
138+
</Tag>)
122139
}
123140
<div className={`card-actions-container ${props.installed ? 'installed' : ''}`}>
124141
<div className="toggle-select-buttons">
@@ -128,20 +145,23 @@ const PackageCard: React.FC<PackageCardProps> = (props: PackageCardProps) => {
128145
value: props.package.versions[0],
129146
label: props.package.versions[0]
130147
}}
131-
onChange={(val) => setSelectedVersionToInstall(val.value)}
148+
onChange={(val) => {
149+
setSelectedVersionToInstall(val);
150+
props.modifyListOfPackagesToInstall(props.package.name, val, isDevPackage)
151+
}}
132152
style={{ textAlign: 'center', minWidth: 80, maxWidth: 80, marginRight: '10px' }}
133153
options={props.package.versions.map(ver => ({ value: ver, label: ver }))}
134154
/>
135155
)
136156
}
137157
<div className="dev-dependency">
138158
<Tooltip title={isDevPackage ? 'Toggle off to make it a regular dependency' : 'Toggle to make it a development dependency'}>
139-
<Switch
140-
disabled={!props.installed && !props.isPackageSelectedToInstall}
141-
checkedChildren="Dev" unCheckedChildren="Dev"
142-
loading={isDevDepToggleLoading}
143-
onChange={devDependencyHandler}
144-
checked={isDevPackage} ></Switch>
159+
<Switch
160+
disabled={!props.installed && !props.isPackageSelectedToInstall}
161+
checkedChildren="Dev" unCheckedChildren="Dev"
162+
loading={isDevDepToggleLoading}
163+
onChange={devDependencyHandler}
164+
checked={isDevPackage} ></Switch>
145165
</Tooltip>
146166
</div>
147167
</div>

0 commit comments

Comments
 (0)