Skip to content

Commit

Permalink
Migrate patchinfo#edit to Bootstrap
Browse files Browse the repository at this point in the history
Align the old and new UIs for specs and consistency

Co-authored-by: Björn Geuken <bgeuken@suse.de>
Co-authored-by: David Kang <dkang@suse.com>
  • Loading branch information
3 people committed Apr 24, 2019
1 parent 5d6bbe4 commit 85146ae
Show file tree
Hide file tree
Showing 14 changed files with 273 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/api/app/assets/javascripts/webui2/application.js
Expand Up @@ -47,4 +47,5 @@
//= require webui2/project.js
//= require webui2/project_monitor.js
//= require webui2/collapsible_text
//= require webui2/patchinfo.js
//= require rails-timeago
128 changes: 128 additions & 0 deletions src/api/app/assets/javascripts/webui2/patchinfo.js
@@ -0,0 +1,128 @@
function setupPatchinfo() { // jshint ignore:line
addIssuesAjaxBefore();
addIssuesAjaxSuccess();
addIssuesAjaxComplete();
deleteIssueClick();
patchinfoBlockChange();
patchinfoBinariesEvents();
}

function addIssuesAjaxBefore() {
$('#add-issues').on('ajax:before', function() {
var issues = $('#issue_ids').val();
if (issues.length === 0) {
return false;
}

var element = $(this);
element.children('i.fas.fa-plus-circle').addClass('d-none');
element.children('i.fas.fa-spin').removeClass('d-none');

issues = $.unique(issues.replace(/ /g, '').split(','));

element.data('params', { issues: issues, project: element.data('project') });
});
}

function addIssuesAjaxSuccess() {
$('#add-issues').on('ajax:success', function(event, data) {
$('#ajax-error-message').text(data.error);
if (data.error !== '') {
return;
}

addIssues(data.issues);
});
}

function addIssues(issues) {
$.each(issues, function() {
var issueTracker = this[0];
var issueId = this[1];
var issueUrl = this[2];
var issueSum = this[3];

if ($('li#issue_' + issueTracker + '_' + issueId).length > 0) {
return;
}

addIssuesHtml(issueTracker, issueId, issueUrl, issueSum);
});
}

function addIssuesHtml(issueTracker, issueId, issueUrl, issueSum) {
var identifier = issueTracker + '_' + issueId;

$('#issues').append(
$('<div>', { id: 'issue_' + identifier, class: 'list-group-item flex-column align-items-start issue-element' }).append(
$('<div>', { class: 'd-flex w-100 mb-1' }).append(
$('<a>', { href: issueUrl, target: '_blank', rel: 'noopener' }).append(
$('<i>', { class: 'fa fa-bug text-danger' })
).append(' ' + issueTracker + '#' + issueId),
$('<a>', { id: 'delete_issue_' + identifier, href: '#', title: 'Delete', class: 'ml-1' }).append(
$('<i>', { class: 'fas fa-times-circle text-danger' })
),
$('<input>', { type: 'hidden', name: 'patchinfo[issueid][]', id: 'issueid_' + identifier, value: issueId, multiple: true }),
$('<input>', { type: 'hidden', name: 'patchinfo[issuetracker][]', id: 'issuetracker_' + identifier, value: issueTracker, multiple: true }),
$('<input>', { type: 'hidden', name: 'patchinfo[issueurl][]', id: 'issueurl_' + identifier, value: issueUrl, multiple: true }),
$('<input>', { type: 'hidden', name: 'patchinfo[issuesum][]', id: 'issueurl_' + identifier, value: issueSum, multiple: true })),
$('<small>', { class: 'text-muted' }).append(issueSum)
)
);
}

function addIssuesAjaxComplete() {
$('#add-issues').on('ajax:complete', function() {
var element = $(this);
element.children('i.fas.fa-spin').addClass('d-none');
element.children('i.fas.fa-plus-circle').removeClass('d-none');
$('#issue_ids').val('');
});
}

function deleteIssueClick() {
$(document).on('click', 'a[id^="delete_issue_"]', function(event) {
event.preventDefault();

$(this).parents('.issue-element').remove();
});
}

function patchinfoBlockChange() {
$('#patchinfo_block').change(function() {
$('#patchinfo_block_reason').prop('disabled', !this.checked);
});
}

