Skip to content

Commit ae4b6d1

Browse files
Mobile view and wording (#151)
* feat(ui): simplified titles and adjusted some wording * style(ui): simplified some views for mobile * style(ui): make job table responsive for mobile * style(ui): login button gap * style(ui): dont hide mobile columns * fix: method return type
1 parent 2b36f86 commit ae4b6d1

File tree

11 files changed

+67
-59
lines changed

11 files changed

+67
-59
lines changed

ui/src/components/menu/Menu.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Tabs, TabPane } from '@douyinfe/semi-ui';
44

55
import { useLocation } from 'react-router';
66
import { IconUser, IconTerminal, IconSetting } from '@douyinfe/semi-icons';
7+
import './Menu.less';
78

89
function parsePathName(name) {
910
const split = name.split('/').filter((s) => s.length !== 0);
@@ -14,7 +15,12 @@ const TopMenu = function TopMenu({ isAdmin }) {
1415
const history = useHistory();
1516
const location = useLocation();
1617
return (
17-
<Tabs type="line" activeKey={parsePathName(location.pathname)} onTabClick={(key) => history.push(key)}>
18+
<Tabs
19+
className="menu"
20+
type="line"
21+
activeKey={parsePathName(location.pathname)}
22+
onTabClick={(key) => history.push(key)}
23+
>
1824
<TabPane
1925
itemKey="/jobs"
2026
tab={

ui/src/components/menu/Menu.less

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.menu {
2+
margin-top: 3rem;
3+
}

ui/src/components/table/JobTable.jsx

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import React from 'react';
33
import { Button, Empty, Table, Switch } from '@douyinfe/semi-ui';
44
import { IconDelete, IconEdit, IconHistogram } from '@douyinfe/semi-icons';
55
import { IllustrationNoResult, IllustrationNoResultDark } from '@douyinfe/semi-illustrations';
6+
7+
import './JobTable.less';
8+
69
const empty = (
710
<Empty
811
image={<IllustrationNoResult />}
912
darkModeImage={<IllustrationNoResultDark />}
10-
description={'No jobs available'}
13+
description={'No jobs available.'}
1114
/>
1215
);
1316

@@ -25,25 +28,25 @@ export default function JobTable({ jobs = {}, onJobRemoval, onJobStatusChanged,
2528
},
2629
},
2730
{
28-
title: 'Job Name',
31+
title: 'Name',
2932
dataIndex: 'name',
3033
},
3134
{
32-
title: 'Number of findings',
35+
title: 'Findings',
3336
dataIndex: 'numberOfFoundListings',
3437
render: (value) => {
3538
return value || 0;
3639
},
3740
},
3841
{
39-
title: 'Active provider',
42+
title: 'Providers',
4043
dataIndex: 'provider',
4144
render: (value) => {
4245
return value.length || 0;
4346
},
4447
},
4548
{
46-
title: 'Active notification adapter',
49+
title: 'Notification adapters',
4750
dataIndex: 'notificationAdapter',
4851
render: (value) => {
4952
return value.length || 0;
@@ -54,19 +57,9 @@ export default function JobTable({ jobs = {}, onJobRemoval, onJobStatusChanged,
5457
dataIndex: 'tools',
5558
render: (_, job) => {
5659
return (
57-
<div style={{ float: 'right' }}>
58-
<Button
59-
type="primary"
60-
icon={<IconHistogram />}
61-
onClick={() => onJobInsight(job.id)}
62-
style={{ marginRight: '1rem' }}
63-
/>
64-
<Button
65-
type="secondary"
66-
icon={<IconEdit />}
67-
onClick={() => onJobEdit(job.id)}
68-
style={{ marginRight: '1rem' }}
69-
/>
60+
<div className="interactions">
61+
<Button type="primary" icon={<IconHistogram />} onClick={() => onJobInsight(job.id)} />
62+
<Button type="secondary" icon={<IconEdit />} onClick={() => onJobEdit(job.id)} />
7063
<Button type="danger" icon={<IconDelete />} onClick={() => onJobRemoval(job.id)} />
7164
</div>
7265
);

ui/src/components/table/JobTable.less

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.interactions {
2+
float: right;
3+
display: flex;
4+
flex-direction: column;
5+
gap: 1rem;
6+
}
7+
8+
@media (min-width: 768px) {
9+
.interactions {
10+
flex-direction: initial;
11+
}
12+
}

ui/src/components/table/NotificationAdapterTable.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ export default function NotificationAdapterTable({ notificationAdapter = [], onR
77
return (
88
<Table
99
pagination={false}
10-
empty={<Empty description="No Data" />}
10+
empty={<Empty description="No notification adapters found." />}
1111
columns={[
1212
{
13-
title: 'Notification Adapter Name',
13+
title: 'Name',
1414
dataIndex: 'name',
1515
},
1616

ui/src/components/table/ProviderTable.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ export default function ProviderTable({ providerData = [], onRemove } = {}) {
77
return (
88
<Table
99
pagination={false}
10-
empty={<Empty description="No Provider available" />}
10+
empty={<Empty description="No providers found." />}
1111
columns={[
1212
{
13-
title: 'Provider Name',
13+
title: 'Name',
1414
dataIndex: 'name',
1515
},
1616
{
17-
title: 'Provider Url',
17+
title: 'URL',
1818
dataIndex: 'url',
1919
render: (_, data) => {
2020
return (

ui/src/components/table/UserTable.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const empty = (
99
<Empty
1010
image={<IllustrationNoResult />}
1111
darkModeImage={<IllustrationNoResultDark />}
12-
description={'No user available'}
12+
description={'No users found.'}
1313
/>
1414
);
1515

ui/src/views/generalSettings/GeneralSettings.jsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,28 +71,20 @@ const GeneralSettings = function GeneralSettings() {
7171

7272
const nullOrEmpty = (val) => val == null || val.length === 0;
7373

74-
const throwMessage = (message, type) => {
75-
if (type === 'error') {
76-
Toast.error(message);
77-
} else {
78-
Toast.success(message);
79-
}
80-
};
81-
8274
const onStore = async () => {
8375
if (nullOrEmpty(interval)) {
84-
throwMessage('Interval may not be empty.', 'error');
76+
Toast.error('Interval may not be empty.');
8577
return;
8678
}
8779
if (nullOrEmpty(port)) {
88-
throwMessage('Port may not be empty.', 'error');
80+
Toast.error('Port may not be empty.');
8981
return;
9082
}
9183
if (
9284
(!nullOrEmpty(workingHourFrom) && nullOrEmpty(workingHourTo)) ||
9385
(nullOrEmpty(workingHourFrom) && !nullOrEmpty(workingHourTo))
9486
) {
95-
throwMessage('Working hours to and from must be set if either to or from has been set before.', 'error');
87+
Toast.error('Working hours to and from must be set if either to or from has been set before.');
9688
return;
9789
}
9890
try {
@@ -109,13 +101,13 @@ const GeneralSettings = function GeneralSettings() {
109101
} catch (exception) {
110102
console.error(exception);
111103
if (exception?.json?.message != null) {
112-
throwMessage(exception.json.message, 'error');
104+
Toast.error(exception.json.message);
113105
} else {
114-
throwMessage('Error while trying to store settings.', 'error');
106+
Toast.error('Error while trying to store settings.');
115107
}
116108
return;
117109
}
118-
throwMessage('Settings stored successfully. We will reload your browser in 3 seconds.', 'success');
110+
Toast.success('Settings stored successfully. We will reload your browser in 3 seconds.');
119111
setTimeout(() => {
120112
location.reload();
121113
}, 3000);

ui/src/views/jobs/mutation/JobMutation.jsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export default function JobMutator() {
3838
const dispatch = useDispatch();
3939

4040
const isSavingEnabled = () => {
41-
return notificationAdapterData.length > 0 && providerData.length > 0 && name != null && name.length > 0;
41+
return Boolean(notificationAdapterData.length && providerData.length && name);
4242
};
4343

4444
const mutateJob = async () => {
@@ -105,13 +105,13 @@ export default function JobMutator() {
105105
</SegmentPart>
106106
<Divider margin="1rem" />
107107
<SegmentPart
108-
name="Provider"
108+
name="Providers"
109109
icon="briefcase"
110-
helpText={
111-
'A provider is essentially the service (Immowelt etc.) that Fredy is using to search for new listings. When adding a new provider, Fredy will open a new tab pointing ' +
112-
'to the website of this provider. You have to adjust your search parameter and click on "Search". If the results are being shown, copy the browser url. This is the url, Fredy will use ' +
113-
'to search for new listings.'
114-
}
110+
helpText={`
111+
A provider is essentially the service (e.g. ImmoScout24, Kleinanzeigen) that Fredy searches for new listings.
112+
Fredy will open a new tab pointing to the website of this provider. You have to adjust your search parameter
113+
and click on "Search". If the results are being shown, copy the browser URL in here.
114+
`}
115115
>
116116
<Button
117117
type="primary"
@@ -132,7 +132,7 @@ export default function JobMutator() {
132132
<Divider margin="1rem" />
133133
<SegmentPart
134134
icon="bell"
135-
name="Notification Adapter"
135+
name="Notification Adapters"
136136
helpText="Fredy supports multiple ways to notify you about new findings. These are called notification adapter. You can chose between email, Telegram etc."
137137
>
138138
<Button
@@ -172,7 +172,7 @@ export default function JobMutator() {
172172
<SegmentPart
173173
icon="play circle outline"
174174
name="Job activation"
175-
helpText="Whether or not the job is activated. If it is not activated, it will be ignored when Fredy checks for new listings."
175+
helpText="Whether or not the job is activated. Inactive jobs will be ignored when Fredy checks for new listings."
176176
>
177177
<Switch className="jobMutation__spaceTop" onChange={(checked) => setEnabled(checked)} checked={enabled} />
178178
</SegmentPart>

ui/src/views/login/Login.jsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Logo from '../../components/logo/Logo';
55
import { xhrPost } from '../../services/xhr';
66
import { useHistory } from 'react-router';
77
import { useDispatch, useSelector } from 'react-redux';
8-
import { Input, Button, Banner } from '@douyinfe/semi-ui';
8+
import { Input, Button, Banner, Toast } from '@douyinfe/semi-ui';
99

1010
import './login.less';
1111
import { IconUser, IconLock } from '@douyinfe/semi-icons';
@@ -27,20 +27,24 @@ export default function Login() {
2727
}, []);
2828

2929
const tryLogin = async () => {
30-
if (username.length === 0 || password.length === 0) {
30+
if (!username?.trim() || !password) {
3131
setError('Username and password are mandatory.');
3232
return;
3333
}
34+
setError(null);
35+
3436
try {
3537
await xhrPost('/api/login', {
36-
username,
38+
username: username.trim(),
3739
password,
3840
});
39-
setError(null);
4041
} catch (Exception) {
41-
setError('Login not successful...');
42+
Toast.error('Login unsuccessful…');
4243
return;
4344
}
45+
46+
Toast.success('Login successful!');
47+
4448
await dispatch.user.getCurrentUser();
4549
history.push('/jobs');
4650
};
@@ -58,7 +62,6 @@ export default function Login() {
5862
placeholder="Username"
5963
value={username}
6064
showClear
61-
style={{ marginTop: error ? '1rem' : '4rem' }}
6265
autoFocus
6366
onChange={(value) => setUserName(value)}
6467
onKeyPress={async (e) => {
@@ -74,7 +77,6 @@ export default function Login() {
7477
prefix={<IconLock />}
7578
value={password}
7679
placeholder="Password"
77-
style={{ marginTop: '2rem' }}
7880
onChange={(value) => setPassword(value)}
7981
onKeyPress={async (e) => {
8082
if (e.key === 'Enter') {
@@ -83,10 +85,10 @@ export default function Login() {
8385
}}
8486
/>
8587

86-
<Button type="primary" onClick={tryLogin} theme="solid" style={{ marginTop: '3rem' }}>
88+
<Button type="primary" onClick={tryLogin} theme="solid" style={{ marginTop: '1rem' }}>
8789
Login
8890
</Button>
89-
<br />
91+
9092
{demoMode && (
9193
<Banner
9294
fullMode={true}

0 commit comments

Comments
 (0)