]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
wizard: more work - add icon+text, and activate tabs according the configuration...
authorJaroslav Kysela <perex@perex.cz>
Fri, 4 Dec 2015 09:08:49 +0000 (10:08 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 4 Dec 2015 09:08:49 +0000 (10:08 +0100)
src/api/api_wizard.c
src/webui/static/app/acleditor.js
src/webui/static/app/chconf.js
src/webui/static/app/config.js
src/webui/static/app/ext.css
src/webui/static/app/idnode.js
src/webui/static/app/mpegts.js
src/webui/static/app/status.js
src/webui/static/app/tvadapters.js
src/webui/static/app/wizard.js
src/wizard.c

index e77bf740ab95002611b227ee8bb477c16e264a62..e30218c360b35ce994764fab0e553cce8cb1f2b7 100644 (file)
@@ -49,17 +49,31 @@ wizard_idnode_save_simple
 }
 
 static int
-wizard_cancel
-  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+wizard_page
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp, const char *page )
 {
   pthread_mutex_lock(&global_lock);
   free(config.wizard);
-  config.wizard = strdup("");
+  config.wizard = strdup(page);
   config_save();
   pthread_mutex_unlock(&global_lock);
   return 0;
 }
 
+static int
+wizard_cancel
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  return wizard_page(perm, opaque, op, args, resp, "");
+}
+
+static int
+wizard_start
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  return wizard_page(perm, opaque, op, args, resp, "hello");
+}
+
 void
 api_wizard_init ( void )
 {
@@ -74,6 +88,7 @@ api_wizard_init ( void )
     { "wizard/status/save",  ACCESS_ADMIN, wizard_idnode_save_simple, wizard_status },
     { "wizard/mapping/load", ACCESS_ADMIN, wizard_idnode_load_simple, wizard_mapping },
     { "wizard/mapping/save", ACCESS_ADMIN, wizard_idnode_save_simple, wizard_mapping },
+    { "wizard/start",        ACCESS_ADMIN, wizard_start, NULL },
     { "wizard/cancel",       ACCESS_ADMIN, wizard_cancel, NULL },
     { NULL },
   };
