Merge pull request #515 from Tert0/master

Add Delete All Button confirmation
This commit is contained in:
Jannis Mattheis 2022-10-08 13:42:02 +00:00 committed by GitHub
commit fb7d910a1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 67 additions and 90 deletions

View File

@ -6,7 +6,7 @@
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": false,
"jsxBracketSameLine": true,
"bracketSameLine": true,
"arrowParens": "always",
"parser": "typescript"
}
}

View File

@ -34,8 +34,7 @@ export default class AddDialog extends Component<IProps, IState> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="app-dialog"
>
id="app-dialog">
<DialogTitle id="form-dialog-title">Create an application</DialogTitle>
<DialogContent>
<DialogContentText>
@ -70,8 +69,7 @@ export default class AddDialog extends Component<IProps, IState> {
disabled={!submitEnabled}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
Create
</Button>
</div>

View File

@ -53,13 +53,11 @@ class Applications extends Component<Stores<'appStore'>> {
id="create-app"
variant="contained"
color="primary"
onClick={() => (this.createDialog = true)}
>
onClick={() => (this.createDialog = true)}>
Create Application
</Button>
}
maxWidth={1000}
>
maxWidth={1000}>
<Grid item xs={12}>
<Paper elevation={6}>
<Table id="app-table">

View File

@ -44,8 +44,7 @@ export default class UpdateDialog extends Component<IProps, IState> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="app-dialog"
>
id="app-dialog">
<DialogTitle id="form-dialog-title">Update an application</DialogTitle>
<DialogContent>
<DialogContentText>
@ -80,8 +79,7 @@ export default class UpdateDialog extends Component<IProps, IState> {
disabled={!submitEnabled}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
Update
</Button>
</div>

View File

@ -28,8 +28,7 @@ export default class AddDialog extends Component<IProps, {name: string}> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="client-dialog"
>
id="client-dialog">
<DialogTitle id="form-dialog-title">Create a client</DialogTitle>
<DialogContent>
<TextField
@ -47,16 +46,14 @@ export default class AddDialog extends Component<IProps, {name: string}> {
<Button onClick={fClose}>Cancel</Button>
<Tooltip
placement={'bottom-start'}
title={submitEnabled ? '' : 'name is required'}
>
title={submitEnabled ? '' : 'name is required'}>
<div>
<Button
className="create"
disabled={!submitEnabled}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
Create
</Button>
</div>

View File

@ -48,12 +48,10 @@ class Clients extends Component<Stores<'clientStore'>> {
id="create-client"
variant="contained"
color="primary"
onClick={() => (this.showDialog = true)}
>
onClick={() => (this.showDialog = true)}>
Create Client
</Button>
}
>
}>
<Grid item xs={12}>
<Paper elevation={6}>
<Table id="client-table">

View File

@ -41,8 +41,7 @@ export default class UpdateDialog extends Component<IProps, IState> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="client-dialog"
>
id="client-dialog">
<DialogTitle id="form-dialog-title">Update a Client</DialogTitle>
<DialogContent>
<DialogContentText>
@ -69,8 +68,7 @@ export default class UpdateDialog extends Component<IProps, IState> {
disabled={!submitEnabled}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
Update
</Button>
</div>

View File

@ -23,8 +23,7 @@ export default function ConfirmDialog({title, text, fClose, fOnSubmit}: IProps)
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
className="confirm-dialog"
>
className="confirm-dialog">
<DialogTitle id="form-dialog-title">{title}</DialogTitle>
<DialogContent>
<DialogContentText>{text}</DialogContentText>
@ -38,8 +37,7 @@ export default function ConfirmDialog({title, text, fClose, fOnSubmit}: IProps)
autoFocus
color="primary"
variant="contained"
className="confirm"
>
className="confirm">
Yes
</Button>
</DialogActions>

View File

@ -16,8 +16,7 @@ export const ConnectionErrorBanner = ({height, retry, message}: ConnectionErrorB
width: '100%',
zIndex: 1300,
position: 'relative',
}}
>
}}>
<Typography align="center" variant="h6" style={{lineHeight: `${height}px`}}>
{message}{' '}
<Button variant="outlined" onClick={retry}>

View File

@ -36,8 +36,7 @@ class ScrollUpButton extends Component {
display: this.state.display,
opacity: this.state.opacity,
}}
onClick={this.scrollUp}
>
onClick={this.scrollUp}>
<KeyboardArrowUp />
</Fab>
);

View File

