initial
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
.vrts-alert-actions {
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
&__trigger {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 0.5rem;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
content: "";
|
||||
background: #f6f7f7;
|
||||
border-radius: 2px;
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-visible,
|
||||
&[aria-expanded="true"] {
|
||||
|
||||
&::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% - 5px);
|
||||
right: 0;
|
||||
background: #fff;
|
||||
border: 1px solid #c3c4c7;
|
||||
box-shadow: 0 3px 28px 0 rgba(0, 0, 0, 0.15);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
min-width: 200px;
|
||||
transform: translateY(-4px);
|
||||
will-change: transform, opacity, visibility;
|
||||
transition: all 0.15s;
|
||||
|
||||
&[aria-hidden="false"] {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__dropdown-action {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
white-space: nowrap;
|
||||
padding: 12px 15px;
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: color 0.2s;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
color: var(--vrts-admin-theme-color);
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
&__modal {
|
||||
|
||||
.vrts-modal__content {
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.vrts-modal__content-inner {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
&-action {
|
||||
margin-top: 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
&-action-success {
|
||||
color: #00a32a;
|
||||
font-size: 0.75rem;
|
||||
margin-left: 0.5rem;
|
||||
display: none;
|
||||
|
||||
&.is-active {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
margin: 0;
|
||||
display: none;
|
||||
|
||||
&.is-active {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.description {
|
||||
color: #757575;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
use Vrts\Core\Utilities\Url_Helpers;
|
||||
|
||||
?>
|
||||
<vrts-alert-actions class="vrts-alert-actions">
|
||||
<button type="button" data-vrts-dropdown-open class="vrts-alert-actions__trigger" aria-expanded="false" aria-controls="vrts-alert-actions-dropdown">
|
||||
<?php vrts()->icon( 'more-horizontal' ); ?>
|
||||
</button>
|
||||
<div id="vrts-alert-actions-dropdown" class="vrts-alert-actions__dropdown" aria-hidden="true">
|
||||
<button data-vrts-loading="false" data-vrts-action-state="<?php echo esc_attr( $data['alert']->is_false_positive ? 'secondary' : 'primary' ); ?>" data-vrts-alert-id="<?php echo esc_attr( $data['alert']->id ); ?>" data-vrts-alert-action="false-positive" class="vrts-alert-actions__dropdown-action vrts-action-button">
|
||||
<span class="vrts-action-button__icons">
|
||||
<span class="vrts-action-button__icon" data-vrts-action-state-primary><?php vrts()->icon( 'flag-outline' ); ?></span>
|
||||
<span class="vrts-action-button__icon" data-vrts-action-state-secondary><?php vrts()->icon( 'flag' ); ?></span>
|
||||
<span class="vrts-action-button__spinner"><?php vrts()->icon( 'spinner' ); ?></span>
|
||||
</span>
|
||||
<span class="vrts-action-button__info" data-vrts-action-state-primary><?php esc_html_e( 'Flag as false positive', 'visual-regression-tests' ); ?></span>
|
||||
<span class="vrts-action-button__info" data-vrts-action-state-secondary><?php esc_html_e( 'Unflag as false positive', 'visual-regression-tests' ); ?></span>
|
||||
</button>
|
||||
<button data-vrts-loading="false" data-vrts-action-state="<?php echo esc_attr( $data['alert']->alert_state ? 'secondary' : 'primary' ); ?>" data-vrts-alert-id="<?php echo esc_attr( $data['alert']->id ); ?>" data-vrts-alert-action="read-status" class="vrts-alert-actions__dropdown-action vrts-action-button">
|
||||
<span class="vrts-action-button__icons">
|
||||
<span class="vrts-action-button__icon" data-vrts-action-state-secondary><?php vrts()->icon( 'email-unread' ); ?></span>
|
||||
<span class="vrts-action-button__icon" data-vrts-action-state-primary><?php vrts()->icon( 'email-read' ); ?></span>
|
||||
<span class="vrts-action-button__spinner"><?php vrts()->icon( 'spinner' ); ?></span>
|
||||
</span>
|
||||
<span class="vrts-action-button__info" data-vrts-action-state-primary><?php esc_html_e( 'Mark as read', 'visual-regression-tests' ); ?></span>
|
||||
<span class="vrts-action-button__info" data-vrts-action-state-secondary><?php esc_html_e( 'Mark as unread', 'visual-regression-tests' ); ?></span>
|
||||
</button>
|
||||
<button type="button" class="vrts-alert-actions__dropdown-action" data-a11y-dialog-show="vrts-modal-hide-elements">
|
||||
<?php vrts()->icon( 'hidden' ); ?>
|
||||
<?php esc_html_e( 'Hide elements', 'visual-regression-tests' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<vrts-modal id="vrts-modal-hide-elements" class="vrts-modal vrts-alert-actions__modal" aria-hidden="true">
|
||||
<div class="vrts-modal__overlay" data-a11y-dialog-hide></div>
|
||||
<div class="vrts-modal__content" role="document">
|
||||
<button type="button" class="vrts-modal__close" data-a11y-dialog-hide aria-label="<?php esc_attr_e( 'Close', 'visual-regression-tests' ); ?>"></button>
|
||||
<h2 class="vrts-modal__title">
|
||||
<?php vrts()->icon( 'hidden' ); ?>
|
||||
<?php esc_html_e( 'Hide elements', 'visual-regression-tests' ); ?>
|
||||
</h2>
|
||||
<div class="vrts-modal__content-inner">
|
||||
<form data-vrts-hide-elements-form action="<?php echo esc_url( Url_Helpers::get_page_url( 'runs' ) ); ?>" method="put">
|
||||
<input type="hidden" name="post_id" value="<?php echo esc_attr( $data['alert']->post_id ); ?>">
|
||||
<input type="hidden" name="test_id" value="<?php echo esc_attr( $data['test_settings']['test_id'] ); ?>">
|
||||
<textarea class="widefat" name="hide_css_selectors" placeholder="<?php esc_html_e( 'e.g.: .lottie, #ads', 'visual-regression-tests' ); ?>" rows="4"><?php echo esc_html( $data['test_settings']['hide_css_selectors'] ); ?></textarea>
|
||||
<p class="description"><?php esc_html_e( 'Hide elements on snapshots to exclude them from comparisons.', 'visual-regression-tests' ); ?></p>
|
||||
<div class="vrts-alert-actions__modal-action">
|
||||
<button type="submit" class="button button-primary"><?php esc_html_e( 'Save Changes', 'visual-regression-tests' ); ?></button>
|
||||
<span class="spinner"></span>
|
||||
<span class="vrts-alert-actions__modal-action-success"><?php esc_html_e( 'Saved successfully.', 'visual-regression-tests' ); ?></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</vrts-modal>
|
||||
</vrts-alert-actions>
|
||||
@@ -0,0 +1,198 @@
|
||||
import Dropdown from '../../assets/scripts/dropdown';
|
||||
|
||||
class VrtsAlertActions extends window.HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.dropdown = null;
|
||||
this.setAsReadTimeout = null;
|
||||
this.resolveElements();
|
||||
this.bindFunctions();
|
||||
this.bindEvents();
|
||||
}
|
||||
|
||||
resolveElements() {
|
||||
this.$actionButtons = this.querySelectorAll(
|
||||
'[data-vrts-alert-action]'
|
||||
);
|
||||
this.$hideElementsForm = this.querySelector(
|
||||
'[data-vrts-hide-elements-form]'
|
||||
);
|
||||
this.$hideElementsModal = document.getElementById(
|
||||
'vrts-modal-hide-elements'
|
||||
);
|
||||
this.$spinner = this.querySelector( '.spinner' );
|
||||
this.$success = this.querySelector(
|
||||
'.vrts-alert-actions__modal-action-success'
|
||||
);
|
||||
}
|
||||
|
||||
bindFunctions() {
|
||||
this.onActionClick = this.onActionClick.bind( this );
|
||||
this.onHideElementsFormSubmit =
|
||||
this.onHideElementsFormSubmit.bind( this );
|
||||
this.onHideElementsModalClose =
|
||||
this.onHideElementsModalClose.bind( this );
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.$actionButtons.forEach( ( item ) => {
|
||||
item.addEventListener( 'click', this.onActionClick );
|
||||
} );
|
||||
this.$hideElementsForm.addEventListener(
|
||||
'submit',
|
||||
this.onHideElementsFormSubmit
|
||||
);
|
||||
this.$hideElementsModal.addEventListener(
|
||||
'hide',
|
||||
this.onHideElementsModalClose
|
||||
);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.dropdown = Dropdown( this );
|
||||
this.setAsReadOnView();
|
||||
}
|
||||
|
||||
setAsReadOnView() {
|
||||
this.$actionButtons.forEach( ( action ) => {
|
||||
const isReadStatusAction =
|
||||
action.getAttribute( 'data-vrts-alert-action' ) ===
|
||||
'read-status';
|
||||
const isUnread =
|
||||
action.getAttribute( 'data-vrts-action-state' ) === 'primary';
|
||||
|
||||
if ( isReadStatusAction && isUnread ) {
|
||||
this.setAsReadTimeout = setTimeout( () => {
|
||||
action.click();
|
||||
}, 1000 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
onHideElementsFormSubmit( e ) {
|
||||
e.preventDefault();
|
||||
const $form = e.currentTarget;
|
||||
const formData = new window.FormData( $form );
|
||||
const postId = formData.get( 'post_id' );
|
||||
|
||||
this.$spinner.classList.add( 'is-active' );
|
||||
this.$success.classList.remove( 'is-active' );
|
||||
|
||||
fetch( `${ window.vrts_admin_vars.rest_url }/tests/post/${ postId }`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'X-WP-Nonce': window.vrts_admin_vars.rest_nonce,
|
||||
},
|
||||
body: new URLSearchParams( formData ),
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
return response.json();
|
||||
} )
|
||||
.then( () => {
|
||||
this.$spinner.classList.remove( 'is-active' );
|
||||
this.$success.classList.add( 'is-active' );
|
||||
} );
|
||||
}
|
||||
|
||||
onHideElementsModalClose() {
|
||||
this.$success.classList.remove( 'is-active' );
|
||||
}
|
||||
|
||||
onActionClick( e ) {
|
||||
const $el = e.currentTarget;
|
||||
const isLoading = $el.getAttribute( 'data-vrts-loading' ) === 'true';
|
||||
const state = $el.getAttribute( 'data-vrts-action-state' );
|
||||
const isPrimary = state === 'primary';
|
||||
|
||||
if ( isLoading ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const action = $el.getAttribute( 'data-vrts-alert-action' );
|
||||
const id = $el.getAttribute( 'data-vrts-alert-id' );
|
||||
|
||||
this.handleAction( action, $el, id, isPrimary );
|
||||
}
|
||||
|
||||
handleAction( action, $el, id, shouldSetAction ) {
|
||||
const restEndpoint = `${ window.vrts_admin_vars.rest_url }/alerts/${ id }/${ action }`;
|
||||
const method = shouldSetAction ? 'POST' : 'DELETE';
|
||||
|
||||
let loadingElapsedTime = 0;
|
||||
let interval = null;
|
||||
|
||||
const timeout = setTimeout( () => {
|
||||
$el.setAttribute( 'data-vrts-loading', 'true' );
|
||||
const loadingStartTime = window.Date.now();
|
||||
interval = setInterval( () => {
|
||||
loadingElapsedTime = window.Date.now() - loadingStartTime;
|
||||
}, 50 );
|
||||
}, 200 );
|
||||
|
||||
fetch( restEndpoint, {
|
||||
method,
|
||||
headers: {
|
||||
'X-WP-Nonce': window.vrts_admin_vars.rest_nonce,
|
||||
},
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
return response.json();
|
||||
} )
|
||||
.then( () => {
|
||||
const loadingTimeoutTime =
|
||||
loadingElapsedTime > 0
|
||||
? Math.abs( loadingElapsedTime - 400 )
|
||||
: 0;
|
||||
|
||||
setTimeout( () => {
|
||||
$el.setAttribute( 'data-vrts-loading', 'false' );
|
||||
|
||||
$el.setAttribute(
|
||||
'data-vrts-action-state',
|
||||
shouldSetAction ? 'secondary' : 'primary'
|
||||
);
|
||||
|
||||
const $alert = document.getElementById(
|
||||
`vrts-alert-${ id }`
|
||||
);
|
||||
|
||||
if ( $alert ) {
|
||||
if ( 'false-positive' === action ) {
|
||||
$alert.setAttribute(
|
||||
'data-vrts-false-positive',
|
||||
shouldSetAction ? 'true' : 'false'
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'read-status' === action ) {
|
||||
$alert.setAttribute(
|
||||
'data-vrts-state',
|
||||
shouldSetAction ? 'read' : 'unread'
|
||||
);
|
||||
}
|
||||
}
|
||||
}, loadingTimeoutTime );
|
||||
|
||||
clearTimeout( timeout );
|
||||
clearInterval( interval );
|
||||
} );
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.dropdown?.();
|
||||
clearTimeout( this.setAsReadTimeout );
|
||||
this.$actionButtons?.forEach( ( item ) => {
|
||||
item.removeEventListener( 'click', this.onActionClick );
|
||||
} );
|
||||
this.$hideElementsForm?.removeEventListener(
|
||||
'submit',
|
||||
this.onHideElementsFormSubmit
|
||||
);
|
||||
this.$hideElementsModal?.removeEventListener(
|
||||
'hide',
|
||||
this.onHideElementsModalClose
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define( 'vrts-alert-actions', VrtsAlertActions );
|
||||
Reference in New Issue
Block a user