index 0afc2c8c6cd5a8876c8c911f975c83a0febdeee2..2c803a26e9b8f930e45906d7285ccc8edbae4a50 100644 (file)
@@ -21,6 +21,7 @@ tvheadend.acleditor = function(panel, index)
                 'channel_tag_exclude,channel_tag,comment';
 
     tvheadend.idnode_grid(panel, {
+        id: 'access_entry',
         url: 'api/access/entry',
         titleS: _('Access Entry'),
         titleP: _('Access Entries'),
index 73527ec3c9c787cc5b940f33585a2aacc1c8dea2..d42c067116b290edca8547889fffef080f003eab 100644 (file)
@@ -193,6 +193,7 @@ tvheadend.channel_tab = function(panel, index)
     };
 
     tvheadend.idnode_grid(panel, {
+        id: 'channels',
         url: 'api/channel',
         all: 1,
         comet: 'channel',
index 2710ef3ef0281ec58e9401df13b330924f1bafc9..ae5303f9dde269b85e307d3fc65cb7ef16f32b53 100644 (file)
@@ -4,6 +4,25 @@
 
 tvheadend.baseconf = function(panel, index) {
 
+    var wizardButton = {
+        name: 'wizard',
+        builder: function() {
+            return new Ext.Toolbar.Button({
+                tooltip: _('Start initial configuration wizard'),
+                iconCls: 'wizard',
+                text: _('Start wizard')
+            });
+        },
+        callback: function(conf) {
+            tvheadend.Ajax({
+                url: 'api/wizard/start',
+                success: function() {
+                    window.location.reload();
+                }
+            });
+        }
+    };
+
     tvheadend.idnode_simple(panel, {
         url: 'api/config',
         title: _('Base'),
@@ -11,6 +30,7 @@ tvheadend.baseconf = function(panel, index) {
         tabIndex: index,
         comet: 'config',
         labelWidth: 250,
+        tbar: [wizardButton],
         postsave: function(data, abuttons) {
             var l = data['uilevel'];
             if (l >= 0) {
index 0de9fa4f741ad7fd221ba7f83fe4b6e8f9393aef..67816ebe371929aea17d722e96f454077298f46d 100644 (file)
     background-image: url(../icons/arrow_right.png) !important;
 }
 
+.finish {
+    background-image: url(../icons/accept.png) !important;
+}
 
 .x-linked {
     display: inline-block;
     color: white;
 }
 
+.x-wizard-icon {
+    float: right;
+}
+
+.x-wizard-description {
+    margin: 5px;
+    font: normal 12px arial, tahoma, helvetica, sans-serif;
+}
+
 /* Table styles for webUI help */
 
 .hts-doc-text table, .hts-doc-text th, .hts-doc-text td {
index 444cd0c24edd3b6021edd5cba7f2f8f36faaca19..d538a05bcbe0b5130829986651bccc0accf1fcc4 100644 (file)
@@ -1129,6 +1129,8 @@ tvheadend.idnode_editor = function(_uilevel, item, conf)
     });
 
     build();
+    if (conf.build)
+        conf.build(conf, panel);
     return panel;
 };
 
@@ -1141,7 +1143,7 @@ tvheadend.idnode_editor_win = function(_uilevel, item, conf)
    var width = p.fixedWidth;
    var w = new Ext.ux.Window({
        title: conf.winTitle,
-       iconCls: 'edit',
+       iconCls: conf.iconCls || 'edit',
        layout: 'fit',
        autoWidth: width ? false : true,
        autoHeight: true,
@@ -1929,6 +1931,7 @@ tvheadend.idnode_grid = function(panel, conf)
     }
 
     var dpanel = new Ext.Panel({
+        id: conf.id || null,
         border: false,
         header: false,
         layout: 'fit',
@@ -2473,6 +2476,7 @@ tvheadend.idnode_tree = function(panel, conf)
     }
 
     var dpanel = new Ext.Panel({
+        id: conf.id || null,
         border: false,
         header: false,
         layout: 'fit',
@@ -2703,6 +2707,7 @@ tvheadend.idnode_simple = function(panel, conf)
     }
 
     var dpanel = new Ext.Panel({
+        id: conf.id || null,
         border: false,
         header: false,
         layout: 'fit',
index a60da9b98d00e656a4037514e574714ccbec7a9a..410faefa3b30cdea4cce8095fb48090192e3fcbc 100644 (file)
@@ -61,6 +61,7 @@ tvheadend.networks = function(panel, index)
     }
 
     tvheadend.idnode_grid(panel, {
+        id: 'mpegts_network',
         url: 'api/mpegts/network',
         titleS: _('Network'),
         titleP: _('Networks'),
index 930a3821ea9396e02c870d4b238b47801a1e5d3e..a77a16a3e32e6901bbba9a65ee76cca471cdcace 100644 (file)
@@ -476,6 +476,7 @@ tvheadend.status_streams = function(panel, index)
     }
 
     var dpanel = new Ext.Panel({
+        id: 'status_streams',
         border: false,
         header: false,
         layout: 'fit',
index 08c8366e39459e9f9f12acd1848814a0ee8216b7..19a428d4c71cbbeb19210441c4bb55ff07ded147 100644 (file)
@@ -1,6 +1,7 @@
 tvheadend.tvadapters = function(panel, index) {
 
     tvheadend.idnode_tree(panel, {
+        id: 'tvadapters',
         url: 'api/hardware/tree',
         title: _('TV adapters'),
         iconCls: 'tvCards',
index 4f663af28d0b085d988ad2dbb54927b6b2846128..745ca1fa59564e9bb2d610c5e4a9febb47cac23d 100644 (file)
@@ -5,6 +5,13 @@
 tvheadend.wizard_start = function(page) {
 
     var w = null;
+    var tabMapping = {
+        hello: 'access_entry',
+        network: 'mpegts_network',
+        input: 'tvadapters',
+        status: 'status_streams',
+        mapping: 'channels',
+    }
 
     function cancel(conf) {
         tvheadend.Ajax({
@@ -26,6 +33,17 @@ tvheadend.wizard_start = function(page) {
         return null;
     }
 
+    function getvalue(data, prefix) {
+        var m = data.params;
+        var l = prefix.length;
+        for (var i = 0; i < m.length; i++) {
+            var id = m[i].id;
+            if (id === prefix)
+                return m[i].value;
+        }
+        return null;
+    }
+
     function newpage(conf, prefix) {
         var p = getparam(conf.fullData, prefix);
         if (p)
@@ -46,12 +64,28 @@ tvheadend.wizard_start = function(page) {
         });
         buttons.splice(0, 0, prevBtn);
     }
+
+    function pbuild(conf, panel) {
+        var data = conf.fullData;
+        var icon = getvalue(data, 'icon');
+        var text = getvalue(data, 'description');
+        var c = '';
+        if (icon)
+          c += '<img class="x-wizard-icon" src="' + icon + '"/>';
+        c += '<div class="x-wizard-description">' + text + '</div>';
+        var p = new Ext.Panel({
+            width: 570,
+            html: c
+        });
+        panel.insert(0, p);
+    }
     
     function build(d) {
         d = json_decode(d);
         var m = d[0];
         var last = getparam(m, 'page_next_') === null;
         tvheadend.idnode_editor_win('basic', m, {
+            build: pbuild,
             fullData: m,
             url: 'api/wizard/' + page,
             winTitle: m.caption,
@@ -68,7 +102,7 @@ tvheadend.wizard_start = function(page) {
             buildbtn: buildbtn,
             labelWidth: 250,
             saveText: last ? _('Finish') : _('Save & Next'),
-            saveIconCls: last ? 'exit' : 'next',
+            saveIconCls: last ? 'finish' : 'next',
             cancel: cancel,
             uilevel: 'expert',
             help: function() {
@@ -78,6 +112,18 @@ tvheadend.wizard_start = function(page) {
     }
 
     tvheadend.wizard = page;
+
+    if (page in tabMapping) {
+        var i = Ext.getCmp(tabMapping[page]);
+        var c = i ? i.ownerCt : null;
+        while (c) {
+            if ('activeTab' in c)
+                c.setActiveTab(i);
+            i = c;
+            c = c.ownerCt;
+        }
+    }
+
     tvheadend.Ajax({
         url: 'api/wizard/' + page + '/load',
         params: {
index 66366dc4ed224ff1bbcf0283a536d237f270804f..962cb0603ae673365c5c50380b2683b312a35061 100644 (file)
@@ -31,17 +31,32 @@ static const void *empty_get(void *o)
   return &prop_sbuf_ptr;
 }
 
-#define SPECIAL_PROP(idval) { \
+static const void *icon_get(void *o)
+{
+  strcpy(prop_sbuf, "docresources/tvheadendlogo.png");
+  return &prop_sbuf_ptr;
+}
+
+#define SPECIAL_PROP(idval, getfcn) { \
   .type = PT_STR, \
   .id   = idval, \
   .name = "", \
-  .get  = empty_get, \
+  .get  = getfcn, \
   .opts = PO_RDONLY | PO_NOUI \
 }
 
-#define PREV_BUTTON(page) SPECIAL_PROP("page_prev_" STRINGIFY(page))
-#define NEXT_BUTTON(page) SPECIAL_PROP("page_next_" STRINGIFY(page))
-#define LAST_BUTTON()     SPECIAL_PROP("page_last")
+#define PREV_BUTTON(page) SPECIAL_PROP("page_prev_" STRINGIFY(page), empty_get)
+#define NEXT_BUTTON(page) SPECIAL_PROP("page_next_" STRINGIFY(page), empty_get)
+#define LAST_BUTTON()     SPECIAL_PROP("page_last", empty_get)
+#define ICON()            SPECIAL_PROP("icon", icon_get)
+#define DESCRIPTION(page) SPECIAL_PROP("description", wizard_description_##page)
+
+#define DESCRIPTION_FCN(page, desc) \
+static const void *wizard_description_##page(void *o) \
+{ \
+  static const char *t = desc; \
+  return &t; \
+}
 
 /*
  *
@@ -80,15 +95,52 @@ static int hello_set_network(void *o, const void *v)
   return 0;
 }
 
+DESCRIPTION_FCN(hello, N_("\
+Enter allowed network (like 192.168.1.0/24) and user logins for administrator and ordinary user. \
+If the username is empty, anonymous access will be allowed.\
+"))
+
 wizard_page_t *wizard_hello(void)
 {
+  static const property_group_t groups[] = {
+    {
+      .name     = N_("Network access"),
+      .number   = 1,
+    },
+    {
+      .name     = N_("Administrator login"),
+      .number   = 2,
+    },
+    {
+      .name     = N_("User login"),
+      .number   = 3,
+    },
+    {}
+  };
   static const property_t props[] = {
     {
       .type     = PT_STR,
       .id       = "network",
-      .name     = N_("Network (like 192.168.1.0/24)"),
+      .name     = N_("Allowed network"),
       .get      = hello_get_network,
       .set      = hello_set_network,
+      .group    = 1
+    },
+    {
+      .type     = PT_STR,
+      .id       = "admin_username",
+      .name     = N_("Admin username"),
+      .get      = hello_get_network,
+      .set      = hello_set_network,
+      .group    = 2
+    },
+    {
+      .type     = PT_STR,
+      .id       = "admin_password",
+      .name     = N_("Admin password"),
+      .get      = hello_get_network,
+      .set      = hello_set_network,
+      .group    = 2
     },
     {
       .type     = PT_STR,
@@ -96,6 +148,7 @@ wizard_page_t *wizard_hello(void)
       .name     = N_("Username"),
       .get      = hello_get_network,
       .set      = hello_set_network,
+      .group    = 3
     },
     {
       .type     = PT_STR,
@@ -103,13 +156,19 @@ wizard_page_t *wizard_hello(void)
       .name     = N_("Password"),
       .get      = hello_get_network,
       .set      = hello_set_network,
+      .group    = 3
     },
+    ICON(),
+    DESCRIPTION(hello),
     NEXT_BUTTON(network),
     {}
   };
-  wizard_page_t *page = page_init("wizard_hello", N_("Welcome - Tvheadend - your TV streaming server and video recorder"));
+  wizard_page_t *page =
+    page_init("wizard_hello",
+    N_("Welcome - Tvheadend - your TV streaming server and video recorder"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   ic->ic_properties = props;
+  ic->ic_groups = groups;
   return page;
 }
 
@@ -117,6 +176,11 @@ wizard_page_t *wizard_hello(void)
  * Network settings
  */
 
+DESCRIPTION_FCN(network, N_("\
+Create networks.\
+"))
+
+
 wizard_page_t *wizard_network(void)
 {
   static const property_t props[] = {
@@ -141,6 +205,8 @@ wizard_page_t *wizard_network(void)
       .get      = hello_get_network,
       .set      = hello_set_network,
     },
+    ICON(),
+    DESCRIPTION(network),
     PREV_BUTTON(hello),
     NEXT_BUTTON(input),
     {}
@@ -155,6 +221,11 @@ wizard_page_t *wizard_network(void)
  * Input settings
  */
 
+DESCRIPTION_FCN(input, N_("\
+Assign inputs to networks.\
+"))
+
+
 wizard_page_t *wizard_input(void)
 {
   static const property_t props[] = {
@@ -179,6 +250,8 @@ wizard_page_t *wizard_input(void)
       .get      = hello_get_network,
       .set      = hello_set_network,
     },
+    ICON(),
+    DESCRIPTION(input),
     PREV_BUTTON(network),
     NEXT_BUTTON(status),
     {}
@@ -193,6 +266,11 @@ wizard_page_t *wizard_input(void)
  * Status
  */
 
+DESCRIPTION_FCN(status, N_("\
+Show the scan status.\
+"))
+
+
 wizard_page_t *wizard_status(void)
 {
   static const property_t props[] = {
@@ -210,6 +288,8 @@ wizard_page_t *wizard_status(void)
       .get      = hello_get_network,
       .set      = hello_set_network,
     },
+    ICON(),
+    DESCRIPTION(status),
     PREV_BUTTON(input),
     NEXT_BUTTON(mapping),
     {}
@@ -224,6 +304,11 @@ wizard_page_t *wizard_status(void)
  * Service Mapping
  */
 
+DESCRIPTION_FCN(mapping, N_("\
+Do the service mapping to channels.\
+"))
+
+
 wizard_page_t *wizard_mapping(void)
 {
   static const property_t props[] = {
@@ -234,6 +319,8 @@ wizard_page_t *wizard_mapping(void)
       .get      = hello_get_network,
       .set      = hello_set_network,
     },
+    ICON(),
+    DESCRIPTION(mapping),
     PREV_BUTTON(status),
     LAST_BUTTON(),
     {}