Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #417

Merged
merged 30 commits into from
Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f13895c
wip: events
rvpanoz Jul 23, 2019
a752622
Hotfix/theme (#391)
rvpanoz Jul 26, 2019
5287500
topBar
rvpanoz Jul 26, 2019
05a5404
Feat/top bar handlers (#393)
rvpanoz Jul 28, 2019
d05d8bf
chore: fix issues
rvpanoz Jul 28, 2019
3d48c20
Feat/notifications (#395)
rvpanoz Jul 29, 2019
eb503a2
fix: layout
rvpanoz Jul 29, 2019
7f1b0b2
fix: layout
rvpanoz Jul 30, 2019
73bf74b
Feat/notification handlers (#398)
rvpanoz Jul 30, 2019
8909111
chore: cleanup components and styles
rvpanoz Jul 30, 2019
57f88cd
Feat/topbar (#400)
rvpanoz Jul 31, 2019
34387b6
Hotfix/tables selection (#402)
rvpanoz Jul 31, 2019
ca44915
Fix/layout issues (#403)
rvpanoz Aug 1, 2019
e976d82
Hotfix/notifications (#404)
rvpanoz Aug 1, 2019
b136981
Notifications/design flow (#405)
rvpanoz Aug 3, 2019
cf3cad8
chore: error message when installation fails
rvpanoz Aug 5, 2019
f8cf12a
Feat/sidebar (#407)
rvpanoz Aug 11, 2019
bda47a5
fix: general issues
rvpanoz Aug 11, 2019
94ee1a7
Hotfix/npm audit doctor (#409)
rvpanoz Aug 11, 2019
8778d82
chore: update dependencies, fix issues
rvpanoz Aug 12, 2019
3d7db51
fix: labels
rvpanoz Aug 12, 2019
c02fb27
Feat/mpm dedupe (#412)
rvpanoz Aug 12, 2019
767b34c
chore: update images
rvpanoz Aug 12, 2019
9e627e1
chore: bump version
rvpanoz Aug 12, 2019
2ad468f
chore: update readme
rvpanoz Aug 12, 2019
ad73767
Hotfix/general issues (#415)
rvpanoz Aug 14, 2019
9e33d83
chore: update deps, fix logging
rvpanoz Aug 15, 2019
3ba44ae
Merge pull request #416 from rvpanoz/feat/promise-to-observables
rvpanoz Aug 15, 2019
a655542
chore: lint
rvpanoz Aug 15, 2019
7b0479e
Merge pull request #418 from rvpanoz/hotfix/lint
rvpanoz Aug 15, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
331 changes: 197 additions & 134 deletions app/cli/manager.js

Large diffs are not rendered by default.

Empty file modified app/cli/npm/tooling/dedupe.js
100644 → 100755
Empty file.
8 changes: 1 addition & 7 deletions app/cli/npm/uninstall.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable prefer-promise-reject-errors */
/* eslint-disable compat/compat */

/**
Expand All @@ -12,16 +11,11 @@ const uninstall = options => {

function getNames() {
if (multiple && Array.isArray(packages)) {

// do not uninstall npm
return packages.filter(pkgName => pkgName !== 'npm');
}

if (!name && !multiple) {
return Promise.reject(
'npm[uninstall] package name parameter must be given'
);
}

return name;
}

Expand Down
37 changes: 12 additions & 25 deletions app/cli/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
/* eslint-disable import/prefer-default-export */

import log from 'electron-log';
import { concat } from 'rxjs'
import { catchError } from 'rxjs/operators';
import manager from './manager';

/**
Expand All @@ -11,36 +13,21 @@ import manager from './manager';
*/

const runCommand = (options, callback) => {
const { cmd, ...rest } = options || {};
const { cmd, ...rest } = options;

// create an array of observables
const combine = () =>
cmd.map((command, idx) => {
try {
const runner = manager[command];
const result = runner(rest, idx);
const runner = manager[command];
const result$ = runner(rest, idx);

return result; // returns a promise
} catch (error) {
log.error(error);
throw new Error(error);
}
return result$.pipe(
catchError(error => log.error(error))
);
});

const tasks = combine();

tasks
.reduce(
(promiseChain, currentTask) =>
promiseChain.then(chainResults =>
currentTask.then(currentResult => [...chainResults, currentResult])
),
Promise.resolve([])
)
.then(results => results.map(result => callback(result)))
.catch(error => {
log.error(error);
return Promise.reject(error);
});
};
// subscribe to observables in order as previous completes
concat(...combine()).subscribe(result => callback(result));
}

export default runCommand;
94 changes: 94 additions & 0 deletions app/components/views/notifications/NotificationsList.js~master
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { withStyles } from '@material-ui/styles';
import { Table, TableBody, Grid, Paper, Divider } from '@material-ui/core';

import { HelperText } from 'components/common';
import { iMessage } from 'commons/utils';
import TableHeader from './Header';
import NotificationItem from './NotificationItem';
import ToolbarView from './Toolbar';

import styles from './styles/list';

const NotificationsList = ({
classes,
notifications,
selected,
loading,
handleSelectAll,
handleSelectOne,
handleInstall
}) => {
const noNotifications = !notifications || notifications.length === 0;

return (
<Grid container>
<Grid
item
md={10}
lg={10}
xl={10}
className={classes.transition}
>
{noNotifications && (
<HelperText text={iMessage('info', 'noNotifications')} />
)}
{!noNotifications && (
<Paper elevation={2}>
<div className={classes.toolbar}>
<ToolbarView
title={iMessage('title', 'notifications')}
total={notifications.length}
selected={selected}
notifications={notifications}
handleInstall={handleInstall}
/>
</div>
<Divider />
<div className={classes.tableWrapper}>
<Table
aria-labelledby="notifications-list"
className={cn(classes.table, {
[classes.hasFilterBlur]: loading
})}
>
<TableHeader
total={notifications.length}
handleSelectAll={handleSelectAll}
selected={selected}
sortBy="Required"
sortDir="asc"
/>
<TableBody>
{notifications.slice(0, 10).map(notification => (
<NotificationItem
{...notification}
key={notification.id}
selected={selected}
handleSelectOne={handleSelectOne}
handleSelectAll={handleSelectAll}
/>
))}
</TableBody>
</Table>
</div>
</Paper>
)}
</Grid>
</Grid>
);
};

NotificationsList.propTypes = {
classes: PropTypes.objectOf(PropTypes.string).isRequired,
notifications: PropTypes.arrayOf(PropTypes.object).isRequired,
selected: PropTypes.arrayOf(PropTypes.string).isRequired,
handleSelectAll: PropTypes.func.isRequired,
handleSelectOne: PropTypes.func.isRequired,
handleInstall: PropTypes.func.isRequired,
loading: PropTypes.bool
};

export default withStyles(styles)(NotificationsList);
54 changes: 54 additions & 0 deletions app/components/views/sidebar/Sidebar.js~master
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import { string, objectOf, func, bool, object, arrayOf } from 'prop-types';
import { withStyles } from '@material-ui/styles';

import { AppTabs, AppLogo } from 'components/common/';
import {
PackagesTab,
ActionsTab,
HistoryTab
} from 'components/views/sidebar/tabs';
import styles from './styles/sidebar';

const Sidebar = ({
classes,
loading,
mode,
history,
loadDirectory,
updatedAt,
tabPackagesData,
installPackagesFromJson,
dedupe
}) => (
<div className={classes.root}>
<AppLogo />
<AppTabs>
<PackagesTab
items={tabPackagesData}
updatedAt={updatedAt}
loading={loading}
/>
<ActionsTab onInstallPackagesFromJson={installPackagesFromJson} onDedupe={dedupe} mode={mode} loading={loading} />
<HistoryTab
directories={history}
onClick={loadDirectory}
loading={loading}
/>
</AppTabs>
</div>
);

Sidebar.propTypes = {
classes: objectOf(string).isRequired,
mode: string.isRequired,
loading: bool,
history: arrayOf(object),
loadDirectory: func.isRequired,
installPackagesFromJson: func.isRequired,
dedupe: func.isRequired,
updatedAt: string,
tabPackagesData: arrayOf(object)
};

export default withStyles(styles)(Sidebar);
145 changes: 145 additions & 0 deletions app/components/views/topBar/TopBar.js~master
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import React from 'react';
import { objectOf, func, bool, arrayOf, object, string } from 'prop-types';
import { withStyles } from '@material-ui/styles';
import { AppBar, Toolbar, Tooltip, Badge, IconButton } from '@material-ui/core';

import NotificationsActiveIcon from '@material-ui/icons/NotificationsActiveOutlined';
import NotificationsIcon from '@material-ui/icons/NotificationsOutlined';
import SettingsIcon from '@material-ui/icons/SettingsOutlined';
import AddIcon from '@material-ui/icons/AddOutlined';
import ArchiveIcon from '@material-ui/icons/ArchiveOutlined';
import SecurityIcon from '@material-ui/icons/SecurityOutlined';
import LocalHospitalIcon from '@material-ui/icons/LocalHospitalOutlined';

import { SearchBox } from 'components/common';
import { iMessage } from 'commons/utils';
import styles from './styles/topBar';

const Topbar = ({
classes,
notifications,
mode,
loading,
onLoadDirectory,
onInitFlow,
onShowSettings,
setActivePage
}) => (
<AppBar
className={classes.root}
position="static"
elevation={0}
color="inherit"
>
<Toolbar disableGutters>
<div className={classes.actions}>
<Toolbar
disableGutters
classes={{
root: classes.root
}}
>
<Tooltip title={iMessage('title', 'loadDirectory')}>
<div>
<IconButton
classes={{
root: classes.button
}}
disableRipple
disabled={loading}
onClick={onLoadDirectory}
color="inherit"
>
<ArchiveIcon className={classes.icon} />
</IconButton>
</div>
</Tooltip>
<Tooltip title={iMessage('title', 'createPackageJson')}>
<div>
<IconButton
classes={{
root: classes.button
}}
disableRipple
color="inherit"
disabled={loading}
onClick={onInitFlow}
>
<AddIcon className={classes.icon} />
</IconButton>
</div>
</Tooltip>
<Tooltip title={iMessage('info', 'npmAuditInfo')}>
<div>
<IconButton
classes={{
root: classes.button
}}
color="inherit"
disableRipple
onClick={() => setActivePage('audit')}
disabled={loading || mode === 'global'}
>
<SecurityIcon className={classes.icon} />
</IconButton>
</div>
</Tooltip>
<Tooltip title={iMessage('info', 'npmDoctorInfo')}>
<div>
<IconButton
color="inherit"
classes={{
root: classes.button
}}
disableRipple
disabled={loading}
onClick={() => setActivePage('doctor')}
>
<LocalHospitalIcon className={classes.icon} />
</IconButton>
</div>
</Tooltip>
<Tooltip title={iMessage('title', 'notifications')}>
<div>
<IconButton
color="inherit"
classes={{
root: classes.button
}}
disableRipple
disabled={loading}
onClick={() => setActivePage('notifications')}
>
<Badge
badgeContent={notifications ? notifications.length : 0}
showZero
color="secondary"
>
{notifications && notifications.length ? <NotificationsActiveIcon /> : <NotificationsIcon />}
</Badge>
</IconButton>
</div>
</Tooltip>
</Toolbar>
</div>
<div className={classes.flexGrow} />
<SearchBox />
<IconButton className={classes.button} color="inherit" onClick={onShowSettings}>
<SettingsIcon />
</IconButton>
</Toolbar>
</AppBar>
);

Topbar.propTypes = {
classes: objectOf(string).isRequired,
mode: string.isRequired,
loading: bool,
notifications: arrayOf(object),
onLoadDirectory: func,
setActivePage: func,
onInitFlow: func,
onShowSettings: func
};

export default withStyles(styles)(Topbar);
17 changes: 17 additions & 0 deletions app/components/views/topBar/styles/topBar.js~master
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const styles = theme => ({
root: {
zIndex: 'auto',
boxShadow: 'none'
},
actions: {
paddingLeft: theme.spacing(1) / 2
},
flexGrow: {
flexGrow: 1
},
button: {
marginLeft: theme.spacing(1)
}
});

export default styles;
Loading