function patchinfoBinariesEvents() {
// Without this, selected binaries are always reset
$("form").submit(function () {
$('#patchinfo_binaries option').prop('selected', true);
$('#available_binaries option').prop('selected', true);
});

$('#select-binary').click(function () {
$("#patchinfo_binaries option[value='']").remove();
moveBinaries('#available_binaries', '#patchinfo_binaries');
});
$('#select-binaries').click(function () {
$("#patchinfo_binaries option[value='']").remove();
$('#available_binaries option').prop('selected', 'true');
moveBinaries('#available_binaries', '#patchinfo_binaries');
});
$('#unselect-binaries').click(function () {
$('#patchinfo_binaries option').prop('selected', 'true');
moveBinaries('#patchinfo_binaries', '#available_binaries');
});
$('#unselect-binary').click(function () {
moveBinaries('#patchinfo_binaries', '#available_binaries');
});
}

function moveBinaries(source, destination) {
var selected = $(source + ' option:selected').remove();
var sorted = $.makeArray($(destination + ' option').add(selected)).sort(function (a, b) {
return $(a).text() > $(b).text() ? 1 : -1;
});
$(destination).empty().append(sorted);
}
4 changes: 4 additions & 0 deletions src/api/app/controllers/webui/patchinfo_controller.rb
Expand Up @@ -29,6 +29,8 @@ def edit
# TODO: check that @tracker has sense if it's coming from create (new_patchinfo) action
@tracker = ::Configuration.default_tracker
@patchinfo.binaries.each { |bin| @binarylist.delete(bin) }

switch_to_webui2
end

def show
Expand All @@ -40,6 +42,8 @@ def show
end

def update
switch_to_webui2

authorize @package, :update?
@patchinfo = Patchinfo.new(patchinfo_params)
if @patchinfo.valid?
Expand Down
4 changes: 2 additions & 2 deletions src/api/app/views/webui/patchinfo/_form.html.haml
Expand Up @@ -5,7 +5,7 @@
.box.show_left.show_right
.box{ style: "background-color:#DDDDDD; margin-top: 0" }
%h2{ style: "display: inline" }
Patchinfo-Editor for #{@project}
Edit Patchinfo for #{@project}
.box.show_left.show_right
%p
%strong
Expand Down Expand Up @@ -131,7 +131,7 @@
%strong Reason:
= f.text_field :block_reason, style: 'width: 99%', disabled: true
%div{ style: "margin-left:5px;" }
= submit_tag 'Save Patchinfo'
= submit_tag 'Save'
= f.hidden_field :name
- content_for :ready_function do
patchinfoReady();
2 changes: 1 addition & 1 deletion src/api/app/views/webui/patchinfo/edit.html.haml
@@ -1,3 +1,3 @@
- @pagetitle = "Patchinfo-Editor"
- @pagetitle = "Edit Patchinfo for #{@project}"
- patchinfo_bread_crumb 'Edit Patchinfo'
= render partial: 'form'
@@ -1,4 +1,11 @@
= render partial: 'webui/package/breadcrumb_items'
- if current_page?(patchinfo_show_path(@project, @package))
%li.breadcrumb-item.active{ 'aria-current' => 'page' }
= render partial: 'webui/main/breadcrumb_items'
%li.breadcrumb-item
= link_to('Projects', projects_path)
%li.breadcrumb-item
= link_to(@project, project_show_path(@project))
%li.breadcrumb-item.active{ 'aria-current' => 'page' }
- case action_name
- when 'show'
Details
- when 'edit'
Edit Patchinfo
47 changes: 47 additions & 0 deletions src/api/app/views/webui2/webui/patchinfo/edit.html.haml
@@ -0,0 +1,47 @@
- @pagetitle = "Edit Patchinfo for #{@project}"

.card
= render partial: 'webui/package/tabs', locals: { project: @project, package: @package }
.card-body
%h3= @pagetitle

