[#43684] migrated op-modal to spot-modal (#11172)

* [#43684] migrated op-modal to spot-modal

- https://community.openproject.org/work_packages/43684
- amended styles
- removed "modal--title"
- removed header component
- removed closing icon
- fixed backdrop click
- removed jquery from modal service

* [#43684] removed unused styling

- fixed some inconsitencies
- readded removed icon
- removed listener on close button

* [#43684] combined spot-action-bar

- used spot-action-bar in combination with spot-modal--footer
- fixed some styling in action bar

* [#43684] replaced more op-modal

- moved spec selectors to spot-modal
- replaced found op-modal in html templates

* [#43684] add no margin to old buttons in new dialogs

- added mobile modal behavior
- fixed some feature spec selectors

* [#43684] added modal close on mobile resolutions

* [#43684] fixed PR issues

- removed old css classes from html
- fixed feature spec click
- readded tour trigger on modal cancel

* when clicking outside the modal it will be closed instaed of clicking on a close button

* exclude _center class from spot-modal sass file itself and add it to the component style sheet

* Words should be break in any case like when there is no space there

* remove unnecessary classes that never used like _fullscreen and _cente, remove _limited-height class to make all the modal look the same

Co-authored-by: bsatarnejad <b.satarnejad@gmail.com>
Co-authored-by: Benjamin Bädorf <b.baedorf@openproject.com>
This commit is contained in:
Eric Schubert
2022-08-29 12:53:41 +02:00
committed by GitHub
parent d1ffd42fb9
commit c8f1e16005
101 changed files with 998 additions and 947 deletions
+7 -4
View File
@@ -1,5 +1,8 @@
<% if footer = registration_footer %>
<div class="op-modal--footer">
<span class="registration-footer"><%= footer %></span>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<% if footer = registration_footer %>
<span><%= footer %></span>
<% end %>
<%= styled_button_tag t(:button_create), class: 'button_no-margin -highlight -with-icon icon-checkmark spot-action-bar--action' %>
</div>
<% end %>
</div>
+6 -19
View File
@@ -33,22 +33,11 @@ See COPYRIGHT and LICENSE files for more details.
<%= back_url_hidden_field_tag %>
<%= error_messages_for :user %>
<div class="op-modal--header">
<%= op_icon 'icon-context icon-user' %>
<h1 class="op-modal--title">
<%= I18n.t('onboarding.welcome', app_title: Setting.app_title) %>
</h1>
<button
type="button"
class="op-modal--close-button"
title="<%= t('js.close_popup_title') %>"
aria-label="<%= t('js.close_popup_title') %>"
>
<%= op_icon('icon-close') %>
</button>
<div class="spot-modal--header">
<%= I18n.t('onboarding.welcome', app_title: Setting.app_title) %>
</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<h2><%= t(:label_register) %></h2>
<section class="form--section">
<% if @user.auth_source_id.nil? %>
@@ -65,7 +54,7 @@ See COPYRIGHT and LICENSE files for more details.
</div>
<div class="form--field -required -wide-label">
<%= f.text_field :lastname, required: true %>
<%= f.text_field :lastname, required: true %>
</div>
<% if registration_show_email? %>
@@ -94,7 +83,7 @@ See COPYRIGHT and LICENSE files for more details.
<%= f.password_field :password_confirmation,
required: true,
size: 25,
autocomplete: 'off' %>
autocomplete: 'off' %>
</div>
<% end %>
</section>
@@ -104,8 +93,6 @@ See COPYRIGHT and LICENSE files for more details.
<%= render partial: 'account/user_consent_check', locals: { consenting_user: @user } %>
<% end %>
<%= styled_button_tag t(:button_create), class: '-highlight -with-icon icon-checkmark' %>
<%= render partial: 'account/auth_providers', locals: { omniauth_title: I18n.t('account.signup_with_auth_provider'), wide: true } %>
</div>
+1 -1
View File
@@ -117,7 +117,7 @@ See COPYRIGHT and LICENSE files for more details.
<% if show_onboarding_modal? %>
<section data-augmented-model-wrapper
data-modal-initialize-now="true"
data-modal-class-name="onboarding-modal op-modal_autoheight -highlight">
data-modal-class-name="onboarding-modal">
<%= render partial: '/onboarding/configuration_modal' %>
</section>
<% end %>
@@ -29,22 +29,13 @@ See COPYRIGHT and LICENSE files for more details.
<div class="modal-delivery-element">
<%= labelled_tabular_form_for current_user, url: { action: 'user_settings', controller: 'onboarding' }, html: { id: 'user-form' } do |f| %>
<div class="op-modal--header op-modal--header_highlight">
<%= avatar(current_user) %>
<h1 class="op-modal--title">
<%= I18n.t('onboarding.welcome', app_title: Setting.app_title) %>, <%= current_user.name %>
</h1>
<button
type="button"
class="op-modal--close-button"
title="<%= t('js.close_popup_title') %>"
aria-label="<%= t('js.close_popup_title') %>"
>
<%= op_icon('icon-close') %>
</button>
<div class="spot-modal--header">
<%= I18n.t('onboarding.welcome', app_title: Setting.app_title) %>, <%= current_user.name %>
</div>
<div class="onboarding--main op-modal--body">
<div class="spot-divider"></div>
<div class="onboarding--main spot-modal--body">
<b><%= I18n.t('onboarding.select_language') %></b>
<fieldset class="form--fieldset">
<div class="form--field">
@@ -53,8 +44,10 @@ See COPYRIGHT and LICENSE files for more details.
</fieldset>
</div>
<div class="onboarding--footer op-modal--footer">
<%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %>
<div class="onboarding--footer spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<%= styled_button_tag t(:button_save), class: 'button_no-margin -highlight -with-icon icon-checkmark spot-action-bar--action' %>
</div>
</div>
<% end %>
</div>
+1 -1
View File
@@ -31,7 +31,7 @@ See COPYRIGHT and LICENSE files for more details.
data-augmented-model-wrapper
data-activation-selector=".onboarding-modal--activation-link"
data-modal-iframe-url="<%= OpenProject::Configuration.onboarding_video_url %>"
data-modal-class-name="onboarding-modal op-modal_autoheight -highlight"
data-modal-class-name="onboarding-modal"
>
<%= link_to t(:label_introduction_video),
'',
@@ -28,22 +28,12 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
<div class="modal-delivery-element">
<div class="op-modal--header op-modal--header_highlight">
<%= op_icon 'icon-context icon-user' %>
<h1 class="op-modal--title">
<%= I18n.t('onboarding.welcome', app_title: Setting.app_title) %>
</h1>
<button
type="button"
class="op-modal--close-button"
title="<%= t('js.close_popup_title') %>"
aria-label="<%= t('js.close_popup_title') %>"
>
<%= op_icon('icon-close') %>
</button>
<div class="spot-modal--header">
<span class="spot-icon spot-icon_user"></span>
<span><%= I18n.t('onboarding.welcome', app_title: Setting.app_title) %></span>
</div>
<div class="onboarding--main op-modal--body">
<div class="spot-divider"></div>
<div class="onboarding--main spot-modal--body">
<h2><%= I18n.t('onboarding.heading_getting_started') %></h2>
<div class="onboarding--video-block">
<div class="onboarding--video-text">
@@ -54,12 +44,14 @@ See COPYRIGHT and LICENSE files for more details.
</div>
</div>
<div class="onboarding--footer op-modal--footer">
<span><em><%= I18n.t('onboarding.text_show_again') %></em></span>
<button
class="button -highlight"
dynamic-content-modal-close-button
title=<%= t(:button_close)%>
><%= t(:button_close)%></button>
<div class="onboarding--footer spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<span><em><%= I18n.t('onboarding.text_show_again') %></em></span>
<button
class="button button_no-margin -highlight spot-action-bar--action"
dynamic-content-modal-close-button
title=<%= t(:button_close) %>
><%= t(:button_close) %></button>
</div>
</div>
</div>
@@ -28,21 +28,12 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
<div class="modal-delivery-element">
<div class="op-modal--header">
<h1 class="op-modal--title">
<%= I18n.t('js.label_export') %>
</h1>
<button
type="button"
class="op-modal--close-button"
aria-label="<%= t('js.close_popup_title') %>"
>
<%= op_icon('icon-close') %>
</button>
<div class="spot-modal--header">
<%= I18n.t('js.label_export') %>
</div>
<div class="op-modal--body">
<ul class="op-export-options">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<ul class="spot-export-options">
<% supported_export_formats.each do |key| %>
<li class="op-export-options--option">
<% filter_params = safe_query_params ['filters', 'sortBy'] %>
+20 -29
View File
@@ -28,42 +28,33 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
<div class="modal-delivery-element">
<div class="op-modal--header">
<h1 class="op-modal--title">
<%= I18n.t('js.label_export') %>
</h1>
<button
type="button"
class="op-modal--close-button"
aria-label="<%= t('js.close_popup_title') %>"
>
<%= op_icon('icon-close') %>
</button>
<div class="spot-modal--header">
<%= I18n.t('js.label_export') %>
</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<ul class="op-export-options">
<li class="op-export-options--option">
<%= link_to url_for(
controller: '/activities',
action: 'index',
show_wiki_edits: 1,
apply: true,
key: User.current.rss_key,
format: 'atom',
), class: 'op-export-options--option-link' do %>
<%= op_icon('icon-big icon-export-atom') %>
<span class="op-export-options--option-label"><%= t('export.format.atom') %></span>
controller: '/activities',
action: 'index',
show_wiki_edits: 1,
apply: true,
key: User.current.rss_key,
format: 'atom',
), class: 'op-export-options--option-link' do %>
<%= op_icon('icon-big icon-export-atom') %>
<span class="op-export-options--option-label"><%= t('export.format.atom') %></span>
<% end %>
</li>
<li class="op-export-options--option">
<%= link_to url_for(
version: @content.version,
id: @page,
format: 'markdown',
), class: 'op-export-options--option-link' do %>
<%= op_icon('icon-big icon-ticket') %>
<span class="op-export-options--option-label"><%= t('text_formatting.markdown') %></span>
version: @content.version,
id: @page,
format: 'markdown',
), class: 'op-export-options--option-link' do %>
<%= op_icon('icon-big icon-ticket') %>
<span class="op-export-options--option-label"><%= t('text_formatting.markdown') %></span>
<% end %>
</li>
</ul>
@@ -71,5 +62,5 @@ See COPYRIGHT and LICENSE files for more details.
</div>
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, controller: '/activities', action: 'index', id: @project, show_wiki_edits: 1, format: 'atom', key: User.current.rss_key) %>
<%= auto_discovery_link_tag(:atom, controller: '/activities', action: 'index', id: @project, show_wiki_edits: 1, format: 'atom', key: User.current.rss_key) %>
<% end %>
+3
View File
@@ -68,6 +68,9 @@ module.exports = {
// Who cares about line length
"max-len": "off",
// Allow short circuit evaluations
"@typescript-eslint/no-unused-expressions": ["error", { "allowShortCircuit": true }],
// Force single quotes to align with ruby
quotes: "off",
"@typescript-eslint/quotes": ["error", "single", { avoidEscape: true }],
@@ -33,11 +33,14 @@ export function detectOnboardingTour():void {
currentTourPart = '';
sessionStorage.setItem(onboardingTourStorageKey, 'readyToStart');
waitForElement('.onboarding-modal .op-modal--close-button', 'body', () => {
// Start automatically when the language selection is closed
jQuery('.op-modal--close-button').click(() => {
tourCancelled = true;
void triggerTour('homescreen');
// Start automatically when modal is closed by backdrop click
waitForElement('.spot-modal-overlay_active', 'body', () => {
const elementsByClassName = document.getElementsByClassName('spot-modal-overlay_active');
Array.from(elementsByClassName).forEach((modalOverlay) => {
modalOverlay.addEventListener('click', () => {
tourCancelled = true;
void triggerTour('homescreen');
});
});
});
@@ -0,0 +1,31 @@
// -- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2022 the OpenProject GmbH
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See COPYRIGHT and LICENSE files for more details.
//++
export default function isNotNull<T>(entity:T|null):entity is T {
return entity !== null;
}
@@ -1,10 +1,12 @@
<div
class="op-modal op-modal_autoheight confirm-form-submit--modal loading-indicator--location"
class="spot-modal spot-modal_autoheight confirm-form-submit--modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<div *ngIf="showWarning && warningText"
class="op-toast -warning">
<div class="op-toast--content">
@@ -12,50 +14,52 @@
</div>
</div>
<div class="form--field">
<div class="form--field-container">
<div class="form--select-container">
<label class="form--label" [textContent]="actionService.label"></label>
<op-autocompleter
#select
classes="new-list--action-select"
appendTo="body"
[resource]="autocompleterOptions.resource"
[openDirectly]="true"
[fetchDataDirectly]="true"
[getOptionsFn]=autocompleterOptions.getOptionsFn
(change)="onModelChange($event)"
>
<ng-template op-autocompleter-footer-tmp *ngIf="autocompleterOptions.resource=='version'" let-search>
<button
class="op-select-footer--label"
type="button"
(click)="onNewActionCreated()">
<div class="form--field">
<div class="form--field-container">
<div class="form--select-container">
<label class="form--label" [textContent]="actionService.label"></label>
<op-autocompleter
#select
classes="new-list--action-select"
appendTo="body"
[resource]="autocompleterOptions.resource"
[openDirectly]="true"
[fetchDataDirectly]="true"
[getOptionsFn]=autocompleterOptions.getOptionsFn
(change)="onModelChange($event)"
>
<ng-template op-autocompleter-footer-tmp *ngIf="autocompleterOptions.resource=='version'" let-search>
<button
class="op-select-footer--label"
type="button"
(click)="onNewActionCreated()">
<span class="icon-context">
<op-icon icon-classes="icon-plus icon-context"></op-icon>
{{text.button_create}} {{ngSelectComponent.ngSelectInstance.searchTerm}}
</span>
</button>
</button>
</ng-template>
</op-autocompleter>
</div>
</ng-template>
</op-autocompleter>
</div>
</div>
</div>
</div>
<div class="op-modal--footer">
<button
class="confirm-form-submit--cancel button"
(click)="closeMe($event)"
[textContent]="text.button_cancel"
[attr.title]="text.button_cancel"
></button>
<button
class="confirm-form-submit--submit button -highlight"
(click)="create()"
[disabled]="!this.selectedAttribute || inFlight"
[textContent]="text.button_add"
[attr.title]="text.button_add"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="confirm-form-submit--cancel button button_no-margin spot-action-bar--action"
(click)="closeMe($event)"
[textContent]="text.button_cancel"
[attr.title]="text.button_cancel"
></button>
<button
class="confirm-form-submit--submit button button_no-margin -highlight spot-action-bar--action"
(click)="create()"
[disabled]="!this.selectedAttribute || inFlight"
[textContent]="text.button_add"
[attr.title]="text.button_add"
></button>
</div>
</div>
</div>
@@ -1,23 +1,27 @@
<div
class="op-modal wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
class="spot-modal wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<div class="tab-content" #tabContentOutlet></div>
</div>
<div class="op-modal--footer">
<button
class="button"
[textContent]="text.cancelButton"
(click)="closeMe($event)"
></button>
<button
class="button -highlight"
[textContent]="text.applyButton"
(click)="saveChanges()"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="button button_no-margin spot-action-bar--action"
[textContent]="text.cancelButton"
(click)="closeMe($event)"
></button>
<button
class="button button_no-margin -highlight spot-action-bar--action"
[textContent]="text.applyButton"
(click)="saveChanges()"
></button>
</div>
</div>
</div>
@@ -1,10 +1,12 @@
<div
class="op-modal op-modal_wide confirm-form-submit--modal loading-indicator--location"
class="spot-modal spot-modal_wide confirm-form-submit--modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.board_type}}</op-modal-header>
<div class="spot-modal--header">{{text.board_type}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<p
*ngIf="eeShowBanners"
>
@@ -1,7 +1,9 @@
<div class="op-modal op-enterprise-modal">
<op-modal-header (close)="closeModal($event)">{{headerText()}}</op-modal-header>
<div class="spot-modal op-enterprise-modal">
<div class="spot-modal--header">{{headerText()}}</div>
<div [ngSwitch]="openWindow()" class="op-modal--body">
<div class="spot-divider"></div>
<div [ngSwitch]="openWindow()" class="spot-modal--body">
<!-- first modal window -->
<div *ngSwitchCase="1">
<enterprise-trial-form></enterprise-trial-form>
@@ -28,39 +30,44 @@
</div>
</div>
<div class="op-modal--footer">
<div *ngIf="!eeTrialService.status || eeTrialService.cancelled; else mailSubmitted">
<button
class="confirm-form-submit--cancel button"
(click)="closeModal($event)"
[textContent]="text.button_cancel"
[attr.title]="text.button_cancel"
></button>
<button
class="confirm-form-submit--continue button -highlight"
(click)="onSubmit()"
[disabled]="!trialForm || trialForm.invalid"
[textContent]="text.button_submit"
[attr.title]="text.button_submit"
[hidden]="eeTrialService.mailSubmitted && !eeTrialService.cancelled"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<div *ngIf="!eeTrialService.status || eeTrialService.cancelled; else mailSubmitted"
class="spot-action-bar--right">
<button
class="confirm-form-submit--cancel button button_no-margin spot-action-bar--action"
(click)="closeModal($event)"
[textContent]="text.button_cancel"
[attr.title]="text.button_cancel"
></button>
<button
class="confirm-form-submit--continue button button_no-margin -highlight spot-action-bar--action"
(click)="onSubmit()"
[disabled]="!trialForm || trialForm.invalid"
[textContent]="text.button_submit"
[attr.title]="text.button_submit"
[hidden]="eeTrialService.mailSubmitted && !eeTrialService.cancelled"
></button>
</div>
<ng-template #mailSubmitted>
<div class="spot-action-bar--right">
<button
class="confirm-form-submit--continue button button_no-margin -highlight spot-action-bar--action"
(click)="startEnterpriseTrial()"
[textContent]="text.button_continue"
[attr.title]="text.button_continue"
[disabled]="!eeTrialService.confirmed"
[hidden]="eeTrialService.trialStarted"
></button>
<button
*ngIf="eeTrialService.trialStarted"
class="confirm-form-submit--continue button button_no-margin -highlight spot-action-bar--action"
(click)="closeModal($event)"
[textContent]="text.button_continue"
[attr.title]="text.button_continue"
></button>
</div>
</ng-template>
</div>
<ng-template #mailSubmitted>
<button
class="confirm-form-submit--continue button -highlight"
(click)="startEnterpriseTrial()"
[textContent]="text.button_continue"
[attr.title]="text.button_continue"
[disabled]="!eeTrialService.confirmed"
[hidden]="eeTrialService.trialStarted"
></button>
<button
*ngIf="eeTrialService.trialStarted"
class="confirm-form-submit--continue button -highlight"
(click)="closeModal($event)"
[textContent]="text.button_continue"
[attr.title]="text.button_continue"
></button>
</ng-template>
</div>
</div>
</div>
@@ -1,10 +1,10 @@
<div
class="op-modal"
class="spot-modal"
*ngIf="loading"
></div>
<op-ium-project-selection
*ngIf="!loading && step === Steps.ProjectSelection"
class="op-modal"
class="spot-modal"
[project]="project"
[type]="type"
(save)="onProjectSelectionSave($event)"
@@ -13,7 +13,7 @@
<op-ium-principal
*ngIf="!loading && step === Steps.Principal"
class="op-modal"
class="spot-modal"
[project]="project"
[principalData]="principalData"
[type]="type"
@@ -24,7 +24,7 @@
<op-ium-role
*ngIf="!loading && step === Steps.Role"
class="op-modal"
class="spot-modal"
[role]="role"
[principal]="principalData.principal"
[project]="project"
@@ -36,7 +36,7 @@
<op-ium-message
*ngIf="!loading && step === Steps.Message"
class="op-modal"
class="spot-modal"
[message]="message"
[principal]="principalData.principal"
[project]="project"
@@ -47,7 +47,7 @@
<op-ium-summary
*ngIf="!loading && step === Steps.Summary"
class="op-modal"
class="spot-modal"
[project]="project"
[principalData]="principalData"
[type]="type"
@@ -64,6 +64,6 @@
[type]="type"
[createdNewPrincipal]="createdNewPrincipal"
*ngIf="!loading && step === Steps.Success"
class="op-modal"
class="spot-modal"
(close)="closeWithPrincipal()"
></op-ium-success>
@@ -2,9 +2,11 @@
[formGroup]="messageForm"
(ngSubmit)="onSubmit($event)"
>
<op-modal-header (close)="close.emit()">{{ text.title() }}</op-modal-header>
<div class="spot-modal--header">{{text.title()}}</div>
<div class="op-modal--body op-form">
<div class="spot-divider"></div>
<div class="spot-modal--body op-form">
<op-form-field [label]="text.label">
<p class="op-form-field--description" slot="description">
{{ text.description() }}
@@ -19,12 +21,14 @@
</op-form-field>
</div>
<div class="op-modal--footer">
<button
type="button"
class="button"
(click)="back.emit()"
>{{ text.backButton }}</button>
<button class="button -highlight">{{ text.nextButton }}</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
type="button"
class="button button_no-margin spot-action-bar--action"
(click)="back.emit()"
>{{ text.backButton }}</button>
<button class="button button_no-margin -highlight spot-action-bar--action">{{ text.nextButton }}</button>
</div>
</div>
</form>
@@ -1,5 +1,5 @@
<ng-select
appendTo=".op-modal-overlay"
appendTo=".spot-modal-overlay"
[formControl]="principalControl"
[addTag]="showAddTag ? createNewFromInput.bind(this) : false"
[typeahead]="input$"
@@ -2,9 +2,11 @@
[formGroup]="principalForm"
(ngSubmit)="onSubmit($event)"
>
<op-modal-header (close)="close.emit()">{{ text.title() }}</op-modal-header>
<div class="spot-modal--header">{{text.title()}}</div>
<div class="op-modal--body op-form">
<div class="spot-divider"></div>
<div class="spot-modal--body op-form">
<op-form-field
[label]="textLabel"
required
@@ -27,7 +29,7 @@
type="button"
class="spot-link"
(click)="principalControl?.setValue(null)"
>{{ text.change }}</button>
>{{ text.change }}</button>
</p>
<p
@@ -60,12 +62,14 @@
></op-dynamic-form>
</div>
<div class="op-modal--footer">
<button
type="button"
class="button"
(click)="back.emit()"
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
type="button"
class="button button_no-margin spot-action-bar--action"
(click)="back.emit()"
>{{ text.backButton }}</button>
<button class="button -highlight">{{ text.nextButton }}</button>
<button class="button button_no-margin -highlight spot-action-bar--action">{{ text.nextButton }}</button>
</div>
</div>
</form>
@@ -2,9 +2,11 @@
[formGroup]="projectAndTypeForm"
(ngSubmit)="onSubmit($event)"
>
<op-modal-header (close)="close.emit()">{{ text.title }}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body op-form">
<div class="spot-divider"></div>
<div class="spot-modal--body op-form">
<op-form-field
[label]="text.project.label"
required
@@ -14,7 +16,7 @@
formControlName="project"
[apiFilters]="APIFiltersForProjects"
[mapResultsFn]="projectFilterFn.bind(this)"
appendTo=".op-modal-overlay"
appendTo=".spot-modal-overlay"
></op-project-autocompleter>
<div
@@ -60,7 +62,9 @@
</op-form-field>
</div>
<div class="op-modal--footer">
<button class="button -highlight">{{ text.nextButton }}</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button class="button button_no-margin -highlight spot-action-bar--action">{{ text.nextButton }}</button>
</div>
</div>
</form>
@@ -1,5 +1,5 @@
<ng-select
appendTo=".op-modal-overlay"
appendTo=".spot-modal-overlay"
[formControl]="roleControl"
[typeahead]="input$"
[items]="items$ | async"
@@ -2,9 +2,11 @@
[formGroup]="roleForm"
(ngSubmit)="onSubmit($event)"
>
<op-modal-header (close)="close.emit()">{{ text.title() }}</op-modal-header>
<div class="spot-modal--header">{{text.title()}}</div>
<div class="op-modal--body op-form">
<div class="spot-divider"></div>
<div class="spot-modal--body op-form">
<op-form-field
[label]="text.label()"
required
@@ -29,12 +31,14 @@
</op-form-field>
</div>
<div class="op-modal--footer">
<button
type="button"
class="button"
(click)="back.emit()"
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
type="button"
class="button button_no-margin spot-action-bar--action"
(click)="back.emit()"
>{{ text.backButton }}</button>
<button class="button -highlight">{{ text.nextButton }}</button>
<button class="button button_no-margin -highlight spot-action-bar--action">{{ text.nextButton }}</button>
</div>
</div>
</form>
@@ -1,5 +1,5 @@
<div class="op-ium-success">
<div class="op-modal--body op-modal--body_center">
<div class="spot-modal--body op-ium-success--content">
<img [src]="type === PrincipalType.Placeholder ? placeholder_image : user_image" />
<h1 [textContent]="text.title()"></h1>
@@ -2,3 +2,8 @@
flex-grow: 1
display: flex
flex-direction: column
&--content
justify-content: center
align-items: center
text-align: center
@@ -3,9 +3,11 @@
(submit)="onSubmit($event)"
class="op-ium-summary"
>
<op-modal-header (close)="close.emit()">{{ text.title() }}</op-modal-header>
<div class="spot-modal--header">{{text.title()}}</div>
<div class="op-modal--body op-form">
<div class="spot-divider"></div>
<div class="spot-modal--body op-form">
<op-form-field [label]="text.projectLabel">
<p slot="input">{{ project.name }}</p>
</op-form-field>
@@ -25,14 +27,16 @@
</op-form-field>
</div>
<div class="op-modal--footer">
<button
type="button"
class="button"
(click)="back.emit()"
>{{ text.backButton }}</button>
<button
class="button -highlight"
>{{ text.nextButton() }}</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
type="button"
class="button button_no-margin spot-action-bar--action"
(click)="back.emit()"
>{{ text.backButton }}</button>
<button
class="button button_no-margin -highlight spot-action-bar--action"
>{{ text.nextButton() }}</button>
</div>
</div>
</form>
@@ -1,9 +1,14 @@
<div
class="op-modal op-modal_wide-fixed job-status--modal"
class="spot-modal job-status--modal"
>
<op-modal-header (close)="closeMe($event)">{{ title }}</op-modal-header>
<div
class="spot-modal--header"
data-qa-selector="job-status--header"
>{{ title }}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<div class="loading-indicator--location"
data-indicator-name="modal">
<div class="status-icon-wrapper" *ngIf="!isLoading && statusIcon">
@@ -1,38 +1,42 @@
<div
class="op-modal op-modal_wide wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
class="spot-modal spot-modal_wide wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<ng-container *ngIf="!!prependModalComponent">
<ng-container *ngComponentOutlet="prependModalComponent; injector: injector"></ng-container>
</ng-container>
<op-scrollable-tabs
*ngIf="tabPortalHost"
[tabs]="availableTabs"
[currentTabId]="tabPortalHost.currentTab?.id"
(tabSelected)="switchTo($event)"
>
*ngIf="tabPortalHost"
[tabs]="availableTabs"
[currentTabId]="tabPortalHost.currentTab?.id"
(tabSelected)="switchTo($event)"
>
</op-scrollable-tabs>
<div class="tab-content" #tabContentOutlet></div>
</div>
<div class="op-modal--footer">
<button
class="button -highlight"
data-qa-selector="op-modal-wp-table-configuration-save-button"
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="button button_no-margin -highlight spot-action-bar--action"
data-qa-selector="spot-modal-wp-table-configuration-save-button"
[textContent]="text.applyButton"
(click)="saveChanges()"
>
</button>
<button
class="button"
>
</button>
<button
class="button button_no-margin spot-action-bar--action"
[textContent]="text.cancelButton"
(click)="closeMe($event)"
>
</button>
>
</button>
</div>
</div>
</div>
@@ -1,13 +1,18 @@
<div
class="op-modal op-modal_autoheight attribute-help-text--modal loading-indicator--location"
class="spot-modal attribute-help-text--modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">
<span class="icon-context icon-help1"></span>
<div
class="spot-modal--header"
data-qa-selector="attribute-help-text--header"
>
<span class="spot-icon spot-icon_help1"></span>
<span [textContent]="helpText.attributeCaption"></span>
</op-modal-header>
</div>
<div class="op-modal--body op-modal--body_limited-height">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<div
class="op-uc-container op-uc-container__no-permalinks"
[innerHtml]="helpText.helpText.html"
@@ -19,15 +24,17 @@
></attachments>
</div>
<div class="op-modal--footer">
<a
class="help-text--edit-button button"
*ngIf="helpText.editText"
[attr.href]="helpTextLink"
[attr.title]="text.edit"
>
<op-icon icon-classes="button--icon icon-edit"></op-icon>
<span class="button--text" [textContent]="text.edit"></span>
</a>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<a
class="help-text--edit-button button button_no-margin spot-action-bar--action"
*ngIf="helpText.editText"
[attr.href]="helpTextLink"
[attr.title]="text.edit"
>
<op-icon icon-classes="button--icon icon-edit"></op-icon>
<span class="button--text" [textContent]="text.edit"></span>
</a>
</div>
</div>
</div>
@@ -1,5 +1,5 @@
<form
class="op-modal op-datepicker-modal loading-indicator--location"
class="spot-modal op-datepicker-modal loading-indicator--location"
data-qa-selector="op-datepicker-modal"
[attr.id]="htmlId"
#modalContainer
@@ -7,7 +7,7 @@
(submit)="save($event)"
>
<op-datepicker-banner [scheduleManually]="scheduleManually"></op-datepicker-banner>
<div class="op-modal--body form -vertical">
<div class="spot-modal--body form -vertical">
<div class="form--field op-datepicker-modal--scheduling-action-container">
<div class="form--field-container">
<label class="form--label-with-check-box">
@@ -115,17 +115,19 @@
hidden>
</div>
<div class="op-modal--footer">
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
(click)="cancel()"
class="op-datepicker-modal--action button"
class="op-datepicker-modal--action button button_no-margin spot-action-bar--action"
data-qa-selector="op-datepicker-modal--action"
[textContent]="text.cancel"
></button>
<button
class="op-datepicker-modal--action button -highlight"
class="op-datepicker-modal--action button button_no-margin -highlight spot-action-bar--action"
data-qa-selector="op-datepicker-modal--action"
[textContent]="text.save"
></button>
</div>
</div>
</form>
@@ -1,10 +1,12 @@
<div
class="op-modal loading-indicator--location"
class="spot-modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="ngdialog-body op-modal--body">
<div class="spot-divider"></div>
<div class="ngdialog-body spot-modal--body">
<op-enterprise-banner
*ngIf="eeShowBanners"
@@ -1,10 +1,12 @@
<div class="op-modal"
<div class="spot-modal"
data-indicator-name="modal"
tabindex="0">
<op-modal-header (close)="closeMe($event)">{{text.displayedDays}}</op-modal-header>
<div class="spot-modal--header">{{text.displayedDays}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<div class="form--field -trailing-label" *ngFor="let day of days; let index = index">
<label class="form--label" [textContent]="day.weekDay" [htmlFor]="'day_' + index"></label>
<span class="form--field-container">
@@ -15,16 +17,18 @@
</div>
</div>
<div class="op-modal--footer">
<button
class="button"
[textContent]="text.cancelButton"
(click)="closeMe($event)"
></button>
<button
class="button -highlight"
[textContent]="text.applyButton"
(click)="saveChanges()"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="button button_no-margin spot-action-bar--action"
[textContent]="text.cancelButton"
(click)="closeMe($event)"
></button>
<button
class="button button_no-margin -highlight spot-action-bar--action"
[textContent]="text.applyButton"
(click)="saveChanges()"
></button>
</div>
</div>
</div>
@@ -1,2 +0,0 @@
.modal-delivery-element
display: none
@@ -1,16 +0,0 @@
<op-icon
*ngIf="icon"
icon-classes="{{ icon }} icon-context"
></op-icon>
<h1 class="op-modal--title">
<ng-content></ng-content>
</h1>
<button
class="op-modal--close-button"
type="button"
data-qa-selector="op-modal-close"
(click)="close.emit()"
[attr.aria-label]="text.closePopup"
>
<op-icon icon-classes="icon-close"></op-icon>
</button>
@@ -1,24 +0,0 @@
import {
Component, EventEmitter, HostBinding, Input, Output,
} from '@angular/core';
import { I18nService } from 'core-app/core/i18n/i18n.service';
@Component({
selector: 'op-modal-header',
templateUrl: './modal-header.component.html',
})
export class OpModalHeaderComponent {
@HostBinding('class.op-modal--header') className = true;
@Input() icon = '';
@Output('close') close = new EventEmitter<void>();
public text = {
closePopup: this.I18n.t('js.close_popup_title'),
};
constructor(
readonly I18n:I18nService,
) {}
}
@@ -1,11 +0,0 @@
<h3>
<ng-content></ng-content>
</h3>
<button
class="op-modal--close-button"
type="button"
(click)="close.emit()"
[attr.aria-label]="text.closePopup"
>
<span class="icon-close"></span>
</button>
@@ -1,22 +0,0 @@
import {
Component, EventEmitter, HostBinding, Output,
} from '@angular/core';
import { I18nService } from 'core-app/core/i18n/i18n.service';
@Component({
selector: 'op-modal-heading',
templateUrl: './modal-heading.component.html',
})
export class OpModalHeadingComponent {
@HostBinding('class.op-modal--heading') className = true;
@Output('close') close = new EventEmitter<void>();
public text = {
closePopup: this.I18n.t('js.close_popup_title'),
};
constructor(
readonly I18n:I18nService,
) {}
}
@@ -53,7 +53,7 @@ export abstract class OpModalComponent extends UntilDestroyedMixin implements On
return true;
}
public closeMe(evt?:JQuery.TriggeredEvent) {
public closeMe(evt?:Event):void {
this.service.close();
if (evt) {
@@ -62,7 +62,7 @@ export abstract class OpModalComponent extends UntilDestroyedMixin implements On
}
}
public onOpen(modalElement:JQuery) {
public onOpen():void {
this.openingEvent.emit();
this.cdRef.detectChanges();
}
@@ -1,5 +0,0 @@
@import 'modal-overrides'
@import 'modal-overlay'
@import 'modal-delivery-element'
@import 'modal'
@@ -4,7 +4,6 @@ import { FocusModule } from 'core-app/shared/directives/focus/focus.module';
import { IconModule } from 'core-app/shared/components/icon/icon.module';
import { OpModalService } from './modal.service';
import { OpModalWrapperAugmentService } from './modal-wrapper-augment.service';
import { OpModalHeaderComponent } from './modal-header.component';
import { OpModalBannerComponent } from 'core-app/shared/components/modal/modal-banner/modal-banner.component';
@NgModule({
@@ -14,7 +13,6 @@ import { OpModalBannerComponent } from 'core-app/shared/components/modal/modal-b
IconModule,
],
exports: [
OpModalHeaderComponent,
OpModalBannerComponent,
],
providers: [
@@ -22,9 +20,7 @@ import { OpModalBannerComponent } from 'core-app/shared/components/modal/modal-b
OpModalWrapperAugmentService,
],
declarations: [
OpModalHeaderComponent,
OpModalBannerComponent,
],
})
export class OpenprojectModalModule { }
@@ -1,107 +0,0 @@
// TODO: Check out -danger-zone and modal-close-button patterns
.op-modal
--modal-padding: 1rem
position: relative
display: flex
flex-direction: column
align-items: stretch
background: white
pointer-events: all
width: 40rem
min-height: 500px
max-width: 100vw
max-height: 100vh
overflow-y: auto
@include styled-scroll-bar
@media (max-width: 680px), (max-height: 500px)
height: 100vh
width: 100vw
min-height: unset
&_wide
width: 70rem
min-height: 40vh
&_fullscreen
width: 100vw
height: 100vh
&_autoheight
min-height: initial
&--header
display: flex
padding: calc(0.5 * var(--modal-padding)) var(--modal-padding) calc(0.5 * var(--modal-padding)) var(--modal-padding)
position: relative
border-bottom: 1px solid #eee
align-items: center
&_highlight
background-color: var(--header-bg-color)
border-bottom-width: var(--header-border-bottom-width)
border-bottom-color: var(--header-border-bottom-color)
*
color: var(--header-item-font-color)
&--body
display: flex
flex-direction: column
padding: var(--modal-padding)
flex-grow: 1
flex-shrink: 1
overflow-y: auto
&:focus
outline-style: none
&_limited-height
max-height: 50vh
&_center
justify-content: center
align-items: center
text-align: center
&--title
font-size: 1.3rem
padding: 0
margin: 0
margin-right: auto
&--footer
display: flex
justify-content: flex-end
padding: calc(0.5 * var(--modal-padding)) var(--modal-padding) var(--modal-padding) var(--modal-padding)
width: 100%
&_split-actions
justify-content: space-between
.button
margin-bottom: 0
@media (max-width: 680px), (max-height: 500px)
padding: var(--modal-padding)
&--close-button
height: 100%
width: 3rem
padding: 0.45rem 0
margin: 0 -1rem
display: flex
justify-content: center
align-items: center
cursor: pointer
color: var(--body-font-color)
background: transparent
border: 0
&:hover
text-decoration: none
color: var(--content-link-color)
@@ -1,3 +1,31 @@
// -- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2022 the OpenProject GmbH
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See COPYRIGHT and LICENSE files for more details.
//++
import {
ApplicationRef,
ComponentFactoryResolver,
@@ -7,12 +35,14 @@ import {
Injector,
} from '@angular/core';
import {
ComponentPortal, ComponentType, DomPortalOutlet, PortalInjector,
ComponentPortal,
ComponentType,
DomPortalOutlet,
PortalInjector,
} from '@angular/cdk/portal';
import { TransitionService } from '@uirouter/core';
import { OpModalComponent } from 'core-app/shared/components/modal/modal.component';
import { FocusHelperService } from 'core-app/shared/directives/focus/focus-helper';
import { KeyCodes } from 'core-app/shared/helpers/keyCodes.enum';
export const OpModalLocalsToken = new InjectionToken<any>('OP_MODAL_LOCALS');
@@ -21,7 +51,7 @@ export class OpModalService {
public active:OpModalComponent|null = null;
// Hold a reference to the DOM node we're using as a host
private portalHostElement:HTMLElement;
private readonly portalHostElement:HTMLElement;
// And a reference to the actual portal host interface on top of the element
private bodyPortalHost:DomPortalOutlet;
@@ -29,30 +59,40 @@ export class OpModalService {
// Remember when we're opening a new modal to avoid the outside click bubbling up.
private opening = false;
constructor(private componentFactoryResolver:ComponentFactoryResolver,
readonly FocusHelper:FocusHelperService,
private appRef:ApplicationRef,
private $transitions:TransitionService,
private injector:Injector) {
const hostElement = this.portalHostElement = document.createElement('div');
hostElement.classList.add('op-modal-overlay');
constructor(
private readonly componentFactoryResolver:ComponentFactoryResolver,
private readonly appRef:ApplicationRef,
private readonly $transitions:TransitionService,
private readonly injector:Injector,
) {
const hostElement = document.createElement('div');
hostElement.classList.add('spot-modal-overlay');
document.body.appendChild(hostElement);
// Listen to keyups on window to close context menus
jQuery(window).on('keydown', (evt:JQuery.TriggeredEvent) => {
if (this.active && this.active.closeOnEscape && evt.which === KeyCodes.ESCAPE) {
this.active.closeOnEscapeFunction(evt);
}
const closeButton = document.createElement('button');
closeButton.classList.add('spot-button', 'spot-modal-close-button');
closeButton.innerHTML = '<span class="spot-icon spot-icon_close"></span>';
hostElement.appendChild(closeButton);
// Listen to keystrokes on window to close context menus
window.addEventListener('keydown', (evt:KeyboardEvent) => {
if (this.active && this.active.closeOnEscape && evt.key === 'Escape') {
this.active.closeOnEscapeFunction();
}
return true;
});
// Listen to any click when should close outside modal
jQuery(window).on('click', (evt:JQuery.TriggeredEvent) => {
// Listen to any click on the modal overlay (backdrop click)
hostElement.addEventListener('click', (evt:MouseEvent) => {
if (this.active
&& !this.opening
&& this.active.closeOnOutsideClick
&& this.activeModal[0] === evt.target as Element) {
&& this.portalHostElement === evt.target as Element) {
this.close();
}
});
closeButton.addEventListener('click', () => {
if (this.active && !this.opening) {
this.close();
}
});
@@ -63,6 +103,8 @@ export class OpModalService {
this.appRef,
this.injector,
);
this.portalHostElement = hostElement;
}
/**
@@ -93,16 +135,15 @@ export class OpModalService {
// Create a portal for the given component class and render it
const portal = new ComponentPortal(modal, null, this.injectorFor(injector, locals));
const ref:ComponentRef<OpModalComponent> = this.bodyPortalHost.attach(portal) as ComponentRef<OpModalComponent>;
const instance = ref.instance as T;
this.active = instance;
this.portalHostElement.classList.add('op-modal-overlay_active');
this.active = ref.instance as T;
this.portalHostElement.classList.add('spot-modal-overlay_active');
if (notFullScreen) {
this.portalHostElement.classList.add('op-modal-overlay_not-full-screen');
this.portalHostElement.classList.add('spot-modal-overlay_not-full-screen');
}
setTimeout(() => {
// Focus on the first element
this.active && this.active.onOpen(this.activeModal);
this.active && this.active.onOpen();
// Mark that we've opened the modal now
this.opening = false;
@@ -114,33 +155,28 @@ export class OpModalService {
return this.active as T;
}
public isActive(modal:OpModalComponent) {
return this.active && this.active === modal;
public isActive(modal:OpModalComponent):boolean {
return this.active !== null && this.active === modal;
}
/**
* Closes currently open modal window
*/
public close() {
public close():void {
// Detach any component currently in the portal
if (this.active && this.active.onClose()) {
this.active.closingEvent.emit(this.active);
this.bodyPortalHost.detach();
this.portalHostElement.classList.remove('op-modal-overlay_active');
this.portalHostElement.classList.remove('op-modal-overlay_not-full-screen');
this.portalHostElement.classList.remove('spot-modal-overlay_active');
this.portalHostElement.classList.remove('spot-modal-overlay_not-full-screen');
this.active = null;
}
}
public get activeModal():JQuery {
return jQuery(this.portalHostElement).find('.op-modal');
}
/**
* Create an augmented injector that is equal to this service's injector + the additional data
* passed into +show+.
* This allows callers to pass data into the newly created modal.
*
*/
private injectorFor(injector:Injector, data:Record<string, unknown>) {
const injectorTokens = new WeakMap();
@@ -1,11 +1,13 @@
<div
class="op-modal op-modal_autoheight confirm-form-submit--modal loading-indicator--location"
[ngClass]="{'-highlight -danger-zone' : dangerHighlighting }"
class="spot-modal confirm-form-submit--modal loading-indicator--location"
[ngClass]="{'-highlight' : dangerHighlighting }"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<p>
<span [textContent]="text.text"></span>
<br/>
@@ -16,15 +18,17 @@
</p>
</div>
<div class="op-modal--footer">
<button class="confirm-form-submit--continue button"
[ngClass]="dangerHighlighting ? '-danger': '-highlight'"
(click)="confirmAndClose($event)"
[textContent]="text.button_continue"
></button>
<button class="confirm-form-submit--cancel button"
(click)="closeMe($event)"
[textContent]="text.button_cancel"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button class="confirm-form-submit--continue button button_no-margin spot-action-bar--action"
[ngClass]="dangerHighlighting ? '-danger': '-highlight'"
(click)="confirmAndClose($event)"
[textContent]="text.button_continue"
></button>
<button class="confirm-form-submit--cancel button button_no-margin spot-action-bar--action"
(click)="closeMe($event)"
[textContent]="text.button_cancel"
></button>
</div>
</div>
</div>
@@ -86,7 +86,7 @@ export class ConfirmDialogModalComponent extends OpModalComponent {
this.text = _.defaults(this.options.text, this.text);
}
public confirmAndClose(evt:JQuery.TriggeredEvent) {
public confirmAndClose(evt:Event):void {
this.confirmed = true;
this.closeMe(evt);
}
@@ -1,30 +1,32 @@
<form
class="op-modal "
class="spot-modal "
(submit)="applyAndClose($event)"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body form">
<div class="spot-divider"></div>
<div class="spot-modal--body form">
<fieldset class="form--fieldset">
<legend [textContent]="text.page"></legend>
<div class="form--field">
<label
for="selected-page"
[textContent]="text.page"
class="form--label hidden-for-sighted">
for="selected-page"
[textContent]="text.page"
class="form--label hidden-for-sighted">
</label>
<div class="form--field-container">
<div class="form--select-container">
<input
#selectedPageInput
tabindex="2"
type="text"
id="selected-page"
name="selected-page"
[value]="selectedPage"
(change)="selectedPage = $event.target.value"
class="form--select"
placeholder="my-project:my-page" />
#selectedPageInput
tabindex="2"
type="text"
id="selected-page"
name="selected-page"
[value]="selectedPage"
(change)="selectedPage = $event.target.value"
class="form--select"
placeholder="my-project:my-page"/>
</div>
</div>
</div>
@@ -33,14 +35,14 @@
<label class="form--label-with-check-box">
<div class="form--check-box-container">
<input
#parentIncludedInput
tabindex="3"
type="checkbox"
id="include-parent"
name="include-parent"
[ngModel]="selectedIncludeParent"
(ngModelChange)="updateIncludeParent($event)"
class="form--check-box" />
#parentIncludedInput
tabindex="3"
type="checkbox"
id="include-parent"
name="include-parent"
[ngModel]="selectedIncludeParent"
(ngModelChange)="updateIncludeParent($event)"
class="form--check-box"/>
</div>
{{ text.include_parent }}
</label>
@@ -49,18 +51,20 @@
<p [textContent]="text.hint"></p>
</fieldset>
</div>
<div class="op-modal--footer">
<button
class="op-modal--cancel-button button"
(click)="closeMe($event)"
type="button"
tabindex="4"
[textContent]="text.button_cancel"
></button>
<button
class="op-modal--submit-button button -highlight"
tabindex="3"
[textContent]="text.button_save"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="spot-modal--cancel-button button button_no-margin spot-action-bar--action"
(click)="closeMe($event)"
type="button"
tabindex="4"
[textContent]="text.button_cancel"
></button>
<button
class="spot-modal--submit-button button button_no-margin -highlight spot-action-bar--action"
tabindex="3"
[textContent]="text.button_save"
></button>
</div>
</div>
</form>
@@ -77,18 +77,18 @@ export class ChildPagesMacroModalComponent extends OpModalComponent implements A
// We could provide an autocompleter here to get correct page names
}
public applyAndClose(evt:JQuery.TriggeredEvent) {
public applyAndClose(evt:Event):void {
this.changed = true;
this.page = this.selectedPage;
this.includeParent = this.selectedIncludeParent;
this.closeMe(evt);
}
ngAfterViewInit() {
ngAfterViewInit():void {
this.selectedPageInput.nativeElement.focus();
}
updateIncludeParent(val:boolean) {
updateIncludeParent(val:boolean):void {
this.selectedIncludeParent = val;
}
}
@@ -1,10 +1,12 @@
<form
class="op-modal "
class="spot-modal "
(submit)="applyAndClose($event)"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<textarea name="codemirror-element"
id="codemirror-element"
[ngModel]="content"
@@ -12,39 +14,41 @@
<hr/>
<div class="form--field">
<label
for="selected-language"
[textContent]="text.language"
class="form--label hidden-for-sighted">
for="selected-language"
[textContent]="text.language"
class="form--label hidden-for-sighted">
</label>
<div class="form--field-container">
<div class="form--select-container">
<input
#selectedLanguage
tabindex="2"
type="text"
id="selected-language"
name="selected-language"
[ngModel]="language"
(ngModelChange)="updateLanguage($event)"
class="form--select" />
#selectedLanguage
tabindex="2"
type="text"
id="selected-language"
name="selected-language"
[ngModel]="language"
(ngModelChange)="updateLanguage($event)"
class="form--select"/>
</div>
</div>
<p [textContent]="text.language_hint"></p>
</div>
</div>
<div class="op-modal--footer">
<button
class="op-modal--cancel-button button"
(click)="closeMe($event)"
tabindex="4"
type="button"
[textContent]="text.button_cancel"
></button>
<button
class="op-modal--submit-button button -highlight"
tabindex="3"
[textContent]="text.button_save"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="spot-modal--cancel-button button button_no-margin spot-action-bar--action"
(click)="closeMe($event)"
tabindex="4"
type="button"
[textContent]="text.button_cancel"
></button>
<button
class="spot-modal--submit-button button button_no-margin -highlight spot-action-bar--action"
tabindex="3"
[textContent]="text.button_save"
></button>
</div>
</div>
</form>
@@ -86,7 +86,7 @@ export class CodeBlockMacroModalComponent extends OpModalComponent implements Af
}
}
public applyAndClose(evt:JQuery.TriggeredEvent) {
public applyAndClose(evt:Event):void {
this.content = this.codeMirrorInstance.getValue();
const lang = this.language || 'text';
this.languageClass = `language-${lang}`;
@@ -95,7 +95,7 @@ export class CodeBlockMacroModalComponent extends OpModalComponent implements Af
this.closeMe(evt);
}
ngAfterViewInit() {
ngAfterViewInit():void {
import('codemirror').then((imported:any) => {
const CodeMirror = imported.default;
this.codeMirrorInstance = CodeMirror.fromTextArea(
@@ -1,29 +1,31 @@
<form
class="op-modal"
class="spot-modal"
(submit)="applyAndClose($event)"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<fieldset class="form--fieldset">
<legend [textContent]="text.page"></legend>
<div class="form--field">
<label
for="selected-page"
[textContent]="text.page"
class="form--label hidden-for-sighted">
for="selected-page"
[textContent]="text.page"
class="form--label hidden-for-sighted">
</label>
<div class="form--field-container">
<div class="form--select-container">
<input
#selectedPageInput
tabindex="2"
type="text"
id="selected-page"
name="selected-page"
[value]="selectedPage"
(change)="selectedPage = $event.target.value"
class="form--select" />
#selectedPageInput
tabindex="2"
type="text"
id="selected-page"
name="selected-page"
[value]="selectedPage"
(change)="selectedPage = $event.target.value"
class="form--select"/>
</div>
</div>
<p [textContent]="text.hint"></p>
@@ -31,20 +33,22 @@
</div>
</fieldset>
</div>
<div class="op-modal--footer">
<button
class="op-modal--cancel-button button"
(click)="closeMe($event)"
tabindex="4"
[textContent]="text.button_cancel"
[attr.title]="text.button_cancel"
></button>
<button
class="op-modal--submit-button button -highlight"
(click)="applyAndClose($event)"
tabindex="3"
[textContent]="text.button_save"
[attr.title]="text.button_save"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="spot-modal--cancel-button button button_no-margin spot-action-bar--action"
(click)="closeMe($event)"
tabindex="4"
[textContent]="text.button_cancel"
[attr.title]="text.button_cancel"
></button>
<button
class="spot-modal--submit-button button button_no-margin -highlight spot-action-bar--action"
(click)="applyAndClose($event)"
tabindex="3"
[textContent]="text.button_save"
[attr.title]="text.button_save"
></button>
</div>
</div>
</form>
@@ -71,13 +71,13 @@ export class WikiIncludePageMacroModalComponent extends OpModalComponent impleme
// We could provide an autocompleter here to get correct page names
}
public applyAndClose(evt:JQuery.TriggeredEvent) {
public applyAndClose(evt:Event):void {
this.changed = true;
this.page = this.selectedPage;
this.closeMe(evt);
}
ngAfterViewInit() {
ngAfterViewInit():void {
this.selectedPageInput.nativeElement.focus();
}
}
@@ -1,28 +1,30 @@
<form
class="op-modal op-modal_autoheight loading-indicator--location"
class="spot-modal spot-modal_autoheight loading-indicator--location"
(submit)="applyAndClose($event)"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body form">
<div class="spot-divider"></div>
<div class="spot-modal--body form">
<fieldset class="form--fieldset">
<legend [textContent]="text.selected_type"></legend>
<div class="form--field">
<label
for="selected-type"
[textContent]="text.selected_type"
class="form--label hidden-for-sighted">
for="selected-type"
[textContent]="text.selected_type"
class="form--label hidden-for-sighted">
</label>
<div class="form--field-container">
<div class="form--select-container">
<select
#typeSelect
id="selected-type"
tabindex="1"
name="selected-type"
(change)="selectedType = $event.target.value"
class="form--select">
#typeSelect
id="selected-type"
tabindex="1"
name="selected-type"
(change)="selectedType = $event.target.value"
class="form--select">
<option [textContent]="text.none"
[selected]="!selectedType"
[value]=""></option>
@@ -56,18 +58,20 @@
<p [textContent]="text.button_style_hint"></p>
</div>
<div class="op-modal--footer">
<button
class="op-modal--cancel-button button"
(click)="closeMe($event)"
tabindex="4"
type="button"
[textContent]="text.button_cancel"
></button>
<button
class="op-modal--submit-button button -highlight"
tabindex="3"
[textContent]="text.button_save"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="spot-modal--cancel-button button button_no-margin spot-action-bar--action"
(click)="closeMe($event)"
tabindex="4"
type="button"
[textContent]="text.button_cancel"
></button>
<button
class="spot-modal--submit-button button button_no-margin -highlight spot-action-bar--action"
tabindex="3"
[textContent]="text.button_save"
></button>
</div>
</div>
</form>
@@ -95,14 +95,14 @@ export class WpButtonMacroModalComponent extends OpModalComponent implements Aft
});
}
public applyAndClose(evt:JQuery.TriggeredEvent) {
public applyAndClose(evt:Event):void {
this.changed = true;
this.classes = this.buttonStyle ? 'button' : '';
this.type = this.selectedType;
this.closeMe(evt);
}
ngAfterViewInit() {
ngAfterViewInit():void {
this.typeSelect.nativeElement.focus();
}
}
@@ -1,7 +1,10 @@
<div class="op-modal op-modal_wide wp-table--configuration-modal op-wp-table-export">
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal spot-modal_wide wp-table--configuration-modal op-wp-table-export">
<div class="op-modal--body">
<div class="spot-modal--header">{{text.title}}</div>
<div class="spot-divider"></div>
<div class="spot-modal--body">
<ul *ngIf="exportOptions" class="op-export-options" [ngClass]="{'-hidden': isLoading}">
<li
*ngFor="let option of exportOptions"
@@ -1,4 +1,4 @@
<div
class="op-modal dynamic-content-modal--wrapper loading-indicator--location"
class="spot-modal dynamic-content-modal--wrapper loading-indicator--location"
data-indicator-name="modal"
></div>
@@ -50,7 +50,7 @@ export class DynamicContentModalComponent extends OpModalComponent implements On
super(locals, cdRef, elementRef);
}
ngOnInit() {
ngOnInit():void {
super.ngOnInit();
// Append the dynamic body
@@ -58,20 +58,9 @@ export class DynamicContentModalComponent extends OpModalComponent implements On
.find('.dynamic-content-modal--wrapper')
.addClass(this.locals.modalClassName)
.append(this.locals.modalBody);
// Register click listeners
// This registers both on the close button in the modal header, as well as on any
// other elements you have added the dynamic-content-modal--close-button class.
jQuery(document.body)
.on('click.opdynamicmodal',
'.op-modal--close-button, [dynamic-content-modal-close-button]',
(evt:JQuery.TriggeredEvent) => {
this.closeMe(evt);
});
}
ngOnDestroy() {
jQuery(document.body).off('click.opdynamicmodal');
ngOnDestroy():void {
super.ngOnDestroy();
}
}
@@ -1,13 +1,13 @@
<form
class="op-modal op-modal_autoheight form -vertical confirm-form-submit--modal password-confirm-dialog--modal loading-indicator--location"
class="spot-modal form -vertical confirm-form-submit--modal password-confirm-dialog--modal loading-indicator--location"
data-indicator-name="modal"
(submit)="confirmAndClose($event)"
>
<op-modal-header (close)="closeMe($event)">
{{text.title}}
</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body request-for-confirmation--form form">
<div class="spot-divider"></div>
<div class="spot-modal--body request-for-confirmation--form form">
<div class="form--field -required">
<label class="form--label"
for="request_for_confirmation_password"
@@ -28,11 +28,14 @@
</div>
</div>
<div class="op-modal--footer">
<button
class="confirm-form-submit--continue button -highlight"
[textContent]="text.confirm_button"
[disabled]="!passwordValuePresent()">
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="confirm-form-submit--continue button button_no-margin -highlight spot-action-bar--action"
[textContent]="text.confirm_button"
[disabled]="!passwordValuePresent()">
>
</button>
</div>
</div>
</form>
@@ -39,7 +39,7 @@ export class PasswordConfirmationModalComponent extends ConfirmDialogModalCompon
@ViewChild('passwordConfirmationField', { static: true }) passwordConfirmationField:ElementRef;
public ngOnInit() {
public ngOnInit():void {
super.ngOnInit();
this.text.title = I18n.t('js.password_confirmation.title');
@@ -52,18 +52,18 @@ export class PasswordConfirmationModalComponent extends ConfirmDialogModalCompon
this.showClose = false;
}
public confirmAndClose(evt:JQuery.TriggeredEvent) {
public confirmAndClose(evt:Event):void {
if (this.passwordValuePresent()) {
super.confirmAndClose(evt);
}
}
public onOpen(modalElement:JQuery) {
super.onOpen(modalElement);
public onOpen():void {
super.onOpen();
this.passwordConfirmationField.nativeElement.focus();
}
public passwordValuePresent() {
public passwordValuePresent():boolean {
return this.password_confirmation !== null && this.password_confirmation.length > 0;
}
}
@@ -1,28 +1,30 @@
<form
class="op-modal wp-table--configuration-modal loading-indicator--location"
class="spot-modal wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
name="modalSaveForm"
(submit)="saveQueryAs($event)"
>
<op-modal-header (close)="closeMe($event)">{{text.save_as}}</op-modal-header>
<div class="spot-modal--header">{{text.save_as}}</div>
<div class="spot-divider"></div>
<div
name="modalSaveForm"
class="op-modal--body form"
class="spot-modal--body form"
>
<div class="form--field -required">
<label class="form--label" for="save-query-name" [textContent]="text.label_name"></label>
<div class="form--field-container">
<div class="form--text-field-container">
<input
class="form--text-field"
type="text"
name="save-query-name"
id="save-query-name"
#queryNameField
[(ngModel)]="queryName"
required
/>
class="form--text-field"
type="text"
name="save-query-name"
id="save-query-name"
#queryNameField
[(ngModel)]="queryName"
required
/>
</div>
</div>
</div>
@@ -30,25 +32,27 @@
<section class="form--section">
<h3 [textContent]="text.label_visibility_settings"></h3>
<query-sharing-form
[isSave]="true"
(onChange)="setValues($event)"
[isStarred]="isStarred"
[isPublic]="isPublic">
[isSave]="true"
(onChange)="setValues($event)"
[isStarred]="isStarred"
[isPublic]="isPublic">
</query-sharing-form>
</section>
</div>
<div class="op-modal--footer">
<button
type="button"
class="button -with-icon icon-cancel"
[textContent]="text.button_cancel"
(click)="closeMe($event)"
></button>
<button
class="button -highlight -with-icon icon-checkmark"
[textContent]="text.button_save"
[disabled]="isBusy || !queryName"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
type="button"
class="button button_no-margin -with-icon icon-cancel spot-action-bar--action"
[textContent]="text.button_cancel"
(click)="closeMe($event)"
></button>
<button
class="button button_no-margin -highlight -with-icon icon-checkmark spot-action-bar--action"
[textContent]="text.button_save"
[disabled]="isBusy || !queryName"
></button>
</div>
</div>
</form>
@@ -91,7 +91,7 @@ export class SaveQueryModalComponent extends OpModalComponent {
return jQuery('#work-packages-settings-button');
}
public saveQueryAs($event:JQuery.TriggeredEvent) {
public saveQueryAs($event:Event):void {
$event.preventDefault();
if (this.isBusy || !this.queryName) {
@@ -1,26 +1,30 @@
<div
class="op-modal wp-table--configuration-modal loading-indicator--location"
class="spot-modal wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header (close)="closeMe($event)">{{text.label_visibility_settings}}</op-modal-header>
<div class="spot-modal--header">{{text.label_visibility_settings}}</div>
<div class="spot-divider"></div>
<query-sharing-form
class="op-modal--body"
[isSave]="false"
(onChange)="setValues($event)"
[isStarred]="isStarred"
[isPublic]="isPublic">
class="spot-modal--body"
[isSave]="false"
(onChange)="setValues($event)"
[isStarred]="isStarred"
[isPublic]="isPublic">
</query-sharing-form>
<div class="op-modal--footer">
<button class="button -highlight -with-icon icon-checkmark"
(click)="saveQuery($event)"
[textContent]="text.button_save">
</button>
<button class="button -with-icon icon-cancel"
[textContent]="text.button_cancel"
[disabled]="isBusy"
(click)="closeMe($event)">
</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button class="button button_no-margin -highlight -with-icon icon-checkmark spot-action-bar--action"
(click)="saveQuery($event)"
[textContent]="text.button_save">
</button>
<button class="button button_no-margin -with-icon icon-cancel spot-action-bar--action"
[textContent]="text.button_cancel"
[disabled]="isBusy"
(click)="closeMe($event)">
</button>
</div>
</div>
</div>
@@ -94,7 +94,7 @@ export class QuerySharingModalComponent extends OpModalComponent implements OnIn
return jQuery('#work-packages-settings-button');
}
public saveQuery($event:JQuery.TriggeredEvent) {
public saveQuery($event:Event):void {
if (this.isBusy) {
return;
}
@@ -1,11 +1,13 @@
<div
class="op-modal op-modal_autoheight wp-table--configuration-modal -danger-zone loading-indicator--location"
class="spot-modal wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
id="wp_destroy_modal"
>
<op-modal-header (close)="closeMe($event)">{{text.title}}</op-modal-header>
<div class="spot-modal--header">{{text.title}}</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<ng-container *ngIf="singleWorkPackage">
<p>
<span [textContent]="text.text"></span>
@@ -56,24 +58,26 @@
name="confirm-children-deletion"
id="confirm-children-deletion"
[(ngModel)]="childrenDeletionConfirmed"
class="form--check-box" />
class="form--check-box"/>
</div>
{{ text.label_confirm_children_deletion }}
</label>
</div>
</div>
<div class="op-modal--footer">
<button
class="button"
[textContent]="text.cancel"
(click)="closeMe($event)"
></button>
<button
class="button -danger"
[textContent]="text.confirm"
[attr.disabled]="busy || blockedDueToUnconfirmedChildren || undefined"
(click)="confirmDeletion($event)"
></button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="button button_no-margin spot-action-bar--action"
[textContent]="text.cancel"
(click)="closeMe($event)"
></button>
<button
class="button button_no-margin -danger spot-action-bar--action"
[textContent]="text.confirm"
[attr.disabled]="busy || blockedDueToUnconfirmedChildren || undefined"
(click)="confirmDeletion($event)"
></button>
</div>
</div>
</div>
@@ -35,12 +35,17 @@ import { OpModalComponent } from 'core-app/shared/components/modal/modal.compone
import { OpModalLocalsToken } from 'core-app/shared/components/modal/modal.service';
import { OpModalLocalsMap } from 'core-app/shared/components/modal/modal.types';
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import { WorkPackageViewFocusService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-focus.service';
import {
WorkPackageViewFocusService,
} from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-focus.service';
import { StateService } from '@uirouter/core';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { BackRoutingService } from 'core-app/features/work-packages/components/back-routing/back-routing.service';
import { WorkPackageNotificationService } from 'core-app/features/work-packages/services/notifications/work-package-notification.service';
import {
WorkPackageNotificationService,
} from 'core-app/features/work-packages/services/notifications/work-package-notification.service';
import { WorkPackageService } from 'core-app/features/work-packages/services/work-package.service';
import isNotNull from 'core-app/core/state/is-not-null';
@Component({
templateUrl: './wp-destroy.modal.html',
@@ -61,7 +66,7 @@ export class WpDestroyModalComponent extends OpModalComponent implements OnInit
// Need to confirm deletion when children are involved
public childrenDeletionConfirmed = false;
public text:any = {
public text = {
label_visibility_settings: this.I18n.t('js.label_visibility_settings'),
button_save: this.I18n.t('js.modals.button_save'),
confirm: this.I18n.t('js.button_confirm'),
@@ -69,10 +74,17 @@ export class WpDestroyModalComponent extends OpModalComponent implements OnInit
cancel: this.I18n.t('js.button_cancel'),
close: this.I18n.t('js.close_popup_title'),
label_confirm_children_deletion: this.I18n.t('js.modals.destroy_work_package.confirm_deletion_children'),
title: '',
text: '',
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
childCount: (wp:WorkPackageResource):string => '',
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
hasChildren: (wp:WorkPackageResource):string => '',
deletesChildren: '',
};
constructor(readonly elementRef:ElementRef,
readonly WorkPackageService:WorkPackageService,
readonly workPackageService:WorkPackageService,
@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
readonly I18n:I18nService,
readonly cdRef:ChangeDetectorRef,
@@ -85,7 +97,7 @@ export class WpDestroyModalComponent extends OpModalComponent implements OnInit
super(locals, cdRef, elementRef);
}
ngOnInit() {
ngOnInit():void {
super.ngOnInit();
this.workPackages = this.locals.workPackages;
@@ -97,7 +109,7 @@ export class WpDestroyModalComponent extends OpModalComponent implements OnInit
this.singleWorkPackageChildren = this.singleWorkPackage.children;
}
this.text.title = this.I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }),
this.text.title = this.I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel });
this.text.text = this.I18n.t('js.modals.destroy_work_package.text', {
label: this.workPackageLabel,
count: this.workPackages.length,
@@ -108,32 +120,37 @@ export class WpDestroyModalComponent extends OpModalComponent implements OnInit
return this.I18n.t('js.units.child_work_packages', { count });
};
this.text.hasChildren = (wp:WorkPackageResource) => this.I18n.t('js.modals.destroy_work_package.has_children', { childUnits: this.text.childCount(wp) }),
this.text.hasChildren = (wp:WorkPackageResource) => {
const childUnits = this.text.childCount(wp);
return this.I18n.t('js.modals.destroy_work_package.has_children', { childUnits });
};
this.text.deletesChildren = this.I18n.t('js.modals.destroy_work_package.deletes_children');
}
public get blockedDueToUnconfirmedChildren() {
public get blockedDueToUnconfirmedChildren():boolean {
return this.mustConfirmChildren && !this.childrenDeletionConfirmed;
}
public get mustConfirmChildren() {
const result = false;
public get mustConfirmChildren():boolean {
let result = false;
if (this.singleWorkPackage && this.singleWorkPackageChildren) {
const result = this.singleWorkPackageChildren.length > 0;
result = this.singleWorkPackageChildren.length > 0;
}
return result || !!_.find(this.workPackages, (wp) => wp.children && wp.children.length > 0);
}
public confirmDeletion($event:JQuery.TriggeredEvent) {
public confirmDeletion($event:Event):boolean {
if (this.busy || this.blockedDueToUnconfirmedChildren) {
return false;
}
this.busy = true;
this.WorkPackageService.performBulkDelete(this.workPackages.map((el) => el.id!), true)
const ids = this.workPackages
.map((el) => el.id)
.filter(isNotNull);
this.workPackageService.performBulkDelete(ids, true)
.then(() => {
this.busy = false;
this.closeMe($event);
@@ -1,14 +1,15 @@
<div
class="op-modal op-modal_autoheight loading-indicator--location"
class="spot-modal loading-indicator--location"
data-indicator-name="modal"
>
<op-modal-header
icon="icon-log_time"
(close)="closeMe($event)">
{{text.title}}
</op-modal-header>
<div class="spot-modal--header">
<span class="spot-icon spot-icon_time"></span>
<span [textContent]="text.title"></span>
</div>
<div class="ngdialog-body op-modal--body">
<div class="spot-divider"></div>
<div class="ngdialog-body spot-modal--body">
<te-form #editForm
[changeset]="changeset"
[showWorkPackageField]="showWorkPackageField"
@@ -17,23 +18,23 @@
</te-form>
</div>
<div class="op-modal--footer op-modal--footer_split-actions">
<div>
<button class="button -danger"
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--left">
<button class="button button_no-margin -danger spot-action-bar--action"
*ngIf="deleteAllowed"
(click)="destroy()"
[textContent]="text.delete"
[attr.title]="text.delete">
</button>
</div>
<div>
<button class="button"
<div class="spot-action-bar--right">
<button class="button button_no-margin spot-action-bar--action"
*ngIf="saveAllowed"
(click)="closeMe($event)"
[textContent]="text.cancel"
[attr.title]="text.cancel">
</button>
<button class="button -highlight button_no-margin"
<button class="button -highlight button_no-margin spot-action-bar--action"
*ngIf="saveAllowed"
(click)="saveEntry()"
[attr.title]="text.save"
+51 -8
View File
@@ -89,22 +89,26 @@ Currently selected value is {{ toggleValue }}
<h1>Checkbox</h1>
<label>
<spot-checkbox></spot-checkbox> Unchecked
<spot-checkbox></spot-checkbox>
Unchecked
</label>
<label>
<spot-checkbox [checked]="true"></spot-checkbox> Checked
<spot-checkbox [checked]="true"></spot-checkbox>
Checked
</label>
<label>
<spot-checkbox [disabled]="true"></spot-checkbox> Disabled
<spot-checkbox [disabled]="true"></spot-checkbox>
Disabled
</label>
<label>
<spot-checkbox
[checked]="true"
[disabled]="true"
></spot-checkbox> Disabled checked
></spot-checkbox>
Disabled checked
</label>
<label>
@@ -454,7 +458,8 @@ Currently selected value is {{ toggleValue }}
type="button"
class="spot-button spot-button_main"
(click)="dropModalOpen = !dropModalOpen"
>Open Modal</button>
>Open Modal
</button>
<ng-container slot="body">
<div class="spot-container">
<h1 class="spot-header-small">Test</h1>
@@ -520,20 +525,58 @@ Currently selected value is {{ toggleValue }}
<div class="spot-action-bar">
<div class="spot-action-bar--left">
<button class="spot-button spot-button_outlined spot-button_main">
<button class="spot-button spot-button_outlined spot-button_main spot-action-bar--action">
Independent action
</button>
</div>
<div class="spot-action-bar--right">
<button class="spot-button spot-button_outlined spot-button_main">
<button class="spot-button spot-button_outlined spot-button_main spot-action-bar--action">
Some Action
</button>
<button class="spot-button spot-button_main">
<button class="spot-button spot-button_main spot-action-bar--action">
Another Action
</button>
</div>
</div>
<h1>Modals</h1>
<div class="spot-modal">
<div class="spot-modal--header">Default size modal</div>
<div class="spot-modal--body">Here is some text in the body. Additionally this is a destructive action.</div>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button class="spot-button spot-button_outlined spot-button_main spot-action-bar--action">
Cancel
</button>
<button class="spot-button spot-button_danger spot-action-bar--action">
<span class="spot-icon spot-icon_delete"></span>
<span>Delete</span>
</button>
</div>
</div>
</div>
<div class="spot-modal spot-modal_wide">
<div class="spot-modal--header">
<span class="spot-icon spot-icon_help1"></span>
<span>Wide modal</span>
</div>
<div class="spot-divider"></div>
<div class="spot-modal--body">
<p>Here is some text in the body.</p>
<p>But this modal has a mininmal height!</p>
</div>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<span>Some explanatory text.</span>
<button class="spot-button spot-button_main spot-action-bar--action">
OK
</button>
</div>
</div>
</div>
<style>
#content-wrapper {
background-color: #eee;
@@ -1,7 +1,7 @@
.spot-action-bar
display: grid
grid-template-columns: 1fr
padding: $spot-spacing-0-75
padding: $spot-spacing-1
background-color: $spot-color-basic-gray-6
&--left,
@@ -13,11 +13,11 @@
justify-content: flex-end
> .spot-action-bar--action
margin-left: $spot-spacing-0_5
margin-left: $spot-spacing-1
&--left
> .spot-action-bar--action
margin-bottom: $spot-spacing-0_5
margin-bottom: $spot-spacing-1
@media #{$spot-mq-action-bar-change}
grid-template-columns: 1fr auto
@@ -0,0 +1,5 @@
.spot-divider
border-bottom: 1px solid $spot-color-basic-gray-5
&_strong
border-bottom: 1px solid $spot-color-basic-gray-4
@@ -1,6 +1,7 @@
// This directory will hold files that implement the styles for specific blocks and components
// Import them here
@import './button'
@import './divider'
@import './link'
@import './toggle'
@import './checkbox'
@@ -8,5 +9,6 @@
@import './filter-chip'
@import './drop-modal'
@import './list'
@import './modal'
@import './action-bar'
@import './tooltip'
@@ -0,0 +1,9 @@
.spot-modal-close-button
display: block
margin: 1rem
@media (min-width: 680px)
display: none
@media (max-height: 480px)
align-self: end
@@ -1,4 +1,4 @@
.op-modal-overlay
.spot-modal-overlay
position: fixed
top: 0
left: 0
@@ -12,9 +12,17 @@
&_active
display: flex
flex-direction: column-reverse
@media (max-width: 680px)
justify-content: end
@media (max-height: 480px)
// reorder elements to be displayed in row on very small heights
flex-direction: row-reverse
&_not-full-screen
background: transparent
right: unset
bottom: unset
top: initial
top: initial
@@ -1,7 +1,10 @@
// Some backend modals come wrapped once extra. Because of the way
// augmented modals are loaded, this is not so easy to change.
// TODO: When refactoring the modal service, this should be removed
.op-modal > .form:only-child
.spot-modal > .form:only-child
display: flex
flex-direction: column
max-height: 100vh
.modal-delivery-element
display: none
@@ -0,0 +1,68 @@
@import './modal-close-button'
@import './modal-overlay'
@import './modal-overrides'
.spot-modal
position: relative
display: flex
flex-direction: column
align-items: stretch
background: white
pointer-events: all
border-radius: $spot-spacing-0-25
width: 40rem
max-width: calc(100vw - 2rem)
max-height: calc(100vh - 2rem)
overflow-y: auto
@media (max-width: 680px)
width: calc(100vw - 2rem)
max-height: calc(100vh - 5rem)
@media (max-height: 480px)
max-height: calc(100vh - 2rem)
max-width: calc(100vw - 6rem)
&_wide
width: 70rem
min-height: 40vh
&--header
@include spot-subheader-big
display: flex
padding: $spot-spacing-1
position: relative
align-items: center
.spot-icon
width: $spot-spacing-1-5
height: $spot-spacing-1-5
margin-right: $spot-spacing-0-5
&_highlight
background-color: var(--header-bg-color)
border-bottom-width: var(--header-border-bottom-width)
border-bottom-color: var(--header-border-bottom-color)
*
color: var(--header-item-font-color)
&--body
@include styled-scroll-bar
display: flex
flex-direction: column
padding: 1rem
flex-grow: 1
flex-shrink: 1
overflow-y: auto
&:focus
outline-style: none
&--footer
width: 100%
+1 -1
View File
@@ -56,4 +56,4 @@ $spot-shadow-hard-mid: 4px 4px 10px rgba(0, 0, 0, 0.25)
$spot-shadow-hard-high: 6px 6px 20px rgba(0, 0, 0, 0.25)
$spot-mq-landscape: '(orientation: landscape)'
$spot-mq-drop-modal-in-context: '(min-width: 1000px) and (min-height: 500px)'
$spot-mq-action-bar-change: '(min-width: 768px)'
$spot-mq-action-bar-change: '(min-width: 600px)'
@@ -50,8 +50,6 @@
max-width: 100%
#tab-content-info form,
.op-modal--body form:not(.-vertical),
form.-wide-labels .op-modal--body
.form--label,
.form--field-container
flex-basis: 100% !important
+24 -53
View File
@@ -3,14 +3,12 @@
## Modals: Standard style
```
<div class="op-modal">
<div class="op-modal--header">
<h3>Export</h3>
<a class="op-modal--close-button">
<i class="icon-close" title="Close popup"></i>
</a>
<div class="spot-modal">
<div class="spot-modal--header">
Export
</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<ul class="export-options">
<li>
<a>
@@ -50,60 +48,33 @@
</li>
</ul>
</div>
</div>
```
## Modals: Highlighted and with footer
```
<div class="op-modal -highlight">
<div class="op-modal--header">
<h2>Welcome to OpenProject</h2>
<a class="op-modal--close-button" title="Close popup">
<i class="icon-close"></i>
</a>
</div>
<div class="op-modal--body">
<b>Please select your language</b>
<fieldset class="form--fieldset">
<div class="form--field">
<label class="form--label" title="Language" for="user_language">Language</label>
<span class="form--field-container">
<span class="form--select-container -slim">
<select class="form--select">
<option value="de">Deutsch</option>
<option selected="selected" value="en">English</option>
<option value="fr">Français</option>
</select>
</span>
</span>
</div>
</fieldset>
</div>
<div class="op-modal--footer">
<button name="button" type="submit" class="button -highlight">Save</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button name="button" type="submit" class="button button_no-margin spot-action-bar--action">Close</button>
</div>
</div>
</div>
```
## Modals: Danger zone highlighting
```
<div class="op-modal -highlight -danger-zone">
<div class="op-modal--header">
<h3 class="icon-context icon-warning">Confirm deletion of Work Package</h3>
<a class="op-modal--close-button" title="Close popup">
<i class="icon-close"></i>
</a>
## Modals: Danger zone (highlighted buttons)
```
<div class="spot-modal">
<div class="spot-modal--header">
<span class="spot-icon spot-icon_warning"></span>
<span>Confirm deletion of Work Package</span>
</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<p>Are you sure you want to delete the following work package?<p>
<p> ... </p>
</div>
<div class="op-modal--footer">
<button name="button" type="submit" class="button -danger">Continue</button>
<button name="button" type="submit" class="button">Cancel</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button name="button" type="submit" class="button button_no-margin spot-action-bar--action">Cancel</button>
<button name="button" type="submit" class="button button_no-margin -danger spot-action-bar--action">Continue</button>
</div>
</div>
</div>
```
@@ -19,7 +19,6 @@
.op-app-header #nav-login-content,
#content,
.op-modal,
.login-auth-providers a.auth-provider
background-repeat: no-repeat
background-size: 18px 18px
@@ -43,6 +43,7 @@
margin: 0
line-height: 1.6em
color: inherit
word-break: break-all
.op-uc-blockquote
display: block
@@ -8,7 +8,6 @@
@import "content/_index.sass"
@import "./common/openproject-common.module"
@import "../app/shared/components/modal/modal.module"
@import "../app/shared/directives/search-highlight.directive"
// Dynamically linked plugin styles from Rails plugins
@@ -36,7 +36,7 @@ See COPYRIGHT and LICENSE files for more details.
.op-app-header #nav-login-content .login-auth-providers a.auth-provider.auth-provider-<%= pro[:name] %> {
background-image: url('<%= asset_path(pro[:icon]) %>') ;
}
.op-modal .login-auth-providers a.auth-provider.auth-provider-<%= pro[:name] %> {
.login-auth-providers a.auth-provider.auth-provider-<%= pro[:name] %> {
background-image: url('<%= asset_path(pro[:icon]) %>') ;
}
</style>
+1 -1
View File
@@ -88,7 +88,7 @@ describe 'bcf export',
expect(page).to have_text("completed successfully")
# Close the modal
page.find('.op-modal--close-button').click
page.find('.spot-modal-overlay').click
@download_list.refresh_from(page)
@@ -341,7 +341,7 @@ module Pages
def open_and_fill_add_list_modal(name)
open_add_list_modal
sleep(0.1)
page.find('.op-modal .new-list--action-select input').set(name)
page.find('.spot-modal .new-list--action-select input').set(name)
end
def open_add_list_modal
@@ -350,7 +350,7 @@ module Pages
end
def add_list_modal_shows_warning(value, with_link: false)
within page.find('.op-modal') do
within page.find('.spot-modal') do
warning = '.op-toast.-warning'
link = '.op-toast--content a'
@@ -79,9 +79,9 @@ describe 'Project description widget on dashboard', type: :feature, js: true do
editor.insert_macro 'Insert create work package button'
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
select 'Task', from: 'selected-type'
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
field.save!
@@ -137,9 +137,9 @@ describe 'Project description widget on dashboard', type: :feature, js: true do
editor.insert_macro 'Insert create work package button'
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
select 'Task', from: 'selected-type'
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
field.save!
+1 -1
View File
@@ -83,7 +83,7 @@ module Pages
area.hover
area.find('.grid--widget-add', visible: :all).click
within('.op-modal', &)
within('.spot-modal', &)
end
def expect_widget_adding_prohibited_generally(row_number = 1, column_number = 1)
@@ -7,35 +7,29 @@
<%= t(:button_show) %>
</a>
<div class="modal-delivery-element">
<div class="op-modal--header">
<h1 class="op-modal--title">
<%= log_entry.class.human_attribute_name('response_body') %>
</h1>
<button
type="button"
class="op-modal--close-button"
aria-label="<%= t(:button_close) %>"
>
<%= op_icon('icon-close') %>
</button>
<div class="spot-modal--header">
<%= log_entry.class.human_attribute_name('response_body') %>
</div>
<div class="op-modal--body">
<div class="spot-divider"></div>
<div class="spot-modal--body">
<h2>Headers</h2>
<pre class="webhooks--response-headers" ><%- log_entry.response_headers.each do |k,v| -%><strong><%= k -%></strong>: <span><%= v -%></span><br/><%- end -%></pre>
<pre class="webhooks--response-headers"><%- log_entry.response_headers.each do |k, v| -%><strong><%= k -%></strong>: <span><%= v -%></span><br/><%- end -%></pre>
<hr/>
<h2>Response body</h2>
<pre class="webhooks--response-body">
<%= log_entry.response_body %>
</pre>
</div>
<div class="op-modal--footer">
<button
class="button"
title="<%= t(:button_close) %>"
dynamic-content-modal-close-button
>
<%= t(:button_close)%>
</button>
<div class="spot-modal--footer spot-action-bar">
<div class="spot-action-bar--right">
<button
class="button button_no-margin spot-action-bar--action"
title="<%= t(:button_close) %>"
dynamic-content-modal-close-button
>
<%= t(:button_close) %>
</button>
</div>
</div>
</div>
</section>
</section>
@@ -98,7 +98,7 @@ describe 'Manage webhooks through UI', type: :feature, js: true do
SeleniumHubWaiter.wait
find('td.response_body a', text: 'Show').click
page.within('.op-modal') do
page.within('.spot-modal') do
expect(page).to have_selector('.webhooks--response-headers strong', text: 'test')
expect(page).to have_selector('.webhooks--response-body', text: log.response_body)
end
@@ -257,7 +257,7 @@ describe 'Enterprise trial management',
end
it 'can confirm that trial regularly' do
find('.op-modal--body [data-qa-selector="op-ee-trial-waiting-resend-link"]', text: 'Resend').click
find('.spot-modal--body [data-qa-selector="op-ee-trial-waiting-resend-link"]', text: 'Resend').click
expect(page).to have_selector('.op-toast.-success', text: 'Email has been resent.', wait: 20)
expect(page).to have_text 'foo@foocorp.example'
@@ -97,7 +97,7 @@ describe 'onboarding tour for new users', js: true do
expect(page).to have_text 'Please select your language'
# Cancel language selection
click_button('Close popup')
page.find('.spot-modal-overlay').click
# The tutorial appears
expect(page).to have_text sanitize_string(I18n.t('js.onboarding.steps.welcome')), normalize_ws: true
@@ -53,14 +53,15 @@ module Components
def open!
SeleniumHubWaiter.wait
container.find("[data-qa-help-text-for='#{help_text.attribute_name}']").click
expect(page).to have_selector('.attribute-help-text--modal h1', text: help_text.attribute_caption)
expect(page).to have_selector('[data-qa-selector="attribute-help-text--header"]', text: help_text.attribute_caption)
end
def close!
within modal_container do
page.find('.icon-close').click
# make backdrop click an the pixel x:10,y:10
page.find('.spot-modal-overlay').tap do |element|
element.click(x: -((element.native.size.width / 2) - 10), y: -((element.native.size.height / 2) - 10))
end
expect(page).to have_no_selector('.attribute-help-text--modal h1', text: help_text.attribute_caption)
expect(page).to have_no_selector('[data-qa-selector="attribute-help-text--header"]', text: help_text.attribute_caption)
end
def expect_edit(admin:)
@@ -54,7 +54,7 @@ module Components
.to have_text(I18n.t('js.button_log_time'))
end
else
expect(page).to have_no_selector '.op-modal'
expect(page).to have_no_selector '.spot-modal'
end
end
@@ -131,7 +131,7 @@ module Components
end
def modal_container
page.find('.op-modal')
page.find('.spot-modal')
end
end
end
+1 -1
View File
@@ -50,7 +50,7 @@ describe 'invitation spec', type: :feature, js: true do
# Visit invitation link with correct token
visit account_activate_path(token: Token::Invitation.last.value)
expect(page).to have_selector('.op-modal--header', text: 'Welcome to OpenProject')
expect(page).to have_selector('.spot-modal--header', text: 'Welcome to OpenProject')
end
context 'as admin' do
@@ -232,7 +232,7 @@ describe 'date inplace editor',
work_packages_page.accept_alert_dialog! if work_packages_page.has_alert_dialog?
# Ensure no modal survives
expect(page).to have_no_selector('.op-modal')
expect(page).to have_no_selector('.spot-modal')
end
context 'with a date custom field' do
+1 -1
View File
@@ -73,7 +73,7 @@ describe 'work package export', type: :feature do
wait: 10
# Expect title
expect(page).to have_selector 'h1', text: I18n.t('export.your_work_packages_export')
expect(page).to have_selector '[data-qa-selector="job-status--header"]', text: I18n.t('export.your_work_packages_export')
begin
perform_enqueued_jobs
@@ -95,18 +95,18 @@ describe 'Wysiwyg child pages spec',
# Edit widget and cancel again
placeholder.click
page.find('.ck-balloon-panel .ck-button', visible: :all, text: 'Edit').click
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
expect(page).to have_field('selected-page', with: '')
find('.op-modal--cancel-button').click
find('.spot-modal--cancel-button').click
# Edit widget and save
placeholder.click
page.find('.ck-balloon-panel .ck-button', visible: :all, text: 'Edit').click
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
fill_in 'selected-page', with: 'parent-page'
# Save widget
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
# Placeholder states `parent-page` and no `Include parent`
expect(placeholder).to have_text('parent-page')
@@ -135,11 +135,11 @@ describe 'Wysiwyg child pages spec',
# Edit widget and save
placeholder.click
page.find('.ck-balloon-panel .ck-button', visible: :all, text: 'Edit').click
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
page.check 'include-parent'
# Save widget
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
# Placeholder states `parent-page` and `Include parent`
expect(placeholder).to have_text('parent-page')
@@ -98,12 +98,12 @@ describe 'Wysiwyg code block macro',
editor.in_editor do |container,|
editor.click_toolbar_button 'Insert code snippet'
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
# CM wraps an accessor to the editor instance on the outer container
cm = page.find('.CodeMirror')
page.execute_script('arguments[0].CodeMirror.setValue(arguments[1]);', cm.native, 'asdf')
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
expect(container).to have_selector('.op-uc-code-block', text: 'asdf')
@@ -133,7 +133,7 @@ describe 'Wysiwyg code block macro',
editor.in_editor do |container,|
editor.click_toolbar_button 'Insert code snippet'
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
# CM wraps an accessor to the editor instance on the outer container
cm = page.find('.CodeMirror')
@@ -145,7 +145,7 @@ describe 'Wysiwyg code block macro',
expect(page).to have_selector('.cm-keyword', text: 'def')
expect(page).to have_selector('.cm-def', text: 'foobar')
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
# Expect macro saved to editor
expect(container).to have_selector('.op-uc-code-block', text: snippet)
@@ -176,7 +176,7 @@ describe 'Wysiwyg code block macro',
widget = container.find('.op-uc-code-block')
page.driver.browser.action.double_click(widget.native).perform
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
expect(page).to have_selector('.op-uc-code-block--language', text: 'ruby')
expect(page).to have_selector('.cm-keyword', text: 'def')
@@ -58,11 +58,11 @@ describe 'Wysiwyg work package button spec',
editor.in_editor do |_container, editable|
editor.insert_macro 'Insert create work package button'
expect(page).to have_selector('.op-modal')
expect(page).to have_selector('.spot-modal')
select 'MyTaskName', from: 'selected-type'
# Cancel editing
find('.op-modal--cancel-button').click
find('.spot-modal--cancel-button').click
expect(editable).to have_no_selector('.macro.-create_work_package_link')
editor.insert_macro 'Insert create work package button'
@@ -70,7 +70,7 @@ describe 'Wysiwyg work package button spec',
check 'button_style'
# Save widget
find('.op-modal--submit-button').click
find('.spot-modal--submit-button').click
# Find widget, click to show toolbar
modal = find('.button.op-uc-placeholder', text: 'Create work package')
@@ -80,7 +80,7 @@ describe 'Wysiwyg work package button spec',
page.find('.ck-balloon-panel .ck-button', visible: :all, text: 'Edit').click
expect(page).to have_checked_field('wp_button_macro_style')
expect(page).to have_select('selected-type', selected: 'MyTaskName')
find('.op-modal--cancel-button').click
find('.spot-modal--cancel-button').click
end
# Save wiki page
+2 -2
View File
@@ -36,7 +36,7 @@ module Components
def expect_title(text)
within_modal do
expect(page).to have_selector('.op-modal--title', text:)
expect(page).to have_selector('.spot-modal--header', text:)
end
end
@@ -69,7 +69,7 @@ module Components
end
def selector
'.op-modal'
'.spot-modal'
end
end
end
@@ -34,7 +34,7 @@ module Components
def initialize; end
def container
'.op-modal'
'.spot-modal'
end
def expect_open
@@ -57,7 +57,7 @@ module Components
get_select(:right).find('option', text: right).select_option
get_select(:farRight).find('option', text: farRight).select_option
page.within '.op-modal' do
page.within '.spot-modal' do
click_on 'Apply'
end
end
@@ -35,7 +35,7 @@ module Components
def open_and_save_query(name)
open!
find("#{selector} .menu-item", text: 'Save', match: :prefer_exact).click
page.within('.op-modal') do
page.within('.spot-modal') do
find('#save-query-name').set name
click_on 'Save'
end
@@ -97,13 +97,13 @@ module Components
end
def cancel_changes
page.within('.op-modal') do
page.within('.spot-modal') do
click_on 'Cancel'
end
end
def apply_changes
page.within('.op-modal') do
page.within('.spot-modal') do
click_on 'Apply'
end
end

Some files were not shown because too many files have changed in this diff Show More