Skip to content

Commit

Permalink
Don’t scroll up when showing confirm modals (#5371)
Browse files Browse the repository at this point in the history
* Don’t scroll up when showing confirm modals

* changelog

* Update CHANGELOG.unreleased.md

* pr feedback
  • Loading branch information
fm3 authored Apr 12, 2021
1 parent a14f50f commit 28e4980
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 57 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Fixed a bug where tasks created from existing volume annotations that did not have a specified bounding box were broken. [#5362](https://github.com/scalableminds/webknossos/pull/5361)
- Fixed a bug in Safari which could cause an error message (which is safe to ignore). [#5373](https://github.com/scalableminds/webknossos/pull/5373)
- Fixed artifacts in screenshots near the dataset border. [#5324](https://github.com/scalableminds/webknossos/pull/5324)
- Fixed a bug where the page would scroll up unexpectedly when showing various confirm modals. [#5371](https://github.com/scalableminds/webknossos/pull/5371)

### Removed
-
Expand Down
9 changes: 4 additions & 5 deletions frontend/javascripts/admin/auth/authentication_modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import messages from "messages";
import features from "features";

import SpotlightRegistrationForm from "admin/auth/spotlight_registration_form";
import LinkButton from "components/link_button";
import RegistrationForm from "./registration_form";
import LoginForm from "./login_form";

Expand Down Expand Up @@ -53,16 +54,14 @@ export default function AuthenticationModal({
{step === "Register" ? (
<React.Fragment>
{registrationForm}
<a href="#" onClick={showLogin}>
Already have an account? Login instead.
</a>
<LinkButton onClick={showLogin}>Already have an account? Login instead.</LinkButton>
</React.Fragment>
) : (
<React.Fragment>
<LoginForm layout="vertical" onLoggedIn={() => onLoggedIn(false)} hideFooter />
<a href="#" onClick={showRegister}>
<LinkButton onClick={showRegister}>
Don&apos;t have an account yet? Register here.
</a>
</LinkButton>
</React.Fragment>
)}
</Modal>
Expand Down
5 changes: 3 additions & 2 deletions frontend/javascripts/admin/dataset/dataset_add_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import DatasetAddNeuroglancerView from "admin/dataset/dataset_add_neuroglancer_v
import DatasetAddBossView from "admin/dataset/dataset_add_boss_view";
import DatasetUploadView from "admin/dataset/dataset_upload_view";
import SampleDatasetsModal from "dashboard/dataset/sample_datasets_modal";
import LinkButton from "components/link_button";
import features from "features";
import { getDatastores } from "admin/admin_rest_api";
import renderIndependently from "libs/render_independently";
Expand Down Expand Up @@ -168,9 +169,9 @@ const DatasetAddView = ({ history, activeUser }: PropsWithRouter) => {
<div style={{ textAlign: "center" }}>
<p>or</p>
<p>
<a href="#" onClick={() => renderSampleDatasetsModal(activeUser, history)}>
<LinkButton onClick={() => renderSampleDatasetsModal(activeUser, history)}>
Add a Sample Dataset
</a>
</LinkButton>
</p>
</div>
<Modal
Expand Down
11 changes: 4 additions & 7 deletions frontend/javascripts/admin/onboarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import React, { type Node } from "react";

import type { APIUser, APIDataStore } from "types/api_flow_types";
import Store, { type OxalisState } from "oxalis/store";
import LinkButton from "components/link_button";
import { getDatastores, sendInvitesForOrganization } from "admin/admin_rest_api";
import DatasetImportView from "dashboard/dataset/dataset_import_view";
import DatasetUploadView from "admin/dataset/dataset_upload_view";
Expand Down Expand Up @@ -440,11 +441,7 @@ class OnboardingView extends React.PureComponent<Props, State> {
<OptionCard
header="Skip"
icon={<ClockCircleOutlined />}
action={
<a href="#" onClick={this.advanceStep}>
Skip this step
</a>
}
action={<LinkButton onClick={this.advanceStep}>Skip this step</LinkButton>}
height={170}
>
You can always do this later!
Expand Down Expand Up @@ -477,9 +474,9 @@ class OnboardingView extends React.PureComponent<Props, State> {
formats and upload processes webKnossos supports.
</FeatureCard>
<FeatureCard header="User & Team Management" icon={<TeamOutlined />}>
<a onClick={() => this.setState({ isInviteModalVisible: true })} href="#">
<LinkButton onClick={() => this.setState({ isInviteModalVisible: true })}>
Invite users
</a>{" "}
</LinkButton>{" "}
<InviteUsersModal
visible={this.state.isInviteModalVisible}
handleVisibleChange={isInviteModalVisible => this.setState({ isInviteModalVisible })}
Expand Down
5 changes: 3 additions & 2 deletions frontend/javascripts/admin/scripts/script_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import _ from "lodash";
import type { APIScript, APIUser } from "types/api_flow_types";
import { getScripts, deleteScript } from "admin/admin_rest_api";
import { handleGenericError } from "libs/error_handling";
import LinkButton from "components/link_button";
import Persistence from "libs/persistence";
import * as Utils from "libs/utils";
import messages from "messages";
Expand Down Expand Up @@ -190,10 +191,10 @@ class ScriptListView extends React.PureComponent<Props, State> {
Edit
</Link>
<br />
<a href="#" onClick={_.partial(this.deleteScript, script)}>
<LinkButton onClick={_.partial(this.deleteScript, script)}>
<DeleteOutlined />
Delete
</a>
</LinkButton>
</span>
)}
/>
Expand Down
5 changes: 3 additions & 2 deletions frontend/javascripts/admin/task/task_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { handleGenericError } from "libs/error_handling";
import FormattedDate from "components/formatted_date";
import Persistence from "libs/persistence";
import TaskAnnotationView from "admin/task/task_annotation_view";
import LinkButton from "components/link_button";
import { downloadTasksAsCSV } from "admin/task/task_create_form_view";
import TaskSearchForm, {
type QueryObject,
Expand Down Expand Up @@ -342,10 +343,10 @@ class TaskListView extends React.PureComponent<Props, State> {
</AsyncLink>
) : null}
<br />
<a href="#" onClick={_.partial(this.deleteTask, task)}>
<LinkButton onClick={_.partial(this.deleteTask, task)}>
<DeleteOutlined />
Delete
</a>
</LinkButton>
</span>
)}
/>
Expand Down
5 changes: 3 additions & 2 deletions frontend/javascripts/admin/tasktype/task_type_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AsyncLink } from "components/async_clickables";
import type { APITaskType } from "types/api_flow_types";
import { getTaskTypes, deleteTaskType, downloadNml } from "admin/admin_rest_api";
import { handleGenericError } from "libs/error_handling";
import LinkButton from "components/link_button";
import Persistence from "libs/persistence";
import * as Utils from "libs/utils";
import messages from "messages";
Expand Down Expand Up @@ -274,10 +275,10 @@ class TaskTypeListView extends React.PureComponent<Props, State> {
Download
</AsyncLink>
<br />
<a href="#" onClick={_.partial(this.deleteTaskType, taskType)}>
<LinkButton onClick={_.partial(this.deleteTaskType, taskType)}>
<DeleteOutlined />
Delete
</a>
</LinkButton>
</span>
)}
/>
Expand Down
5 changes: 3 additions & 2 deletions frontend/javascripts/admin/team/team_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import _ from "lodash";
import type { APITeam } from "types/api_flow_types";
import { getEditableTeams, deleteTeam } from "admin/admin_rest_api";
import { handleGenericError } from "libs/error_handling";
import LinkButton from "components/link_button";
import CreateTeamModal from "admin/team/create_team_modal_view";
import Persistence from "libs/persistence";
import * as Utils from "libs/utils";
Expand Down Expand Up @@ -157,10 +158,10 @@ class TeamListView extends React.PureComponent<Props, State> {
title="Action"
key="actions"
render={(__, script: APITeam) => (
<a href="#" onClick={_.partial(this.deleteTeam, script)}>
<LinkButton onClick={_.partial(this.deleteTeam, script)}>
<DeleteOutlined />
Delete
</a>
</LinkButton>
)}
/>
</Table>
Expand Down
13 changes: 7 additions & 6 deletions frontend/javascripts/admin/user/user_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type { APIUser, APITeamMembership, ExperienceMap } from "types/api_flow_t
import { InviteUsersModal } from "admin/onboarding";
import type { OxalisState } from "oxalis/store";
import { enforceActiveUser } from "oxalis/model/accessors/user_accessor";
import LinkButton from "components/link_button";
import { getEditableUsers, updateUser } from "admin/admin_rest_api";
import { stringToColor } from "libs/format_utils";
import EditableTextLabel from "oxalis/view/components/editable_text_label";
Expand Down Expand Up @@ -201,10 +202,10 @@ class UserListView extends React.PureComponent<PropsWithRouter, State> {
<Row key={user.id} gutter={16}>
<Col span={6}>{`${user.lastName}, ${user.firstName} (${user.email}) `}</Col>
<Col span={4}>
<a href="#" onClick={() => this.activateUser(user)}>
<LinkButton onClick={() => this.activateUser(user)}>
<UserAddOutlined />
Activate User
</a>
</LinkButton>
</Col>
</Row>
))}
Expand Down Expand Up @@ -510,16 +511,16 @@ class UserListView extends React.PureComponent<PropsWithRouter, State> {
{// eslint-disable-next-line no-nested-ternary
user.isActive ? (
this.props.activeUser.isAdmin ? (
<a href="#" onClick={() => this.deactivateUser(user)}>
<LinkButton onClick={() => this.deactivateUser(user)}>
<UserDeleteOutlined />
Deactivate User
</a>
</LinkButton>
) : null
) : (
<a href="#" onClick={() => this.activateUser(user)}>
<LinkButton onClick={() => this.activateUser(user)}>
<UserAddOutlined />
Activate User
</a>
</LinkButton>
)}
</span>
)}
Expand Down
10 changes: 10 additions & 0 deletions frontend/javascripts/components/link_button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @flow
import { Button } from "antd";
import * as React from "react";

// This component should be used instead of <a href="#" onClick={} />.
// One advantage of this component is that clicking the link button won't scroll
// up (which would happen with <a ... /> if not handled otherwise)
export default function LinkButton(props: Object) {
return <Button type="link" {...props} className="link-button" />;
}
17 changes: 9 additions & 8 deletions frontend/javascripts/dashboard/dashboard_task_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from "admin/admin_rest_api";
import { enforceActiveUser } from "oxalis/model/accessors/user_accessor";
import { handleGenericError } from "libs/error_handling";
import LinkButton from "components/link_button";
import FormattedDate from "components/formatted_date";
import Persistence from "libs/persistence";
import Request from "libs/request";
Expand Down Expand Up @@ -257,10 +258,10 @@ class DashboardTaskListView extends React.PureComponent<PropsWithRouter, State>
<br />
{isAdmin || this.props.isAdminView ? (
<div>
<a href="#" onClick={() => this.openTransferModal(annotation.id)}>
<LinkButton onClick={() => this.openTransferModal(annotation.id)}>
<TeamOutlined />
Transfer
</a>
</LinkButton>
<br />
</div>
) : null}
Expand All @@ -277,23 +278,23 @@ class DashboardTaskListView extends React.PureComponent<PropsWithRouter, State>
Download
</AsyncLink>
<br />
<a href="#" onClick={() => this.resetTask(annotation)}>
<LinkButton onClick={() => this.resetTask(annotation)}>
<RollbackOutlined />
Reset
</a>
</LinkButton>
<br />
<a href="#" onClick={() => this.cancelAnnotation(annotation)}>
<LinkButton onClick={() => this.cancelAnnotation(annotation)}>
<DeleteOutlined />
Reset and Cancel
</a>
</LinkButton>
<br />
</div>
) : null}
{this.props.isAdminView ? null : (
<a href="#" onClick={() => this.confirmFinish(task)}>
<LinkButton onClick={() => this.confirmFinish(task)}>
<CheckCircleOutlined />
Finish
</a>
</LinkButton>
)}
</div>
);
Expand Down
29 changes: 10 additions & 19 deletions frontend/javascripts/dashboard/dataset/dataset_import_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
} from "types/api_flow_types";
import type { DatasetConfiguration, OxalisState } from "oxalis/store";
import DatasetCacheProvider, { datasetCache } from "dashboard/dataset/dataset_cache_provider";
import LinkButton from "components/link_button";
import { diffObjects, jsonStringify } from "libs/utils";
import {
getDataset,
Expand Down Expand Up @@ -353,21 +354,17 @@ class DatasetImportView extends React.PureComponent<Props, State> {
<div>
The current datasource-properties.json on the server seems to have invalid or missing
properties. <br />
<a
href="#"
<LinkButton
onClick={() =>
showJSONModal("Suggested datasource-properties.json", inferredDataSource)
}
>
Here
</a>{" "}
</LinkButton>{" "}
are suggested settings from webKnossos. But be aware that properties like the voxel size
or the largest segment id cannot be detected correctly. <br />
If you want to apply those settings, click{" "}
<a href="#" onClick={applySuggestedSettings}>
here
</a>
.
<LinkButton onClick={applySuggestedSettings}>here</LinkButton>.
</div>
);
} else if (
Expand All @@ -392,8 +389,7 @@ class DatasetImportView extends React.PureComponent<Props, State> {
additional information about the dataset that could be inferred. The original
datasource-properties.json settings can be seen below in the advanced version. The
JSON-encoded difference between the current and the suggested version can be inspected{" "}
<a
href="#"
<LinkButton
onClick={() =>
showJSONModal(
"Difference to suggested datasource-properties.json",
Expand All @@ -402,22 +398,17 @@ class DatasetImportView extends React.PureComponent<Props, State> {
}
>
here
</a>
</LinkButton>
.<br />
Click{" "}
<a href="#" onClick={applySuggestedSettings}>
here
</a>{" "}
to set the suggested JSON settings. This will replace the current settings in the form
with{" "}
<a
href="#"
Click <LinkButton onClick={applySuggestedSettings}>here</LinkButton> to set the suggested
JSON settings. This will replace the current settings in the form with{" "}
<LinkButton
onClick={() =>
showJSONModal("Suggested datasource-properties.json", inferredDataSource)
}
>
these settings
</a>
</LinkButton>
.
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import Store, {
type Tracing,
type Task,
} from "oxalis/store";
import LinkButton from "components/link_button";
import Toast from "libs/toast";
import * as Utils from "libs/utils";
import api from "oxalis/api/internal_api";
Expand Down Expand Up @@ -612,7 +613,7 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps, State> {

return (
<Tooltip title="Open Dialog to Downsample Volume Data">
<a href="#" onClick={this.showDownsampleVolumeModal}>
<LinkButton onClick={this.showDownsampleVolumeModal}>
<img
src="/assets/images/icon-downsampling.svg"
style={{
Expand All @@ -625,7 +626,7 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps, State> {
}}
alt="Resolution Icon"
/>
</a>
</LinkButton>
</Tooltip>
);
};
Expand Down
11 changes: 11 additions & 0 deletions frontend/stylesheets/antd_overwrites.less
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,14 @@ label.ant-checkbox-wrapper {
flex-direction: column;
line-height: 13px;
}

// Custom component `LinkButton` renders a button that looks like a link.
// Antd’s `button type="link"` only gets us halfway there, though, hence, this:
.link-button {
border: 0;
padding: 0;
height: initial;
}
.link-button > .anticon + span, .link-button > span + .anticon {
margin-left: initial;
}

0 comments on commit 28e4980

Please sign in to comment.