[Kimchi-devel] [WOK] List Widget specification

Samuel Henrique De Oliveira Guimaraes samuel.guimaraes at eldorado.org.br
Fri Sep 11 12:10:19 UTC 2015


Hi Atreye,

Thanks! For the action buttons, I know the following piece of code might look ugly but here's what I've done with wok.Grid to support a single button dismissing modal windows or a set of links in a drop-down button with "Action" label:

        var toolbarButtons = this['opts']['toolbarButtons'];
        var toolbarNode = null;
        var btnHTML, dropHTML = [];
        if(toolbarButtons) {
            toolbarNode = $('<div class="btn-group"></div>');
            toolbarNode.prependTo(theContainer);
            if(toolbarButtons.length > 1) {
                dropHTML = ['<div class="dropdown menu-flat">',
                    '<button id="wok-dropdown-button-', containerID, '" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">',
                    '<span class="edit-alt"></span>Actions<span class="caret"></span>',
                    '</button>',
                    '<ul class="dropdown-menu"></ul>',
                    '</div>'
                ].join('');
                $(dropHTML).appendTo(toolbarNode);
                $.each(toolbarButtons, function(i, button) {
                    btnHTML = [
                        '<li', button.critical === true ? ' class="critical"' : '', '><a data-toggle="modal"',
                        button.id ? (' id="' + button.id + '"') : '',
                        ' class="', button.disabled === true ? ' disabled' : '', '">',
                        button.class ? ('<i class="' + button.class) + '"></i>' : '',
                        button.label,
                        '</a></li>'
                    ].join('');
                    var btnNode = $(btnHTML).appendTo(toolbarNode[0].children[0].children[1]);
                    button.onClick && btnNode.on('click', button.onClick);
                });
            }else {
                $.each(toolbarButtons, function(i, button) {
                    btnHTML = [
                        '<button data-dismiss="modal" ',
                            button['id'] ? (' id="' + button['id'] + '"') : '',
                            ' class="btn btn-primary',
                                button['class'] ? (' ' + button['class']) : '',
                               '"',
                                button['disabled'] === true ? ' disabled' : '',
                                '>',
                                button['label'],
                        '</button>'
                    ].join('');
                    var btnNode = $(btnHTML).appendTo(toolbarNode);
                    button['onClick'] &&
                        btnNode.on('click', button['onClick']);
                });
            }
        }

In hosts.js:

Repository list:

