Skip to content

Commit

Permalink
make open editor buttons linked
Browse files Browse the repository at this point in the history
  • Loading branch information
CollinBeczak committed Feb 15, 2025
1 parent 3eceec6 commit f5466cf
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 19 deletions.
45 changes: 44 additions & 1 deletion src/components/Button/Button.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
import classNames from "classnames";
import PropTypes from "prop-types";
import React from "react";
import { getEditorWindowReference, setEditorWindowReference } from "../../services/Editor/Editor";

/**
* Basic button component that includes proper styling for disabled state
* and optional link wrapping
*/
export default function Button({ className, disabled = false, children, ...otherProps }) {
export default function Button({
className,
disabled = false,
children,
href,
onClick,
...otherProps
}) {
// If href is provided, wrap the button in an anchor tag
if (href && !disabled) {
return (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
disabled={disabled}
{...otherProps}
className={classNames("mr-button", className, {
"mr-opacity-50 mr-cursor-not-allowed": disabled,
})}
onClick={(e) => {
e.preventDefault();
if (onClick) {
const existingEditor = getEditorWindowReference();
if (existingEditor && !existingEditor.closed) {
existingEditor.focus();
onClick(e);
} else {
const newWindow = window.open(href, "_blank");
setEditorWindowReference(newWindow);
onClick(e);
}
}
}}
>
{children}
</a>
);
}

return (
<button
className={classNames("mr-button", className, {
Expand All @@ -23,4 +64,6 @@ Button.propTypes = {
className: PropTypes.string,
children: PropTypes.node.isRequired,
disabled: PropTypes.bool,
href: PropTypes.string,
onClick: PropTypes.func,
};
45 changes: 40 additions & 5 deletions src/components/UserEditorSelector/UserEditorSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import _map from "lodash/map";
import _pick from "lodash/pick";
import { Component } from "react";
import { FormattedMessage } from "react-intl";
import { DEFAULT_EDITOR, Editor, editorLabels, keysByEditor } from "../../services/Editor/Editor";
import {
DEFAULT_EDITOR,
Editor,
constructEditorUri,
editorLabels,
keysByEditor,
} from "../../services/Editor/Editor";
import { OPEN_STREET_MAP } from "../../services/VisibleLayer/LayerSources";
import BusySpinner from "../BusySpinner/BusySpinner";
import Button from "../Button/Button";
import Dropdown from "../Dropdown/Dropdown";
Expand All @@ -19,6 +26,21 @@ export default class UserEditorSelector extends Component {
isSaving: false,
};

getEditorUri = (editor) => {
const { task, mapBounds, source, showMapillaryLayer, taskBundle, taskFeatureProperties } =

Check warning on line 30 in src/components/UserEditorSelector/UserEditorSelector.jsx

View workflow job for this annotation

GitHub Actions / build (18)

'taskFeatureProperties' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 30 in src/components/UserEditorSelector/UserEditorSelector.jsx

View workflow job for this annotation

GitHub Actions / build (20)

'taskFeatureProperties' is assigned a value but never used. Allowed unused vars must match /^_/u
this.props;

if (!task) return null;

const comment = task.parent?.checkinComment;
const options = {
imagery: source?.id !== OPEN_STREET_MAP ? source : undefined,
photoOverlay: showMapillaryLayer ? "mapillary" : null,
};

return constructEditorUri(editor, task, mapBounds, options, taskBundle, comment);
};

/** Process keyboard shortcuts for the edit controls */
handleKeyboardShortcuts = (event) => {
// Ignore if shortcut group is not active
Expand Down Expand Up @@ -84,7 +106,9 @@ export default class UserEditorSelector extends Component {
}

chooseEditor = (editor, closeDropdown) => {
const updatedSettings = Object.assign({}, this.props.user.settings, { defaultEditor: editor });
const updatedSettings = Object.assign({}, this.props.user.settings, {
defaultEditor: editor,
});

this.setState({ isSaving: true });
this.props
Expand All @@ -95,19 +119,22 @@ export default class UserEditorSelector extends Component {

render() {
const localizedEditorLabels = editorLabels(this.props.intl);
const currentEditor = this.currentEditor();
const editorUri = this.getEditorUri(currentEditor);

return (
<div className="mr-text-xs mr-text-white mr-flex mr-whitespace-nowrap mr-items-center">
<div className="mr-flex">
<Button
className="mr-button--green-fill mr-px-2 mr-cursor-pointer mr-text-sm"
onClick={() => this.props.pickEditor({ value: this.currentEditor() })}
onClick={() => this.props.pickEditor({ value: currentEditor })}
href={editorUri}
style={{ minWidth: "11.5rem" }}
>
{this.state.isSaving ? (
<BusySpinner />
) : (
localizedEditorLabels[keysByEditor[this.currentEditor()]] || (
localizedEditorLabels[keysByEditor[currentEditor]] || (
<FormattedMessage {...messages.editLabel} />
)
)}
Expand All @@ -128,12 +155,14 @@ export default class UserEditorSelector extends Component {
)}
dropdownContent={(dropdown) => (
<ListEditorItems
{...this.props}
allowedEditors={this.props.allowedEditors}
editorLabels={localizedEditorLabels}
activeEditor={this.currentEditor()}
activeEditor={currentEditor}
chooseEditor={this.chooseEditor}
closeDropdown={dropdown.closeDropdown}
pickEditor={this.props.pickEditor}
getEditorUri={this.getEditorUri}
/>
)}
/>
Expand All @@ -150,6 +179,7 @@ const ListEditorItems = ({
chooseEditor,
closeDropdown,
pickEditor,
getEditorUri,
}) => {
const renderEditorItems = (isAllowed) =>
_compact(
Expand All @@ -160,6 +190,8 @@ const ListEditorItems = ({
const isEditorAllowed = !allowedEditors || allowedEditors.includes(editor);
if (isEditorAllowed !== isAllowed) return null;

const editorUri = getEditorUri(editor);

return (
<li key={editor} className={classNames({ active: editor === activeEditor })}>
<a
Expand All @@ -168,6 +200,9 @@ const ListEditorItems = ({
? chooseEditor(editor, closeDropdown)
: pickEditor({ value: editor })
}
href={editorUri}
target={editorUri ? "_blank" : undefined}
rel={editorUri ? "noopener noreferrer" : undefined}
>
<div className="mr-flex mr-items-center">
{!isEditorAllowed ? (
Expand Down
53 changes: 40 additions & 13 deletions src/services/Editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,9 @@ export const editTask = function (
editorWindowReference.close();
}

if (editor === ID) {
editorWindowReference = window.open(
constructIdURI(task, mapBounds, options, taskBundle, replacedComment),
);
} else if (editor === LEVEL0) {
editorWindowReference = window.open(
constructLevel0URI(task, mapBounds, options, taskBundle, replacedComment),
);
} else if (editor === RAPID) {
editorWindowReference = window.open(
constructRapidURI(task, mapBounds, options, replacedComment),
);
}
editorWindowReference = window.open(
constructEditorUri(editor, task, mapBounds, options, taskBundle, replacedComment),
);

dispatch(editorOpened(editor, task.id, RequestStatus.success));
} else if (isJosmEditor(editor)) {
Expand Down Expand Up @@ -747,3 +737,40 @@ export const firstTruthyValue = function (object, acceptableKeys) {
const matchingKey = _find(acceptableKeys, (key) => object[key]);
return matchingKey ? object[matchingKey] : undefined;
};

/**
* Constructs the appropriate editor URI based on the editor type
*/
export const constructEditorUri = (
editor,
task,
mapBounds,
options = {},
taskBundle = null,
comment = null,
) => {
if (!task) return null;

switch (editor) {
case Editor.id:
return constructIdURI(task, mapBounds, options, taskBundle, comment);
case Editor.level0:
return constructLevel0URI(task, mapBounds, options, taskBundle, comment);
case Editor.rapid:
return constructRapidURI(task, mapBounds, options, comment);
default:
return null;
}
};

/**
* Gets the existing editor window reference
*/
export const getEditorWindowReference = () => editorWindowReference;

/**
* Sets the editor window reference
*/
export const setEditorWindowReference = (windowRef) => {
editorWindowReference = windowRef;
};

0 comments on commit f5466cf

Please sign in to comment.