= form_for(@patchinfo, url: update_patchinfo_path(project: @project, package: @package), method: :put, html: { id: 'patchinfo' }) do |form|
= form.hidden_field(:name)
.form-group.col-8.col-md-4
= render partial: 'webui/autocomplete', locals: { html_id: 'patchinfo[packager]', label: 'Packager', value: @patchinfo.packager,
source: url_for(controller: '/webui/user', action: 'autocomplete') }
.form-group.col-md-6
= form.label(:summary)
%abbr.text-danger{ title: 'required (minimum 10 characters)' } *
= form.text_area(:summary, required: true, class: 'form-control', minlength: 10)
%small.form-text.text-muted Summarize the changes
.form-group.col-md-6
= form.label(:description)
%abbr.text-danger{ title: 'required (minimum 50 characters)' } *
= form.text_area(:description, required: true, rows: 8, class: 'form-control', minlength: 50)
%small.form-text.text-muted Fully describe the changes
.form-group.col-4.col-md-2
= form.label(:version)
= form.text_field(:version, class: 'form-control')
.form-group.col-md-6
= form.label(:message)
= form.text_area(:message, rows: 4, class: 'form-control')
.form-group.col-6.col-md-3
= form.label(:category)
= form.select(:category, options_for_select(Patchinfo::CATEGORIES, @patchinfo.category), {}, class: 'custom-select')
.form-group.col-6.col-md-3
= form.label(:rating)
= form.select(:rating, options_for_select(Patchinfo::RATINGS, @patchinfo.rating), {}, class: 'custom-select')
= render partial: 'webui2/webui/patchinfo/form/issues',
locals: { form: form, issues: @patchinfo.issues, project: @project, package: @package }
= render partial: 'webui2/webui/patchinfo/form/required_actions',
locals: { form: form, zypp_restart_needed: @zypp_restart_needed, relogin: @relogin, reboot: @reboot }
= render partial: 'webui2/webui/patchinfo/form/binaries',
locals: { form: form, binarylist: @binarylist, binaries: @patchinfo.binaries }
= render partial: 'webui2/webui/patchinfo/form/block_release',
locals: { form: form, patchinfo_block: @patchinfo.block }

= form.submit('Save', class: 'btn btn-primary', data: { disable_with: 'Saving...' })

= content_for(:ready_function) do
setupPatchinfo();
20 changes: 20 additions & 0 deletions src/api/app/views/webui2/webui/patchinfo/form/_binaries.html.haml
@@ -0,0 +1,20 @@
.form-group.col-md-6
= form.label(:binaries)
- if binarylist.present? || binaries.present?
.form-row
.col
= select_tag(:available_binaries, options_for_select(binarylist.to_a), multiple: true, size: 6, class: 'custom-select')
%small.form-text.text-muted Available binaries
.col-auto
%button.btn.btn-sm.btn-secondary.mb-1#select-binary{ type: 'button', title: 'Select binary' } >
%br
%button.btn.btn-sm.btn-secondary.mb-1#select-binaries{ type: 'button', title: 'Select all binaries' } >>
%br
%button.btn.btn-sm.btn-secondary.mb-1#unselect-binaries{ type: 'button', title: 'Unselect all binaries' } <<
%br
%button.btn.btn-sm.btn-secondary.mb-1#unselect-binary{ type: 'button', title: 'Unselect binary' } <
.col
= form.select(:binaries, options_for_select(binaries.to_a), { include_hidden: false }, multiple: true, size: 6, class: 'custom-select')
%small.form-text.text-muted Selected binaries
- else
%p No binaries available
@@ -0,0 +1,8 @@
.form-group.col-md-6
.custom-control.custom-checkbox
= form.check_box(:block, class: 'custom-control-input')
= form.label(:block, 'Block release?', class: 'custom-control-label')
.form-group.col-md-6
= form.label(:block_reason, 'Reason')
= form.text_field(:block_reason, class: 'form-control', disabled: !patchinfo_block)
%small.form-text.text-muted Explain what is blocking the release of this patchinfo
33 changes: 33 additions & 0 deletions src/api/app/views/webui2/webui/patchinfo/form/_issues.html.haml
@@ -0,0 +1,33 @@
.form-group.col-md-6
= form.label(:issues, class: 'd-block')

.list-group#issues
- issues.to_a.each do |issue|
- issue_name = "#{issue[1]}_#{issue[0]}"
.list-group-item.flex-column.align-items-start.issue-element{ id: "issue_#{issue_name}" }
.d-flex.w-100.mb-1
%i.fa.fa-bug.text-danger.pt-1.mr-1
= patchinfo_issue_link(issue[1], issue[0], issue[2])
= link_to('#', id: "delete_issue_#{issue_name}", title: 'Delete', class: 'ml-1') do
%i.fas.fa-times-circle.text-danger