repositoriesGrid = new wok.widget.List({
            container: 'repositories-grid-container',
            id: 'repositories-grid',
            title: i18n['KCHREPO6003M'],
            toolbarButtons: [{
                id: 'repositories-grid-add-button',
                label: i18n['KCHREPO6012M'],
                class: 'fa fa-plus-circle',
                onClick: function(event) {
                    wok.window.open({url:'plugins/kimchi/repository-add.html',
                                    class: repo_type});
                }
            }, {
                id: 'repositories-grid-enable-button',
                label: i18n['KCHREPO6016M'],
                class: 'fa fa-play-circle-o',
                disabled: true,
                onClick: function(event) {
                    var repository = repositoriesGrid.getSelected();
                    if(!repository) {
                        return;
                    }
                    var name = repository['repo_id'];
                    var enable = !repository['enabled'];
                    $(this).prop('disabled', true);
                    kimchi.enableRepository(name, enable, function() {
                        wok.topic('kimchi/repositoryUpdated').publish();
                    });
                }
            }, {
                id: 'repositories-grid-edit-button',
                label: i18n['KCHREPO6013M'],
                class: 'fa fa-pencil',
                disabled: true,
                onClick: function(event) {
                    var repository = repositoriesGrid.getSelected();
                    if(!repository) {
                        return;
                    }
                    kimchi.selectedRepository = repository['repo_id'];
                    wok.window.open({url:'plugins/kimchi/repository-edit.html',
                                    class: repo_type});
                }
            }, {
                id: 'repositories-grid-remove-button',
                label: i18n['KCHREPO6014M'],
                disabled: true,
                class: 'fa fa-minus-circle',
                critical: true,
                onClick: function(event) {
                    var repository = repositoriesGrid.getSelected();
                    if(!repository) {
                        return;
                    }

                    var settings = {
                        title : i18n['KCHREPO6001M'],
                        content : i18n['KCHREPO6002M'],
                        confirm : i18n['KCHAPI6004M'],
                        cancel : i18n['KCHAPI6003M']
                    };

                    wok.confirm(settings, function() {
                        kimchi.deleteRepository(
                            repository['repo_id'],
                            function(result) {
                                wok.topic('kimchi/repositoryDeleted').publish(result);
                            }, function(error) {
                            }
                        );
                    });
                }
            }]

Debug reports:

var initReportGrid = function(reports) {
        reportGrid = new wok.widget.List({
            container: 'available-reports-grid-container',
            id: reportGridID,
            title: i18n['KCHDR6002M'],
            toolbarButtons: [{
                id: reportGridID + '-generate-button',
                class: 'fa fa-plus-circle',
                label: i18n['KCHDR6006M'],
                onClick: function(event) {
                    wok.window.open('plugins/kimchi/report-add.html');
                }
            }, {
                id: reportGridID + '-rename-button',
                class: 'fa fa-pencil',
                label: i18n['KCHDR6008M'],
                disabled: true,
                onClick: function(event) {
                    var report = reportGrid.getSelected();
                    if(!report) {
                        return;
                    }

                    kimchi.selectedReport = report['name'];
                    wok.window.open('plugins/kimchi/report-rename.html');
                }
            }, {
                id: reportGridID + '-download-button',
                label: i18n['KCHDR6010M'],
                class: 'fa fa-download',
                disabled: true,
                onClick: function(event) {
                    var report = reportGrid.getSelected();
                    if(!report) {
                        return;
                    }

                    kimchi.downloadReport({
                        file: report['uri']
                   });
                }
            }, {
                id: reportGridID + '-remove-button',
                class: 'fa fa-minus-circle',
                label: i18n['KCHDR6009M'],
                critical: true,
                disabled: true,
                onClick: function(event) {
                    var report = reportGrid.getSelected();
                    if(!report) {
                        return;
                    }

                    var settings = {
                        title : i18n['KCHAPI6004M'],
                        content : i18n['KCHDR6001M'],
                        confirm : i18n['KCHAPI6002M'],
                        cancel : i18n['KCHAPI6003M']
                    };

                    wok.confirm(settings, function() {
                        kimchi.deleteReport({
                            name: report['name']
                        }, function(result) {
                            listDebugReports();
                        }, function(error) {
                           wok.message.error(error.responseJSON.reason);
                        });
                    });
                }
            }]

I've added critical parameter (so the critical option always have a red background) and in the class parameter I'm putting font awesome classes (fa fa-circle-plus for instance). The supporting classes and styles are already in bootstrap.custom.css located in wok ui/libs/themes/base/ folder. By the way, this widget should be name wok.List instead of kimchi.list and added to wok js files. I believe we can use this later for other application scenarios, not just Kimchi Hosts tab.

I had some merge conflicts when I've pulled latest commits and applied the latest patches but once I fix my workspace I'll send a new patch.

Regards,
Samuel

From: Atreye Mukhopadhyay [mailto:atreyee at linux.vnet.ibm.com]
Sent: sexta-feira, 11 de setembro de 2015 08:40
To: Samuel Henrique De Oliveira Guimaraes <samuel.guimaraes at eldorado.org.br>; kimchi-devel at ovirt.org
Subject: Re: [Kimchi-devel] [WOK] List Widget specification

Hi Samuel,
I have created new UI widget for Repositories and Debug Report panel. New widget is created using Bootstrap provided css classes and js plugins. I have added some inline css styles to match new-ui spec which we can move to some css class files later.
I am still working on the implementation of action buttons (real functionality when specific action clicked) and scroll bar for these panels.
Attached files are changed for this implementation. kimchi.list.js is for the new widget list which we need to merge in '\plugins\kimchi\ui\js\src ' folder.

In kimchi.host.js, I replaced kimchi.widget.Grid  to kimchi.widget.List  for both Repositories and Debug Reports. Also added additional  attribute 'type' in the corresponding field configuration of the panel.

Code changes of kimchi.host.js look like below  for Repositories:
1. Replace the Grid to List
        repositoriesGrid = new kimchi.widget.Grid({
to
        repositoriesGrid = new kimchi.widget.List({

2. Added additional attribute 'type'
        if (repo_type == "yum") {
                gridFields=[{
                    name: 'repo_id',
                    label: i18n['KCHREPO6004M'],
                    'class': 'repository-id',
                    type:'name'

                }, {
                    name: 'config[repo_name]',
                    label: i18n['KCHREPO6005M'],
                    'class': 'repository-name',
                    type:'description'

                }, {
                    name: 'enabled',
                    label: i18n['KCHREPO6009M'],
                    'class': 'repository-enabled',
                    type:'action'
                }];
        }

Similar changes for debug reports as well...

Please let me know your suggestions.

Below are the screenshots of the implementation.

[cid:image002.jpg at 01D0EC70.0DB2FA70]           [cid:image004.jpg at 01D0EC70.0DB2FA70]                 [cid:image006.jpg at 01D0EC70.0DB2FA70]
On 9/2/2015 11:11 PM, Samuel Henrique De Oliveira Guimaraes wrote:
Hi team,

As we discussed on the chat today, I need help creating a widget for the new-ui while I'm still working on the current Grid widget for Hosts, Storage and Network tabs.

According to the new-ui design spec doc, in the Host tab, Debug Reports and Repositories panels shouldn't be presented as tables but as lists with each line having a drop-down button on the right instead of one on the top below the panel header:

[cid:image007.png at 01D0EC70.0DB2FA70]

This is the current json response for Repositories:

[
  {
    "config":{
      "gpgcheck":false,
      "gpgkey":"file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"<file:///\\etc\pki\rpm-gpg\RPM-GPG-KEY-fedora-$releasever-$basearch>,
      "metalink":"https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch"<https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch>,
      "mirrorlist":"",
      "repo_name":"Fedora $releasever - $basearch"
    },
    "repo_id":"fedora",
    "enabled":true,
    "baseurl":""
  }
]

And Debug Reports:

[
  {
    "time":"2015-08-31-15:13:10",
    "name":"test2",
    "uri":"plugins/kimchi/data/debugreports/test2.tar.xz"
  },
  {
    "time":"2015-08-31-15:12:57",
    "name":"test",
    "uri":"plugins/kimchi/data/debugreports/test.tar.xz"
  }
]

I've planned the following HTML output for this widget:

- A <i class="fa fa-power-off"></i> tag, empty when repository is not enabled;
- repo_id: Displays the repository name
- repo_name: Repository description
- Bootstrap modal button (don't worry about styles since I'm still customizing it)

Reference: http://plnkr.co/edit/SgQcpfu5b5vVXWD9imND?p=preview

For debug reports lists:

-name;
-time;
- Bootstrap modal button (don't worry about styles since I'm still customizing it)

It is very important that we keep the same model from kimchi.hosts.js by replacing only the current widget with the new one (example: repositoriesGrid = new kimchi.widget.Grid({ }); to repositoriesGrid = new kimchi.widget.List({ }); ).
I don't think it is necessary to fetch the whole branch and apply the patches to edit kimchi files, this can be done using www.jsfiddle.net<http://www.jsfiddle.net>, www.jsbin.com<http://www.jsbin.com> , http://plnkr.co/ or http://codepen.io/ (I suggest plnkr or jsfiddle since we can easily include jQuery, FonAwesome and Bootstrap from their CDN servers).

Thanks,
Samuel






_______________________________________________

Kimchi-devel mailing list

Kimchi-devel at ovirt.org<mailto:Kimchi-devel at ovirt.org>

http://lists.ovirt.org/mailman/listinfo/kimchi-devel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20150911/d45df88b/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image002.jpg
Type: image/jpeg
Size: 18527 bytes
Desc: image002.jpg
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20150911/d45df88b/attachment.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image004.jpg
Type: image/jpeg
Size: 20437 bytes
Desc: image004.jpg
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20150911/d45df88b/attachment-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image006.jpg
Type: image/jpeg
Size: 9599 bytes
Desc: image006.jpg
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20150911/d45df88b/attachment-0002.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image007.png
Type: image/png
Size: 64584 bytes
Desc: image007.png
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20150911/d45df88b/attachment.png>


More information about the Kimchi-devel mailing list