@ -31,8 +31,7 @@ class SettingsDialog extends Component<IProps & Stores<'currentUser'>> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="changepw-dialog"
>
id="changepw-dialog">
<DialogTitle id="form-dialog-title">Change Password</DialogTitle>
<DialogContent>
<TextField
@ -55,8 +54,7 @@ class SettingsDialog extends Component<IProps & Stores<'currentUser'>> {
disabled={pass.length === 0}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
Change
</Button>
</div>

View File

@ -106,8 +106,7 @@ class Header extends Component<IProps> {
</Link>
<a
href={'https://github.com/gotify/server/releases/tag/v' + version}
className={classes.link}
>
className={classes.link}>
<Typography variant="button" color="inherit">
@{version}
</Typography>
@ -123,8 +122,7 @@ class Header extends Component<IProps> {
href="https://github.com/gotify/server"
className={classes.link}
target="_blank"
rel="noopener noreferrer"
>
rel="noopener noreferrer">
<IconButton color="inherit">
<GitHubIcon />
</IconButton>

View File

@ -57,8 +57,7 @@ class Navigation extends Component<
onClick={() => setNavOpen(false)}
className={`${classes.link} item`}
to={'/messages/' + app.id}
key={app.id}
>
key={app.id}>
<ListItem button>
<ListItemText primary={app.name} />
</ListItem>
@ -79,8 +78,7 @@ class Navigation extends Component<
classes={{root: classes.root, paper: classes.drawerPaper}}
navOpen={navOpen}
setNavOpen={setNavOpen}
id="message-navigation"
>
id="message-navigation">
<div className={classes.toolbar} />
<Link className={classes.link} to="/" onClick={() => setNavOpen(false)}>
<ListItem button disabled={!loggedIn} className="all">
@ -96,8 +94,7 @@ class Navigation extends Component<
onClick={() => {
requestPermission();
this.setState({showRequestNotification: false});
}}
>
}}>
Enable Notifications
</Button>
) : null}

View File

@ -11,6 +11,7 @@ import {inject, Stores} from '../inject';
import {observable} from 'mobx';
import ReactInfinite from 'react-infinite';
import {IMessage} from '../types';
import ConfirmDialog from '../common/ConfirmDialog';
type IProps = RouteComponentProps<{id: string}>;
@ -22,6 +23,8 @@ interface IState {
class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>, IState> {
@observable
private heights: Record<string, number> = {};
@observable
private deleteAll = false;
private static appId(props: IProps) {
if (props === undefined) {
@ -70,8 +73,7 @@ class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>,
disabled={!hasMessages}
color="primary"
onClick={() => messagesStore.refreshByApp(appId)}
style={{marginRight: 5}}
>
style={{marginRight: 5}}>
Refresh
</Button>
<Button
@ -79,21 +81,20 @@ class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>,
variant="contained"
disabled={!hasMessages}
color="primary"
onClick={() => messagesStore.removeByApp(appId)}
>
onClick={() => {
this.deleteAll = true;
}}>
Delete All
</Button>
</div>
}
>
}>
{hasMessages ? (
<div style={{width: '100%'}} id="messages">
<ReactInfinite
key={appId}
useWindowAsScrollContainer
preloadBatchSize={window.innerHeight * 3}
elementHeight={messages.map((m) => this.heights[m.id] || 1)}
>
elementHeight={messages.map((m) => this.heights[m.id] || 1)}>
{messages.map(this.renderMessage)}
</ReactInfinite>
@ -108,6 +109,15 @@ class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>,
) : (
this.label('No messages')
)}
{this.deleteAll && (
<ConfirmDialog
title="Confirm Delete"
text={'Delete all messages?'}
fClose={() => (this.deleteAll = false)}
fOnSubmit={() => messagesStore.removeByApp(appId)}
/>
)}
</DefaultPage>
);
}

View File

@ -79,8 +79,7 @@ class PluginDetailView extends Component<IProps & Stores<'pluginStore'>, IState>
name={'Configurer'}
description={'This is the configuration panel for this plugin.'}
icon={Build}
refresh={this.refreshConfigurer.bind(this)}
>
refresh={this.refreshConfigurer.bind(this)}>
<ConfigurerPanel
pluginInfo={pluginInfo}
initialConfig={
@ -100,8 +99,7 @@ class PluginDetailView extends Component<IProps & Stores<'pluginStore'>, IState>
name={'Displayer'}
description={'This is the information generated by the plugin.'}
refresh={this.refreshDisplayer.bind(this)}
icon={Subject}
>
icon={Subject}>
<DisplayerPanel
pluginInfo={pluginInfo}
displayText={
@ -147,8 +145,7 @@ const PanelWrapper: React.FC<IPanelWrapperProps> = ({
style={{float: 'right'}}
onClick={() => {
refresh();
}}
>
}}>
<Refresh />
</Button>
) : null}
@ -202,8 +199,7 @@ class ConfigurerPanel extends Component<IConfigurerPanelProps, {unsavedChanges:
this.props.save(newConfig!).then(() => {
this.setState({unsavedChanges: null});
});
}}
>
}}>
<Typography variant="button">Save</Typography>
</Button>
</div>
@ -264,8 +260,7 @@ class PluginInfo extends Component<{pluginInfo: IPlugin}> {
href={url}
target="_blank"
rel="noopener noreferrer"
className="custom-route"
>
className="custom-route">
{url}
</a>
))(`${config.get('url')}plugin/${id}/custom/${token}/`)}

