Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Update shot delete confirmation dialog. (#4186)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenba committed Apr 25, 2018
1 parent 320d442 commit eb6d850
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 28 deletions.
9 changes: 9 additions & 0 deletions locales/en-US/server.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,15 @@ shotIndexPageNextPage =
shotIndexNoExpirationSymbol =
.title = This shot does not expire
## Delete Confirmation Dialog

shotDeleteConfirmationMessage = Are you sure you want to delete this shot?
shotDeleteCancel = Cancel
.title = Cancel
shotDeleteConfirm = Delete
.title = Delete
## Metrics page
## All metrics strings are optional for translation

Expand Down
96 changes: 96 additions & 0 deletions server/src/delete-shot-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const React = require("react");
const PropTypes = require("prop-types");
const { Localized } = require("fluent-react/compat");

exports.DeleteShotButton = class DeleteShotButton extends React.Component {
constructor(props) {
super(props);
this.elRef = React.createRef();
this.trashButtonRef = React.createRef();
this.state = {confirmationPanelOpen: false}
this.maybeCloseDeleteConfirmation = this.maybeCloseDeleteConfirmation.bind(this);
}

componentDidUpdate() {
if (this.state.confirmationPanelOpen) {
document.addEventListener("mousedown", this.maybeCloseDeleteConfirmation);
} else {
document.removeEventListener("mousedown", this.maybeCloseDeleteConfirmation);
}
}

componentWillUnmount() {
document.removeEventListener("mousedown", this.maybeCloseDeleteConfirmation);
}

onClickDelete(e) {
e.stopPropagation();
e.preventDefault();
this.props.clickDeleteHandler && this.props.clickDeleteHandler();
this.setState({confirmationPanelOpen: true});
}

onConfirmDelete(e) {
e.stopPropagation();
this.props.confirmDeleteHandler && this.props.confirmDeleteHandler();
this.setState({confirmationPanelOpen: false});
}

onCancelDelete(e) {
e.stopPropagation();
this.props.cancelDeleteHandler && this.props.cancelDeleteHandler();
this.setState({confirmationPanelOpen: false});
}

maybeCloseDeleteConfirmation(e) {
if (this.elRef.current === e.target || this.elRef.current.contains(e.target)) {
return;
}

this.onCancelDelete(e);
}

render() {
let rightAlign = "";
if (this.trashButtonRef.current && (this.trashButtonRef.current.getBoundingClientRect().left + 320) > document.body.scrollWidth) {
rightAlign = "right-align";
}

let confirmationPanel = null, deletePanelOpenClass = null;
if (this.state.confirmationPanelOpen) {
confirmationPanel = <div className={`delete-confirmation-dialog ${rightAlign}`} ref={this.elRef}>
<div className="triangle"><div className="triangle-inner"></div></div>
<Localized id="shotDeleteConfirmationMessage">
<div className="delete-confirmation-message">Are you sure you want to delete this shot?</div>
</Localized>
<div className="delete-confirmation-buttons">
<Localized id="shotDeleteCancel">
<button className="button primary" title="Cancel" onClick={ this.onCancelDelete.bind(this) }>Cancel</button>
</Localized>
<Localized id="shotDeleteConfirm">
<button className="button secondary" title="Delete" onClick={ this.onConfirmDelete.bind(this) }>Delete</button>
</Localized>
</div>
</div>;
deletePanelOpenClass = "active";
}

return (
<div className="delete-shot-button">
<Localized id="shotPageDeleteButton">
<button className={`button transparent trash ${deletePanelOpenClass}`}
title="Delete this shot permanently"
onClick={this.onClickDelete.bind(this)}
ref={this.trashButtonRef}></button>
</Localized>
{ confirmationPanel }
</div>
);
}
}

exports.DeleteShotButton.propTypes = {
clickDeleteHandler: PropTypes.func,
confirmDeleteHandler: PropTypes.func,
cancelDeleteHandler: PropTypes.func
}
26 changes: 15 additions & 11 deletions server/src/pages/shot/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { Localized } = require("fluent-react/compat");
const { Footer } = require("../../footer-view");
const sendEvent = require("../../browser-send-event.js");
const { ShareButton } = require("../../share-buttons");
const { DeleteShotButton } = require("../../delete-shot-button");
const { TimeDiff } = require("./time-diff");
const reactruntime = require("../../reactruntime");
const { Editor } = require("./editor");
Expand Down Expand Up @@ -182,15 +183,17 @@ class Body extends React.Component {
this.setState({closeBanner: true});
}

onClickDelete(e) {
clickDeleteHandler() {
sendEvent("start-delete", "navbar", {useBeacon: true});
const confirmMessage = document.getElementById("shotPageConfirmDelete").textContent;
if (window.confirm(confirmMessage)) {
sendEvent("delete", "popup-confirm", {useBeacon: true});
this.props.controller.deleteShot(this.props.shot);
} else {
sendEvent("cancel-delete", "popup-confirm");
}
}

confirmDeleteHandler() {
sendEvent("delete", "popup-confirm", {useBeacon: true});
this.props.controller.deleteShot(this.props.shot);
}

cancelDeleteHandler() {
sendEvent("cancel-delete", "popup-confirm");
}

onClickFlag(e) {
Expand Down Expand Up @@ -346,9 +349,10 @@ class Body extends React.Component {
let editButton;
const highlight = this.props.highlightEditButton ? <div className="edit-highlight" onClick={ this.onClickEdit.bind(this) } onMouseOver={ this.onMouseOverHighlight.bind(this) } onMouseOut={ this.onMouseOutHighlight.bind(this) }></div> : null;
if (this.props.isOwner) {
trashOrFlagButton = <Localized id="shotPageDeleteButton">
<button className="button transparent trash" title="Delete this shot permanently" onClick={ this.onClickDelete.bind(this) }></button>
</Localized>;
trashOrFlagButton = <DeleteShotButton
clickDeleteHandler={ this.clickDeleteHandler.bind(this) }
confirmDeleteHandler={ this.confirmDeleteHandler.bind(this) }
cancelDeleteHandler={ this.cancelDeleteHandler.bind(this) } />;
editButton = <Localized id="shotPageEditButton">
<button className="button transparent edit" title="Edit this image" onClick={ this.onClickEdit.bind(this) } ref={(edit) => { this.editButton = edit }}></button>
</Localized>;
Expand Down
45 changes: 28 additions & 17 deletions server/src/pages/shotindex/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Masonry = require("react-masonry-component");
const { Localized } = require("fluent-react/compat");
const { isValidClipImageUrl } = require("../../../shared/shot");
const { getThumbnailDimensions } = require("../../../shared/thumbnailGenerator");
const { DeleteShotButton } = require("../../delete-shot-button");

class Head extends React.Component {

Expand Down Expand Up @@ -331,8 +332,17 @@ class Card extends React.Component {
neverExpireIndicator = <Localized id="shotIndexNoExpirationSymbol"><div className="never-expires" title=""></div></Localized>
}

const deleteConfirmationClass = this.state.deletePanelOpen ? "panel-open" : "";

return (
<div className={`shot ${this.getClipType(shot.thumbnail, clip._image.dimensions)} ${this.state.panelOpen} ${this.isDeleted()}`} key={shot.id}>
<div className={
`shot
${this.getClipType(shot.thumbnail, clip._image.dimensions)}
${this.state.panelOpen}
${deleteConfirmationClass}
${this.isDeleted()}`
}
key={shot.id}>
<a href={shot.viewUrl} onClick={this.onOpen.bind(this, shot.viewUrl)}>
<div className="shot-image-container">
<img src={imageUrl} />
Expand All @@ -355,9 +365,10 @@ class Card extends React.Component {
title="Download the shot image" ref={downloadButton => this.downloadButton = downloadButton} />
</Localized>
<ShareButton setPanelState={this.setPanelState.bind(this)} abTests={this.props.abTests} clipUrl={imageUrl} shot={shot} isOwner={this.props.isOwner} staticLink={this.props.staticLink} isExtInstalled={this.props.isExtInstalled} />
<Localized id="shotPageDeleteButton">
<button className="button transparent trash" title="Delete this shot permanently" onClick={ this.onClickDelete.bind(this, shot) } ref={trashButton => this.trashButton = trashButton} />
</Localized>
<DeleteShotButton
clickDeleteHandler={this.clickDeleteHandler.bind(this)}
confirmDeleteHandler={this.confirmDeleteHandler.bind(this, shot)}
cancelDeleteHandler={this.cancelDeleteHandler.bind(this)} />
</div>
{neverExpireIndicator}
</div>
Expand Down Expand Up @@ -426,20 +437,20 @@ class Card extends React.Component {
return title;
}

onClickDelete(shot, event) {
event.stopPropagation();
event.preventDefault();
clickDeleteHandler(event) {
sendEvent("start-delete", "my-shots", {useBeacon: true});
const confirmMessage = document.getElementById("shotIndexPageConfirmShotDelete").textContent;
if (window.confirm(confirmMessage)) {
sendEvent("delete", "my-shots-popup-confirm", {useBeacon: true});
this.setState({deleted: true});
controller.deleteShot(shot);
} else {
sendEvent("cancel-delete", "my-shots-popup-confirm");
}
this.trashButton.blur();
return false;
this.setState({ deletePanelOpen: true });
}

confirmDeleteHandler(shot, event) {
sendEvent("delete", "my-shots-popup-confirm", { useBeacon: true });
controller.deleteShot(shot);
this.setState({ deleted: true, deletePanelOpen: false });
}

cancelDeleteHandler(event) {
this.setState({ deletePanelOpen: false });
sendEvent("cancel-delete", "my-shots-popup-confirm");
}

onClickDownload() {
Expand Down
8 changes: 8 additions & 0 deletions static/css/frame.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import "partials/partials";
@import "partials/delete-confirmation";

.frame-header {
@include respond-to("medium") {
Expand Down Expand Up @@ -77,6 +78,13 @@
}
}

.delete-confirmation-dialog {
&.right-align {
top: 48px;
}
}


.back-to-index {
@include respond-to("small") {
background-position: left -5px center;
Expand Down
4 changes: 4 additions & 0 deletions static/css/partials/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
padding: 0 8px;
}

&.active {
background-color: $light-active;
}

&.tiny {
font-size: 14px;
height: 26px;
Expand Down
66 changes: 66 additions & 0 deletions static/css/partials/_delete-confirmation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.delete-shot-button {
position: relative;
}

.delete-confirmation-dialog {
background-color: #fff;
border: 1px solid #c7c7c7 ;
border-radius: 3px;
box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.25), 0 0 0 0 rgba(0, 0, 0, 0.29), inset 0 0 0 0 #fff;
min-height: 114px;
min-width: 320px;
padding: 18px;
position: absolute;
left: 3px;
top: 47px;
z-index: 3;

.triangle {
position: absolute;
width: 0;
height: 0;
border-left: 9px solid transparent;
border-right: 9px solid transparent;
border-bottom: 15px solid $light-border;
top: -15px;
left: 8px;

.triangle-inner {
position: absolute;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-bottom: 13px solid #fff;
left: -8px;
top: 2px;
}
}
.delete-confirmation-message {
font-size: 15px;
}
.delete-confirmation-buttons {
display: flex;
justify-content: space-between;
margin-top: 18px;

button {
&.primary {
width: 135px;
height: 40px;
}
&.secondary {
border: 1px solid #c7c7c7;
width: 133px;
height: 38px;
}
}
}

&.right-align {
left: -281px;
.triangle {
left: 292px;
}
}
}
1 change: 1 addition & 0 deletions static/css/shot-index.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import "partials/partials";
@import "partials/delete-confirmation";

//Shot index page styles

Expand Down

0 comments on commit eb6d850

Please sign in to comment.