- ['issueid', 'issuetracker', 'issueurl', 'issuesum'].each_with_index do |type, index|
= form.hidden_field(type.to_sym, value: issue[index], id: "#{type}_#{issue_name}", multiple: true)
%small.text-muted= issue[3]
.form-group.col-md-6
= text_field_tag(:issue_ids, '', class: 'form-control w-auto d-inline-block')
= link_to(patchinfo_new_tracker_url, id: 'add-issues', title: 'Add Issues', remote: true, data: { dataType: 'json', project: project.name }) do
%i.fas.fa-plus-circle.text-primary
%i.fas.fa-spinner.fa-spin.d-none
Add issues
%small.form-text.text-danger#ajax-error-message
%small.form-text.text-muted
Add issues (a single issue or a comma-separated list of issues, e.g.: "boo#123456,bgo#654321,CVE-2012-1234")
= link_to('https://en.opensuse.org/openSUSE:Packaging_Patches_guidelines#Current_set_of_abbreviations',
target: '_blank', rel: 'noopener', class: 'd-block') do
%i.fas.fa-info-circle.text-info
List of supported trackers
.form-group.col-md-6
= link_to('Update issues from sources', update_issues_patchinfo_path(project: project, package: package),
data: { confirm: 'Attention! All unsaved data will be lost! Continue?' }, method: :post)

@@ -0,0 +1,11 @@
.form-group.col-md-6
= form.label(:required_actions, 'Required Actions')
.custom-control.custom-checkbox
= form.check_box(:zypp_restart_needed, class: 'custom-control-input')
= form.label(:zypp_restart_needed, 'Package manager restart suggested', class: 'custom-control-label')
.custom-control.custom-checkbox
= form.check_box(:relogin_needed, class: 'custom-control-input')
= form.label(:relogin_needed, 'Relogin suggested', class: 'custom-control-label')
.custom-control.custom-checkbox
= form.check_box(:reboot_needed, class: 'custom-control-input')
= form.label(:reboot_needed, 'Reboot suggested', class: 'custom-control-label')
Expand Up @@ -92,14 +92,14 @@
check('block')
fill_in('block_reason', with: 'locked!')

click_button('Save Patchinfo')
click_button('Save')
expect(page).to have_css('#flash-messages', text: 'Successfully edited patchinfo')
expect(find(:css, '.ui-state-error b')).to have_text('This update is currently blocked:')

click_link('Edit patchinfo')
uncheck('block')
expect(page).to have_css('input[id=block_reason][disabled]')
click_button 'Save Patchinfo'
click_button 'Save'

logout

Expand Down
4 changes: 2 additions & 2 deletions src/api/spec/features/webui/maintenance_workflow_spec.rb
Expand Up @@ -85,14 +85,14 @@
check('patchinfo[block]')
fill_in('patchinfo[block_reason]', with: 'locked!')

click_button('Save Patchinfo')
click_button('Save')
expect(page).to have_css('#flash-messages', text: 'Successfully edited patchinfo')
expect(find(:css, '.ui-state-error b')).to have_text('This update is currently blocked:')

click_link('Edit patchinfo')
uncheck('patchinfo[block]')
expect(page).to have_css('input[id=patchinfo_block_reason][disabled]')
click_button 'Save Patchinfo'
click_button 'Save'

logout

Expand Down
8 changes: 4 additions & 4 deletions src/api/spec/features/webui/patchinfo_spec.rb
Expand Up @@ -13,10 +13,10 @@
expect(page).to have_link('Create Patchinfo')
click_link('Create Patchinfo')
expect(page).to have_current_path(edit_patchinfo_path(project: project, package: 'patchinfo'))
expect(page).to have_text("Patchinfo-Editor for #{project.name}")
expect(page).to have_text("Edit Patchinfo for #{project.name}")
fill_in 'patchinfo[summary]', with: 'A' * 9
fill_in 'patchinfo[description]', with: 'A' * 30
click_button 'Save Patchinfo'
click_button 'Save'
# We check this field using 'minlength' HTML5 control. It opens a tooltip and the error message inside can vary depending on the browser,
# so we just check its presence and not its content like follows.
message = page.find('#patchinfo_summary').native.attribute('validationMessage')
Expand All @@ -31,10 +31,10 @@
expect(page).to have_link('Create Patchinfo')
click_link('Create Patchinfo')
expect(page).to have_current_path(edit_patchinfo_path(project: project, package: 'patchinfo'))
expect(page).to have_text("Patchinfo-Editor for #{project.name}")
expect(page).to have_text("Edit Patchinfo for #{project.name}")
fill_in 'patchinfo[summary]', with: 'A' * 15
fill_in 'patchinfo[description]', with: 'A' * 55
click_button 'Save Patchinfo'
click_button 'Save'
expect(page).to have_current_path(patchinfo_show_path(project: project, package: 'patchinfo'))
expect(page).to have_text('Successfully edited patchinfo')
end
Expand Down

0 comments on commit 85146ae

Please sign in to comment.