View File

@ -42,8 +42,7 @@ class SnackBarHandler extends Component<Stores<'snackManager'>> {
key="close"
aria-label="Close"
color="inherit"
onClick={this.closeCurrentSnack}
>
onClick={this.closeCurrentSnack}>
<Close />
</IconButton>
}

View File

@ -219,6 +219,8 @@ describe('Messages', () => {
it('deletes all linux messages', async () => {
await navigate('Linux');
await page.click('#delete-all');
await page.waitForSelector(selector.$confirmDialog.selector());
await page.click(selector.$confirmDialog.button('.confirm'));
await page.waitForSelector('#delete-all:disabled');
await expectMessages({
all: [windows3, backup1, windows1],
@ -250,6 +252,9 @@ describe('Messages', () => {
it('deletes all messages', async () => {
await navigate('All Messages');
await page.click('#delete-all');
await page.waitForSelector(selector.$confirmDialog.selector());
await page.click(selector.$confirmDialog.button('.confirm'));
await page.waitForSelector('#delete-all:disabled');
await expectMessages({
all: [],
windows: [],
@ -269,6 +274,8 @@ describe('Messages', () => {
it('deletes all backup messages and navigates to all messages', async () => {
await navigate('Backup');
await page.click('#delete-all');
await page.waitForSelector(selector.$confirmDialog.selector());
await page.click(selector.$confirmDialog.button('.confirm'));
await page.waitForSelector('#delete-all:disabled');
await navigate('All Messages');
await createMessage(backup3, backupServerToken);

View File

@ -44,8 +44,7 @@ export default class AddEditDialog extends Component<IProps, IState> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="add-edit-user-dialog"
>
id="add-edit-user-dialog">
<DialogTitle id="form-dialog-title">
{isEdit ? 'Edit ' + this.props.name : 'Add a user'}
</DialogTitle>
@ -91,16 +90,14 @@ export default class AddEditDialog extends Component<IProps, IState> {
? ''
: 'password is required'
: 'name is required'
}
>
}>
<div>
<Button
className="save-create"
disabled={!passPresent || !namePresent}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
{isEdit ? 'Save' : 'Create'}
</Button>
</div>

View File

@ -52,8 +52,7 @@ class Login extends Component<Stores<'currentUser'>> {
color="primary"
disabled={!!this.props.currentUser.connectionErrorMessage}
style={{marginTop: 15, marginBottom: 5}}
onClick={this.login}
>
onClick={this.login}>
Login
</Button>
</form>
@ -81,8 +80,7 @@ class Login extends Component<Stores<'currentUser'>> {
id="register"
variant="contained"
color="primary"
onClick={() => (this.registerDialog = true)}
>
onClick={() => (this.registerDialog = true)}>
Register
</Button>
);

View File

@ -41,8 +41,7 @@ export default class RegistrationDialog extends Component<IProps, IState> {
open={true}
onClose={fClose}
aria-labelledby="form-dialog-title"
id="add-edit-user-dialog"
>
id="add-edit-user-dialog">
<DialogTitle id="form-dialog-title">Registration</DialogTitle>
<DialogContent>
<TextField
@ -75,16 +74,14 @@ export default class RegistrationDialog extends Component<IProps, IState> {
? ''
: 'password is required'
: 'name is required'
}
>
}>
<div>
<Button
className="save-create"
disabled={!passPresent || !namePresent}
onClick={submitAndClose}
color="primary"
variant="contained"
>
variant="contained">
Register
</Button>
</div>

View File

@ -75,12 +75,10 @@ class Users extends Component<WithStyles<'wrapper'> & Stores<'userStore'>> {
id="create-user"
variant="contained"
color="primary"
onClick={() => (this.createDialog = true)}
>
onClick={() => (this.createDialog = true)}>
Create User
</Button>
}
>
}>
<Grid item xs={12}>
<Paper elevation={6}>
<Table id="user-table">